Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Merge updates from HEAD Note that this branch currently does not fully support the new {expand} syntax. Updates to TclEvalScriptTokens and TclCompileScriptTokens are still to come. |
|---|---|
| Timelines: | family | ancestors | descendants | both | dgp-refactor |
| Files: | files | file ages | folders |
| SHA1: |
beeeb45bbf5e097d636382d4b3ff2ac8 |
| User & Date: | dgp 2004-02-07 05:47:59.000 |
Context
|
2004-02-18
| ||
| 22:30 | Merge updates from HEAD. Ported support of {expand} syntax. check-in: 257d73b262 user: dgp tags: dgp-refactor | |
|
2004-02-07
| ||
| 05:47 | Merge updates from HEAD Note that this branch currently does not fully support the new {expand} syn... check-in: beeeb45bbf user: dgp tags: dgp-refactor | |
|
2003-10-16
| ||
| 02:29 | Merge updates from HEAD. check-in: 6eee5f37f0 user: dgp tags: dgp-refactor | |
Changes
Changes to ChangeLog.
1 2 3 4 5 6 7 | 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] | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 |
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@pobo.co>
* 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 #paragma 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]
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. [Tcl patch 858493]
2003-12-23 David Gravereaux <davygrvy@pobox.com>
* generic/tclAlloc.c: All uses of 'panic' (the macro) changed
* generic/tclBasic.c: to 'Tcl_Panic' (the function). The
* generic/tclBinary.c: #define of panic in tcl.h clearly states
* generic/tclCkalloc.c: it is deprecated in the comments.
* generic/tclCmdAH.c: [Patch 865264]
* 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.
This fixes Tcl Bug #839519.
* generic/tclPathObj.c: fixed Tcl_FSGetTranslatedPath
to always return properly refcounted path object.
This fixes Tcl 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
* doc/switch.n: using -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 [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
* tools/man2tcl.c: are 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. [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
* generic/tclCompile.c: and the bytecode compiler/execution engine
* generic/tclCompile.h: to 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.
* library/safe.tcl: In the test files lindex.test and lset.test,
* tests/cmdInfo.test: replaced use of [eval] to force direct
* tests/encoding.test: string evaluation with use of [testevalex]
* tests/execute.test: which more directly and robustly serves the
* tests/fCmd.test: same purpose.
* 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
* 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.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
* win/makefile.bc: adding a "root locale" to
* win/Makefile.in: the 'msgcat' package. Advanced
* win/Makefile.vc: msgcat version number to 1.4.
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]
|
| ︙ | ︙ |
Changes to doc/FileSystem.3.
1 2 3 4 5 6 | '\" '\" Copyright (c) 2001 Vincent Darley '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | '\" '\" Copyright (c) 2001 Vincent Darley '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" '\" RCS: @(#) $Id: FileSystem.3,v 1.32.4.4 2004/02/07 05:47:59 dgp Exp $ '\" .so man.macros .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 .SH SYNOPSIS |
| ︙ | ︙ | |||
159 160 161 162 163 164 165 | rename operation. .AP "CONST char" *encodingName in The encoding of the data stored in the file identified by \fBpathPtr\fR and to be evaluted. .AP "CONST char" *pattern in Only files or directories matching this pattern will be returned by \fBTcl_FSMatchInDirectory\fR. | | | | 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | rename operation. .AP "CONST char" *encodingName in The encoding of the data stored in the file identified by \fBpathPtr\fR and to be evaluted. .AP "CONST char" *pattern in Only files or directories matching this pattern will be returned by \fBTcl_FSMatchInDirectory\fR. .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' and 'mount' flags are properly handled. This parameter may be NULL. .AP Tcl_Interp *interp in Interpreter to use either for results, evaluation, or reporting error messages. .AP ClientData clientData in The native description of the path object to create. .AP Tcl_Obj *firstPtr in |
| ︙ | ︙ | |||
495 496 497 498 499 500 501 | \fBTcl_FSPathSeparator\fR returns the separator character to be used for most specific element of the path specified by pathPtr (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 | | > | | < > | > > > | | | | | | > | > > > | > > > | 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 | \fBTcl_FSPathSeparator\fR returns the separator character to be used for most specific element of the path specified by pathPtr (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 (which is allowed to have a refCount of zero), 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, 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. In particular, the returned object could be an element of the given list, so freeing the list might free the object prematurely if no refCount has been taken. .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 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. .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 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, 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, 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 |
| ︙ | ︙ | |||
558 559 560 561 562 563 564 | Returns NULL or a valid internal path representation. This internal 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. .PP | | | | | | > | | | | > > | | | | | | | | | > > > > > > | > > > | 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 | Returns NULL or a valid internal path representation. This internal 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. .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 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 \fBTcl_FSGetNormalizedPath\fR or \fBTcl_GetNativePath\fR are usually better functions to use for most purposes. .PP \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, \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 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. .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. .PP \fBTcl_FSGetNativePath\fR 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. 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 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. 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 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. |
| ︙ | ︙ | |||
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 | rather results should be added to the \fIresult\fR object given (which can be assumed to be a valid 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 result --- errors are only signaled for actual file or filesystem problems which may occur during the matching process. .SH 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'. .PP .CS | > > > > > > > > > > > > > | 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 | rather results should be added to the \fIresult\fR object given (which can be assumed to be a valid 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 result --- errors are only signaled for actual file or filesystem problems which may occur during the matching process. .PP There are two specific cases which it is important to handle correctly, both when \fItypes\fR is non-NULL. The two cases are when \fItypes->types & TCL_GLOB_TYPE_DIR\fR or \fItypes->types & TCL_GLOB_TYPE_MOUNT\fR are true (and in particular when the other flags are false). In the first of these cases, the function must list the contained directories. Tcl uses this to implement recursive globbing, so it is critical that filesystems implement directory matching correctly. In the second of these cases, with \fITCL_GLOB_TYPE_MOUNT\fR, the filesystem must list the mount points 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 .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'. .PP .CS |
| ︙ | ︙ | |||
1308 1309 1310 1311 1312 1313 1314 | 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 | | | | < | | | > > > > | 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 | 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 unload procedure will be called with the given Tcl_LoadHandle 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. .SH UNLOADFILEPROC .PP Function to unload a previously successfully loaded file. If load was implemented, then this should also be implemented, if there is any cleanup action required. .PP .CS |
| ︙ | ︙ |
Changes to doc/Hash.3.
1 2 3 4 5 6 7 | '\" '\" Copyright (c) 1989-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. '\" | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | '\" '\" Copyright (c) 1989-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. '\" '\" RCS: @(#) $Id: Hash.3,v 1.10.4.2 2004/02/07 05:47:59 dgp Exp $ '\" .so man.macros .TH Tcl_Hash 3 "" Tcl "Tcl Library Procedures" .BS .SH NAME Tcl_InitHashTable, Tcl_InitCustomHashTable, Tcl_InitObjHashTable, Tcl_DeleteHashTable, Tcl_CreateHashEntry, Tcl_DeleteHashEntry, Tcl_FindHashEntry, Tcl_GetHashValue, Tcl_SetHashValue, Tcl_GetHashKey, Tcl_FirstHashEntry, Tcl_NextHashEntry, Tcl_HashStats \- procedures to manage hash tables .SH SYNOPSIS |
| ︙ | ︙ | |||
252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
.PP
The \fIflags\fR member is 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.
.PP
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);
| > > > > > > > > > > > | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
.PP
The \fIflags\fR member is 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.
.VS 8.5 br
.IP \fBTCL_HASH_KEY_SYSTEM_HASH\fR 25
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.
.CS
typedef unsigned int (Tcl_HashKeyProc) (
Tcl_HashTable *\fItablePtr\fR,
VOID *\fIkeyPtr\fR);
|
| ︙ | ︙ |
Changes to doc/Panic.3.
1 2 3 4 | '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" | | | < < < < < < | 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 | '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" '\" RCS: @(#) $Id: Panic.3,v 1.3.14.1 2004/02/07 05:47:59 dgp Exp $ '\" .so man.macros .TH Tcl_Panic 3 8.4 Tcl "Tcl Library Procedures" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Tcl_Panic, Tcl_PanicVA, Tcl_SetPanicProc \- report fatal error and abort .SH SYNOPSIS .nf \fB#include <tcl.h>\fR .sp void \fBTcl_Panic\fR(\fIformat\fR, \fIarg\fR, \fIarg\fR, \fI...\fR) .sp void \fBTcl_PanicVA\fR(\fIformat\fR, \fIargList\fR) .sp void \fBTcl_SetPanicProc\fR(\fIpanicProc\fR) .sp .SH ARGUMENTS .AS Tcl_PanicProc *panicProc .AP "CONST char*" format in A printf-style format string. .AP "" arg in Arguments matching the format string. .AP va_list argList in |
| ︙ | ︙ | |||
90 91 92 93 94 95 96 | Although the primary callers of \fBTcl_Panic\fR are the procedures of the Tcl library, \fBTcl_Panic\fR is a public function and may be called by any extension or application that wishes to abort the process and 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 | | < < < < | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | Although the primary callers of \fBTcl_Panic\fR are the procedures of the Tcl library, \fBTcl_Panic\fR is a public function and may be called by any extension or application that wishes to abort the process and 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. .SH "SEE ALSO" abort(3), printf(3), exec(n), format(n) .SH KEYWORDS abort, fatal, error |
Changes to doc/ParseCmd.3.
1 2 3 4 5 6 | '\" '\" 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. '\" | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | '\" '\" 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. '\" '\" RCS: @(#) $Id: ParseCmd.3,v 1.11.2.1 2004/02/07 05:47:59 dgp Exp $ '\" .so man.macros .TH Tcl_ParseCommand 3 8.3 Tcl "Tcl Library Procedures" .BS .SH NAME Tcl_ParseCommand, Tcl_ParseExpr, Tcl_ParseBraces, Tcl_ParseQuotedString, Tcl_ParseVarName, Tcl_ParseVar, Tcl_FreeParse, Tcl_EvalTokens, Tcl_EvalTokensStandard \- parse Tcl scripts and expressions .SH SYNOPSIS |
| ︙ | ︙ | |||
282 283 284 285 286 287 288 289 290 291 292 293 294 295 | number of sub-tokens that make up the word, including sub-tokens of \fBTCL_TOKEN_VARIABLE\fR and \fBTCL_TOKEN_BS\fR tokens. .TP \fBTCL_TOKEN_SIMPLE_WORD\fR 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_TEXT\fR The token describes a range of literal text that is part of a word. The \fInumComponents\fR field is always 0. .TP \fBTCL_TOKEN_BS\fR The token describes a backslash sequence such as \fB\en\fR or \fB\e0xa3\fR. | > > > > > > > > > > | 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 |
number of sub-tokens that make up the word, including sub-tokens
of \fBTCL_TOKEN_VARIABLE\fR and \fBTCL_TOKEN_BS\fR tokens.
.TP
\fBTCL_TOKEN_SIMPLE_WORD\fR
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.
.VS 8.5
.TP
\fBTCL_TOKEN_EXPAND_WORD\fR
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{expand}\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
.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.
.TP
\fBTCL_TOKEN_BS\fR
The token describes a backslash sequence such as \fB\en\fR or \fB\e0xa3\fR.
|
| ︙ | ︙ | |||
371 372 373 374 375 376 377 | \fIx\fR, \fIy\fR, and \fIz\fR. The \fInumComponents\fR field for a \fBTCL_TOKEN_OPERATOR\fR token is always 0. .PP 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 | > > | > | > | 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 | \fIx\fR, \fIy\fR, and \fIz\fR. The \fInumComponents\fR field for a \fBTCL_TOKEN_OPERATOR\fR token is always 0. .PP 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 .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 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 Tcl_Parse structure always has type \fBTCL_TOKEN_SUB_EXPR\fR. It is followed by the sub-tokens that must be evaluated to produce the value of the expression. Only the token information in the Tcl_Parse structure |
| ︙ | ︙ |
Changes to doc/Tcl.n.
1 2 3 4 5 6 7 | '\" '\" 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. '\" | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | '\" '\" 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. '\" '\" RCS: @(#) $Id: Tcl.n,v 1.9.4.1 2004/02/07 05:47:59 dgp Exp $ '\" .so man.macros .TH Tcl n "8.5" Tcl "Tcl Built-In Commands" .BS .SH NAME Tcl \- Tool Command Language .SH SYNOPSIS Summary of Tcl language syntax. .BE .SH DESCRIPTION |
| ︙ | ︙ | |||
45 46 47 48 49 50 51 | 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. | > > > > > > > > > > | | > | | | 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 |
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.
.VS 8.5 br
.IP "[5] \fBArgument expansion.\fR"
If a word starts with the string ``{expand}'' followed by a
non-whitespace character, then the leading ``{expand}'' is removed
and the rest of the word is parsed and substituted as any other other
word. After substitution, the word is parsed again without
substitutions, and its words are added to the command being
substituted. For instance, ``cmd a {expand}{b c} d {expand}{e f}'' is
equivalent to ``cmd a b c d e f''.
.VE 8.5
.IP "[6] \fBBraces.\fR"
If the first character of a word is an open brace (``{'') and
rule [5] does not apply, then
the word is terminated by the matching close brace (``}'').
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
quoted with a backslash then it is not counted in locating the
matching close brace).
No substitutions are performed on the characters between the
braces except for backslash-newline substitutions described
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 "[7] \fBCommand substitution.\fR"
If a word contains an open bracket (``['') 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 (``]'').
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 "[8] \fBVariable substitution.\fR"
If a word contains a dollar-sign (``$'') then Tcl performs \fIvariable
substitution\fR: the dollar-sign and the following characters are
replaced in the word by the value of a variable.
Variable substitution may take any of the following forms:
.RS
.TP 15
\fB$\fIname\fR
|
| ︙ | ︙ | |||
98 99 100 101 102 103 104 |
\fB${\fIname\fB}\fR
\fIName\fR is the name of a scalar variable. It may contain any
characters whatsoever except for close braces.
.LP
There may be any number of variable substitutions in a single word.
Variable substitution is not performed on words enclosed in braces.
.RE
| | | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
\fB${\fIname\fB}\fR
\fIName\fR is the name of a scalar variable. It may contain any
characters whatsoever except for close braces.
.LP
There may be any number of variable substitutions in a single word.
Variable substitution is not performed on words enclosed in braces.
.RE
.IP "[9] \fBBackslash substitution.\fR"
If a backslash (``\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.
This allows characters such as double quotes, close brackets,
and dollar signs to be included in words without triggering
|
| ︙ | ︙ | |||
143 144 145 146 147 148 149 | 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 in braces or quotes. .TP 7 \e\e Backslash (``\e''). | < < | | | | > | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | 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 in braces or quotes. .TP 7 \e\e Backslash (``\e''). .TP 7 \e\fIooo\fR . The digits \fIooo\fR (one, two, or three of them) give an eight-bit octal value for the Unicode character that will be inserted. The upper bits of the Unicode character will be 0. .TP 7 \e\fBx\fIhh\fR . The hexadecimal digits \fIhh\fR give an eight-bit hexadecimal value for the Unicode character that will be inserted. Any number of hexadecimal digits may be present; however, all but the last two are ignored (the result is always a one-byte quantity). The upper bits of the Unicode character will be 0. .TP 7 \e\fBu\fIhhhh\fR . 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. .LP Backslash substitution is not performed on words enclosed in braces, except for backslash-newline as described above. .RE .IP "[10] \fBComments.\fR" If a hash character (``#'') 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 "[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 substitutions are performed on the value of the variable; the value is inserted into the word verbatim. If command substitution occurs then the nested command is processed entirely by the recursive call to the Tcl interpreter; no substitutions are performed before making the recursive call and no additional substitutions are performed on the result of the nested script. .RS .LP Substitutions take place from left to right, and each substitution is evaluated completely before attempting to evaluate the next. Thus, a sequence like .CS set y [set x 0][incr x][incr x] .CE will always set the variable \fIy\fR to the value, \fI012\fR. .RE .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. |
Changes to doc/clock.n.
1 2 3 4 5 6 7 8 9 10 11 12 | '\" '\" 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 '\" '\" 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. '\" | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | '\" '\" 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 '\" '\" 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. '\" '\" RCS: @(#) $Id: clock.n,v 1.12.2.1 2004/02/07 05:47:59 dgp Exp $ '\" .so man.macros .TH clock n 8.4 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME clock \- Obtain and manipulate time |
| ︙ | ︙ | |||
58 59 60 61 62 63 64 | speed up the clock frequency slightly until it's back in synchronization. For this reason, most Tcl programmers need never worry about such phenomena as leap seconds. .VE 8.5 .TP \fBclock format \fIclockValue\fR ?\fB\-format \fIstring\fR? ?\fB\-gmt \fIboolean\fR? Converts an integer time value, typically returned by | | | | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | speed up the clock frequency slightly until it's back in synchronization. For this reason, most Tcl programmers need never worry about such phenomena as leap seconds. .VE 8.5 .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: .RS .IP \fB%%\fR |
| ︙ | ︙ |
Changes to doc/file.n.
1 2 3 4 5 6 7 | '\" '\" 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. '\" | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | '\" '\" 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. '\" '\" RCS: @(#) $Id: file.n,v 1.24.2.2 2004/02/07 05:47:59 dgp Exp $ '\" .so man.macros .TH file n 8.3 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME file \- Manipulate file names and attributes |
| ︙ | ︙ | |||
99 100 101 102 103 104 105 | .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 | | > > | | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | .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 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, or overwrite a file with a directory will all result in errors even if \fI\-force\fR was specified. 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 delete \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIpathname\fR ?\fIpathname\fR ... ? |
| ︙ | ︙ | |||
202 203 204 205 206 207 208 | 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, seems to be the case with hard links, which look just like ordinary files), then an error is returned. . | | | | > | | | | > > > > > > | | | | | | | | 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | 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, seems to be the case with hard links, which look just like ordinary files), then an error is returned. . 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 (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 doesn't care what type of link is created. . 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". . 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, "~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), MacOS supports symbolic links and Windows NT/2000/XP (on NTFS drives) support symbolic directory links and hard file links. .TP \fBfile lstat \fIname varName\fR . 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 |
| ︙ | ︙ | |||
374 375 376 377 378 379 380 | see the manual entry for \fBstat\fR for details on the meanings of the values. The \fBtype\fR element gives the type of the file in the same form returned by the command \fBfile type\fR. This command returns an empty string. .TP \fBfile system \fIname\fR . | | | | | | | | < | | | 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 | see the manual entry for \fBstat\fR for details on the meanings of the values. The \fBtype\fR element gives the type of the file in the same form returned by the command \fBfile type\fR. This command returns an empty string. .TP \fBfile system \fIname\fR . 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 'native', and a second element which when given is a platform-specific type name for the file's system (e.g. 'NTFS', 'FAT', on Windows). 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. .TP \fBfile tail \fIname\fR . Returns all of the characters in the last filesystem component of \fIname\fR. Any trailing directory separator in \fIname\fR is ignored. |
| ︙ | ︙ |
Changes to doc/filename.n.
1 2 3 4 5 6 | '\" '\" 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. '\" | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | '\" '\" 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. '\" '\" RCS: @(#) $Id: filename.n,v 1.7.14.2 2004/02/07 05:47:59 dgp Exp $ '\" .so man.macros .TH filename n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME filename \- File name conventions supported by Tcl commands |
| ︙ | ︙ | |||
41 42 43 44 45 46 47 | .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 | | | | | | | | | | | | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | .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 Classic systems (i.e. with MacOS 9.x or older), 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. .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 |
| ︙ | ︙ | |||
96 97 98 99 100 101 102 | .TP 15 \fB\&../MyFile\fR Relative path to a file named \fBMyFile\fR in the folder above the current folder. .RE .TP \fBunix\fR | | | | | | | | > | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | .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 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. The following examples illustrate various forms of path names: .RS .TP 15 \fB/\fR Absolute path to the root directory. .TP 15 \fB/etc/passwd\fR Absolute path to the file named \fBpasswd\fR in the directory |
| ︙ | ︙ | |||
171 172 173 174 175 176 177 | 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 | | | | | | | | | > | | | | < | | | | | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | 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. This works on Unix, MacOS X and Windows (except very old releases). .PP The Classic Macintosh (OS 9 and older) platform and 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: |
| ︙ | ︙ | |||
211 212 213 214 215 216 217 | 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 | | > > > | 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | 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 in the results of 'file normalize'. Furthermore, a file name consisting only of dots '.........' or dots with trailing characters '.....abc' is illegal. .SH KEYWORDS current directory, absolute file name, relative file name, volume-relative file name, portability .SH "SEE ALSO" file(n), glob(n) |
Changes to doc/glob.n.
1 2 3 4 5 6 7 | '\" '\" 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. '\" | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | '\" '\" 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. '\" '\" RCS: @(#) $Id: glob.n,v 1.12.4.1 2004/02/07 05:47:59 dgp Exp $ '\" .so man.macros .TH glob n 8.3 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME glob \- Return names of files that match patterns |
| ︙ | ︙ | |||
145 146 147 148 149 150 151 152 153 154 155 156 157 158 | .LP The \fBglob\fR command differs from csh globbing in two ways. First, it does not sort its result list (use the \fBlsort\fR command if you want the list sorted). Second, \fBglob\fR only returns the names of files that actually exist; in csh no check for existence is made unless a pattern contains a ?, *, or [] construct. .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. | > > > > > > > | 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | .LP The \fBglob\fR command differs from csh globbing in two ways. First, it does not sort its result list (use the \fBlsort\fR command if you want the list sorted). Second, \fBglob\fR only returns the names of files that actually 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 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. |
| ︙ | ︙ |
Added doc/lassign.n.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
'\"
'\" 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.
'\"
'\" RCS: @(#) $Id: lassign.n,v 1.1.2.1 2004/02/07 05:47:59 dgp Exp $
'\"
.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 "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
|
Changes to doc/lset.n.
1 2 3 4 5 6 | '\" '\" 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. '\" | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | '\" '\" 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. '\" '\" RCS: @(#) $Id: lset.n,v 1.6.4.1 2004/02/07 05:47:59 dgp Exp $ '\" .so man.macros .TH lset n 8.4 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME lset \- Change an element in a list |
| ︙ | ︙ | |||
33 34 35 36 37 38 39 |
.CS
lset varName {} newValue
.CE
In this case, \fInewValue\fR replaces the old value of the variable
\fIvarName\fR.
.PP
When presented with a single index, the \fBlset\fR command
| | | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
.CS
lset varName {} newValue
.CE
In this case, \fInewValue\fR replaces the old value of the variable
\fIvarName\fR.
.PP
When presented with a single index, the \fBlset\fR command
treats the content of the \fIvarName\fR variable as a Tcl list.
It addresses the \fIindex\fR'th element in it
(0 refers to the first element of the list).
When interpreting the list, \fBlset\fR observes the same rules
concerning braces and quotes and backslashes as the Tcl command
interpreter; however, variable
substitution and command substitution do not occur.
The command constructs a new list in which the designated element is
|
| ︙ | ︙ |
Changes to doc/msgcat.n.
1 2 3 4 5 6 7 8 9 | '\" '\" Copyright (c) 1998 Mark Harrison. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" '\" SCCS: @(#) msgcat.n '\" .so man.macros | | | | 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 | '\" '\" Copyright (c) 1998 Mark Harrison. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" '\" SCCS: @(#) msgcat.n '\" .so man.macros .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 .sp \fBpackage require msgcat 1.4\fR .sp \fB::msgcat::mc \fIsrc-string\fR ?\fIarg arg ...\fR? .sp \fB::msgcat::mcmax ?\fIsrc-string src-string ...\fR? .sp \fB::msgcat::mclocale \fR?\fInewLocale\fR? .sp |
| ︙ | ︙ | |||
90 91 92 93 94 95 96 | Returns an ordered list of the locales preferred by the user, based on the user's language specification. The list is ordered from most specific to least preference. The list is derived from the current locale set in msgcat by \fBmsgcat::mclocale\fR, and cannot be set independently. For example, if the current locale is en_US_funky, then \fBmsgcat::mcpreferences\fR | > | > | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
Returns an ordered list of the locales preferred by
the user, based on the user's language specification.
The list is ordered from most specific to least
preference. The list is derived from the current
locale set in msgcat by \fBmsgcat::mclocale\fR, and
cannot be set independently. For example, if the
current locale is en_US_funky, then \fBmsgcat::mcpreferences\fR
.VS 1.4
returns \fB{en_US_funky en_US en {}}\fR.
.VE
.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
read in order, assuming a UTF-8 encoding. The file contents are
|
| ︙ | ︙ | |||
163 164 165 166 167 168 169 | 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''. .PP When a locale is specified by the user, a ``best match'' search is performed during string translation. For example, if a user specifies | > | > > | | | | 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | 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''. .PP When a locale is specified by the user, a ``best match'' search is performed during string translation. For example, if a user specifies .VS 1.4 en_GB_Funky, the locales ``en_GB_Funky'', ``en_GB'', ``en'' and ``'' (the empty string) .VE are searched in order until a matching translation string is found. If no translation string is available, then \fB::msgcat::unknown\fR is called. .SH "NAMESPACES AND MESSAGE CATALOGS" .PP Strings stored in the message catalog are stored relative to the namespace from which they were added. This allows multiple packages to use the same strings without fear of collisions with other packages. It also allows the |
| ︙ | ︙ | |||
232 233 234 235 236 237 238 239 240 241 242 243 244 245 | .IP [2] The message file name is a msgcat locale specifier (all lowercase) followed by ``.msg''. For example: .CS es.msg -- spanish en_gb.msg -- United Kingdom English .CE .IP [3] The file contains a series of calls to \fBmcset\fR and \fBmcmset\fR, setting the necessary translation strings for the language, likely enclosed in a \fBnamespace eval\fR so that all source strings are tied to the namespace of the package. For example, a short \fBes.msg\fR might contain: .CS | > > > > > > | 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 | .IP [2] The message file name is a msgcat locale specifier (all lowercase) followed by ``.msg''. For example: .CS es.msg -- spanish en_gb.msg -- United Kingdom English .CE .VS \fIException:\fR The message file for the root locale ``'' is called \fBROOT.msg\fR. This exception is made so as not to cause peculiar behavior, such as marking the message file as ``hidden'' on Unix file systems. .VE .IP [3] The file contains a series of calls to \fBmcset\fR and \fBmcmset\fR, setting the necessary translation strings for the language, likely enclosed in a \fBnamespace eval\fR so that all source strings are tied to the namespace of the package. For example, a short \fBes.msg\fR might contain: .CS |
| ︙ | ︙ |
Changes to doc/switch.n.
1 2 3 4 5 6 7 | '\" '\" 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. '\" | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | '\" '\" 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. '\" '\" RCS: @(#) $Id: switch.n,v 1.5.20.1 2004/02/07 05:47:59 dgp Exp $ '\" .so man.macros .TH switch n 7.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME switch \- Evaluate one of several scripts, depending on a given value |
| ︙ | ︙ | |||
44 45 46 47 48 49 50 51 52 53 54 55 56 57 | When matching \fIstring\fR to the patterns, use glob-style matching (i.e. the same as implemented by the \fBstring match\fR command). .TP 10 \fB\-regexp\fR When matching \fIstring\fR to the patterns, use regular expression matching (as described in the \fBre_syntax\fR reference page). .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. .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; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | When matching \fIstring\fR to the patterns, use glob-style matching (i.e. the same as implemented by the \fBstring match\fR command). .TP 10 \fB\-regexp\fR 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\-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. .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; |
| ︙ | ︙ |
Changes to doc/tclvars.n.
1 2 3 4 5 6 7 | '\" '\" 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. '\" | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | '\" '\" 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. '\" '\" RCS: @(#) $Id: tclvars.n,v 1.13.4.1 2004/02/07 05:47:59 dgp Exp $ '\" .so man.macros .TH tclvars n 8.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME tclvars \- Variables used by Tcl |
| ︙ | ︙ | |||
253 254 255 256 257 258 259 | .TP \fBbyteOrder\fR The native byte order of this machine: either \fBlittleEndian\fR or \fBbigEndian\fR. .VE .TP \fBdebug\fR | | | | | > | 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | .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 to a debug enabled C run-time. This variable will only exist on Windows, so extension writers can specify which package to load depending on the C run-time library that is in use. This is not an indication that this core contains symbols. .TP \fBmachine\fR The instruction set executed by this machine, such as \fBintel\fR, \fBPPC\fR, \fB68k\fR, or \fBsun4m\fR. On UNIX machines, this is the value returned by \fBuname -m\fR. .TP \fBos\fR |
| ︙ | ︙ |
Changes to generic/regcomp.c.
| ︙ | ︙ | |||
549 550 551 552 553 554 555 |
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 */
| > > > | | > | 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 |
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;
}
}
}
/* do the splits */
for (s = slist; s != NULL; s = s2) {
s2 = newstate(nfa);
copyouts(nfa, s, s2);
|
| ︙ | ︙ |
Changes to generic/tcl.decls.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # tcl.decls -- # # This file contains the declarations for all supported public # 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. # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # tcl.decls -- # # This file contains the declarations for all supported public # 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. # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: tcl.decls,v 1.97.2.5 2004/02/07 05:47:59 dgp Exp $ library tcl # Define the tcl interface with several sub interfaces: # tclPlat - platform specific public # tclInt - generic private # tclPlatInt - platform specific private |
| ︙ | ︙ | |||
1635 1636 1637 1638 1639 1640 1641 |
declare 461 generic {
Tcl_Obj* Tcl_FSSplitPath(Tcl_Obj* pathPtr, int *lenPtr)
}
declare 462 generic {
int Tcl_FSEqualPaths(Tcl_Obj* firstPtr, Tcl_Obj* secondPtr)
}
declare 463 generic {
| | | | | | | | | | 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 |
declare 461 generic {
Tcl_Obj* Tcl_FSSplitPath(Tcl_Obj* pathPtr, int *lenPtr)
}
declare 462 generic {
int Tcl_FSEqualPaths(Tcl_Obj* firstPtr, Tcl_Obj* secondPtr)
}
declare 463 generic {
Tcl_Obj* Tcl_FSGetNormalizedPath(Tcl_Interp *interp, Tcl_Obj* pathPtr)
}
declare 464 generic {
Tcl_Obj* Tcl_FSJoinToPath(Tcl_Obj *pathPtr, int objc,
Tcl_Obj *CONST objv[])
}
declare 465 generic {
ClientData Tcl_FSGetInternalRep(Tcl_Obj* pathPtr,
Tcl_Filesystem *fsPtr)
}
declare 466 generic {
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,
ClientData clientData)
}
declare 469 generic {
CONST char* Tcl_FSGetNativePath(Tcl_Obj* pathPtr)
}
declare 470 generic {
Tcl_Obj* Tcl_FSFileSystemInfo(Tcl_Obj* pathPtr)
}
declare 471 generic {
Tcl_Obj* Tcl_FSPathSeparator(Tcl_Obj* pathPtr)
}
declare 472 generic {
Tcl_Obj* Tcl_FSListVolumes(void)
}
declare 473 generic {
int Tcl_FSRegister(ClientData clientData, Tcl_Filesystem *fsPtr)
}
declare 474 generic {
int Tcl_FSUnregister(Tcl_Filesystem *fsPtr)
}
declare 475 generic {
ClientData Tcl_FSData(Tcl_Filesystem *fsPtr)
}
declare 476 generic {
CONST char* Tcl_FSGetTranslatedStringPath(Tcl_Interp *interp,
Tcl_Obj* pathPtr)
}
declare 477 generic {
Tcl_Filesystem* Tcl_FSGetFileSystemForPath(Tcl_Obj* pathPtr)
}
declare 478 generic {
Tcl_PathType Tcl_FSGetPathType(Tcl_Obj *pathPtr)
}
# New function due to TIP#49
declare 479 generic {
int Tcl_OutputBuffered(Tcl_Channel chan)
}
declare 480 generic {
void Tcl_FSMountsChanged(Tcl_Filesystem *fsPtr)
|
| ︙ | ︙ |
Changes to generic/tcl.h.
| ︙ | ︙ | |||
9 10 11 12 13 14 15 | * Copyright (c) 1994-1998 Sun Microsystems, Inc. * 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. * | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | * Copyright (c) 1994-1998 Sun Microsystems, Inc. * 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. * * RCS: @(#) $Id: tcl.h,v 1.157.2.6 2004/02/07 05:48:00 dgp Exp $ */ #ifndef _TCL #define _TCL /* * For C++ compilers, use extern "C" |
| ︙ | ︙ | |||
39 40 41 42 43 44 45 | * 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 * unix/configure.in (2 LOC Major, 2 LOC minor, 1 LOC patch) * win/configure.in (as above) * win/tcl.m4 (not patchlevel) | < | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | * 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 * unix/configure.in (2 LOC Major, 2 LOC minor, 1 LOC patch) * win/configure.in (as above) * win/tcl.m4 (not patchlevel) * win/makefile.bc (not patchlevel) 2 LOC * README (sections 0 and 2) * mac/README (2 LOC, not patchlevel) * macosx/Tcl.pbproj/project.pbxproj (not patchlevel) 2 LOC * win/README.binary (sections 0-4) * win/README (not patchlevel) (sections 0 and 2) * unix/tcl.spec (2 LOC Major/Minor, 1 LOC patch) |
| ︙ | ︙ | |||
1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 |
* 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.
*/
#define TCL_HASH_KEY_RANDOMIZE_HASH 0x1
/*
* Structure definition for the methods associated with a hash table
* key type.
*/
#define TCL_HASH_KEY_TYPE_VERSION 1
struct Tcl_HashKeyType {
| > > > > > | 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 |
* 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.
*/
#define TCL_HASH_KEY_TYPE_VERSION 1
struct Tcl_HashKeyType {
|
| ︙ | ︙ | |||
2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 | #define TCL_TOKEN_SIMPLE_WORD 2 #define TCL_TOKEN_TEXT 4 #define TCL_TOKEN_BS 8 #define TCL_TOKEN_COMMAND 16 #define TCL_TOKEN_VARIABLE 32 #define TCL_TOKEN_SUB_EXPR 64 #define TCL_TOKEN_OPERATOR 128 /* * 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 | > | 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 | #define TCL_TOKEN_SIMPLE_WORD 2 #define TCL_TOKEN_TEXT 4 #define TCL_TOKEN_BS 8 #define TCL_TOKEN_COMMAND 16 #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. */ #define TCL_PARSE_SUCCESS 0 |
| ︙ | ︙ | |||
2230 2231 2232 2233 2234 2235 2236 |
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;
| > > | | | | < < | | | | > | | | | | | | > | 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 |
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;
#ifndef TCL_NO_DEPRECATED
/*
* Deprecated Tcl procedures:
*/
# define Tcl_EvalObj(interp,objPtr) \
Tcl_EvalObjEx((interp),(objPtr),0)
# 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
/*
* 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
|
| ︙ | ︙ |
Changes to generic/tclAlloc.c.
| ︙ | ︙ | |||
11 12 13 14 15 16 17 | * Copyright (c) 1998-1999 by Scriptics Corporation. * * 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. * | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | * Copyright (c) 1998-1999 by Scriptics Corporation. * * 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. * * RCS: @(#) $Id: tclAlloc.c,v 1.16.4.1 2004/02/07 05:48:00 dgp Exp $ */ /* * Windows and Unix use an alternative allocator when building with threads * that has significantly reduced lock contention. */ |
| ︙ | ︙ | |||
136 137 138 139 140 141 142 | */ static unsigned int nmalloc[NBUCKETS+1]; #include <stdio.h> #endif #if defined(DEBUG) || defined(RCHECK) | | | | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | */ static unsigned int nmalloc[NBUCKETS+1]; #include <stdio.h> #endif #if defined(DEBUG) || defined(RCHECK) #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) #endif /* * Prototypes for functions used only in this file. |
| ︙ | ︙ |
Changes to generic/tclBasic.c.
| ︙ | ︙ | |||
9 10 11 12 13 14 15 | * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 2001, 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. * | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 2001, 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. * * RCS: @(#) $Id: tclBasic.c,v 1.82.2.6 2004/02/07 05:48:00 dgp Exp $ */ #include "tclInt.h" #include "tclCompile.h" #ifndef TCL_GENERIC_ONLY # include "tclPort.h" #endif |
| ︙ | ︙ | |||
110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
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,
| > > | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
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},
{"lassign", (Tcl_CmdProc *) NULL, Tcl_LassignObjCmd,
TclCompileLassignCmd, 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,
|
| ︙ | ︙ | |||
289 290 291 292 293 294 295 |
/*
* Panic if someone updated the CallFrame structure without
* also updating the Tcl_CallFrame structure (or vice versa).
*/
if (sizeof(Tcl_CallFrame) != sizeof(CallFrame)) {
/*NOTREACHED*/
| | | 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 |
/*
* Panic if someone updated the CallFrame structure without
* also updating the Tcl_CallFrame structure (or vice versa).
*/
if (sizeof(Tcl_CallFrame) != sizeof(CallFrame)) {
/*NOTREACHED*/
Tcl_Panic("Tcl_CallFrame and CallFrame are not the same size");
}
/*
* 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.
*/
|
| ︙ | ︙ | |||
367 368 369 370 371 372 373 |
Tcl_IncrRefCount(iPtr->emptyObjPtr);
iPtr->resultSpace[0] = 0;
iPtr->globalNsPtr = NULL; /* force creation of global ns below */
iPtr->globalNsPtr = (Namespace *) Tcl_CreateNamespace(interp, "",
(ClientData) NULL, (Tcl_NamespaceDeleteProc *) NULL);
if (iPtr->globalNsPtr == NULL) {
| | | 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 |
Tcl_IncrRefCount(iPtr->emptyObjPtr);
iPtr->resultSpace[0] = 0;
iPtr->globalNsPtr = NULL; /* force creation of global ns below */
iPtr->globalNsPtr = (Namespace *) Tcl_CreateNamespace(interp, "",
(ClientData) NULL, (Tcl_NamespaceDeleteProc *) NULL);
if (iPtr->globalNsPtr == NULL) {
Tcl_Panic("Tcl_CreateInterp: can't create global namespace");
}
/*
* Initialize support for code compilation and execution. We call
* TclCreateExecEnv after initializing namespaces since it tries to
* reference a Tcl variable (it links to the Tcl "tcl_traceExec"
* variable).
|
| ︙ | ︙ | |||
441 442 443 444 445 446 447 |
cmdInfoPtr++) {
int new;
Tcl_HashEntry *hPtr;
if ((cmdInfoPtr->proc == (Tcl_CmdProc *) NULL)
&& (cmdInfoPtr->objProc == (Tcl_ObjCmdProc *) NULL)
&& (cmdInfoPtr->compileProc == (CompileProc *) NULL)) {
| | | 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 |
cmdInfoPtr++) {
int new;
Tcl_HashEntry *hPtr;
if ((cmdInfoPtr->proc == (Tcl_CmdProc *) NULL)
&& (cmdInfoPtr->objProc == (Tcl_ObjCmdProc *) NULL)
&& (cmdInfoPtr->compileProc == (CompileProc *) NULL)) {
Tcl_Panic("Tcl_CreateInterp: builtin command with NULL string and object command procs and a NULL compile proc\n");
}
hPtr = Tcl_CreateHashEntry(&iPtr->globalNsPtr->cmdTable,
cmdInfoPtr->name, &new);
if (new) {
cmdPtr = (Command *) ckalloc(sizeof(Command));
cmdPtr->hPtr = hPtr;
|
| ︙ | ︙ | |||
489 490 491 492 493 494 495 |
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) {
| | | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 |
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) {
Tcl_Panic("Tcl_CreateInterp: Tcl_CreateMathFunc incorrectly registered '%s'", builtinFuncPtr->name);
return NULL;
}
mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
mathFuncPtr->builtinFuncIndex = i;
i++;
}
iPtr->flags |= EXPR_INITIALIZED;
|
| ︙ | ︙ | |||
971 972 973 974 975 976 977 |
ResolverScheme *resPtr, *nextResPtr;
/*
* Punt if there is an error in the Tcl_Release/Tcl_Preserve matchup.
*/
if (iPtr->numLevels > 0) {
| | | | 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 |
ResolverScheme *resPtr, *nextResPtr;
/*
* Punt if there is an error in the Tcl_Release/Tcl_Preserve matchup.
*/
if (iPtr->numLevels > 0) {
Tcl_Panic("DeleteInterpProc called with active evals");
}
/*
* The interpreter should already be marked deleted; otherwise how
* did we get here?
*/
if (!(iPtr->flags & DELETED)) {
Tcl_Panic("DeleteInterpProc called on interpreter not marked deleted");
}
TclHandleFree(iPtr->handle);
/*
* Dismantle everything in the global namespace except for the
* "errorInfo" and "errorCode" variables. These remain until the
|
| ︙ | ︙ | |||
1360 1361 1362 1363 1364 1365 1366 |
* 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,
| | | 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 |
* 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 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;
}
|
| ︙ | ︙ |
Changes to generic/tclBinary.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* * tclBinary.c -- * * This file contains the implementation of the "binary" Tcl built-in * command and the Tcl binary data object. * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* * tclBinary.c -- * * This file contains the implementation of the "binary" Tcl built-in * command and the Tcl binary data object. * * 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. * * RCS: @(#) $Id: tclBinary.c,v 1.13.4.1 2004/02/07 05:48:00 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" #include <math.h> /* |
| ︙ | ︙ | |||
57 58 59 60 61 62 63 | 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)); | | > | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | 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)); /* * 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 |
| ︙ | ︙ | |||
260 261 262 263 264 265 266 |
int length; /* Length of the array of bytes, which must
* be >= 0. */
{
Tcl_ObjType *typePtr;
ByteArray *byteArrayPtr;
if (Tcl_IsShared(objPtr)) {
| | | 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
int length; /* Length of the array of bytes, which must
* be >= 0. */
{
Tcl_ObjType *typePtr;
ByteArray *byteArrayPtr;
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("Tcl_SetByteArrayObj called with shared object");
}
typePtr = objPtr->typePtr;
if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
(*typePtr->freeIntRepProc)(objPtr);
}
Tcl_InvalidateStringRep(objPtr);
|
| ︙ | ︙ | |||
342 343 344 345 346 347 348 |
Tcl_SetByteArrayLength(objPtr, length)
Tcl_Obj *objPtr; /* The ByteArray object. */
int length; /* New length for internal byte array. */
{
ByteArray *byteArrayPtr, *newByteArrayPtr;
if (Tcl_IsShared(objPtr)) {
| | | 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
Tcl_SetByteArrayLength(objPtr, length)
Tcl_Obj *objPtr; /* The ByteArray object. */
int length; /* New length for internal byte array. */
{
ByteArray *byteArrayPtr, *newByteArrayPtr;
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("Tcl_SetObjLength called with shared object");
}
if (objPtr->typePtr != &tclByteArrayType) {
SetByteArrayFromAny(NULL, objPtr);
}
byteArrayPtr = GET_BYTEARRAY(objPtr);
if (length > byteArrayPtr->allocated) {
|
| ︙ | ︙ | |||
747 748 749 750 751 752 753 |
} else {
offset = count;
}
break;
}
default: {
errorString = str;
| | | 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 |
} else {
offset = count;
}
break;
}
default: {
errorString = str;
goto badField;
}
}
}
if (offset > length) {
length = offset;
}
if (length == 0) {
|
| ︙ | ︙ | |||
1046 1047 1048 1049 1050 1051 1052 |
}
switch (cmd) {
case 'a':
case 'A': {
unsigned char *src;
if (arg >= objc) {
| | < < | 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 |
}
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;
|
| ︙ | ︙ | |||
1082 1083 1084 1085 1086 1087 1088 |
}
}
valuePtr = Tcl_NewByteArrayObj(src, size);
resultPtr = Tcl_ObjSetVar2(interp, objv[arg],
NULL, valuePtr, TCL_LEAVE_ERR_MSG);
arg++;
if (resultPtr == NULL) {
| | < < | < < | 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 |
}
}
valuePtr = Tcl_NewByteArrayObj(src, size);
resultPtr = Tcl_ObjSetVar2(interp, objv[arg],
NULL, valuePtr, TCL_LEAVE_ERR_MSG);
arg++;
if (resultPtr == NULL) {
DeleteScanNumberCache(numberCachePtr);
Tcl_DecrRefCount(valuePtr); /* unneeded */
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;
|
| ︙ | ︙ | |||
1141 1142 1143 1144 1145 1146 1147 |
}
}
resultPtr = Tcl_ObjSetVar2(interp, objv[arg],
NULL, valuePtr, TCL_LEAVE_ERR_MSG);
arg++;
if (resultPtr == NULL) {
| | < < | < < | 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 |
}
}
resultPtr = Tcl_ObjSetVar2(interp, objv[arg],
NULL, valuePtr, TCL_LEAVE_ERR_MSG);
arg++;
if (resultPtr == NULL) {
DeleteScanNumberCache(numberCachePtr);
Tcl_DecrRefCount(valuePtr); /* unneeded */
return TCL_ERROR;
}
offset += (count + 7 ) / 8;
break;
}
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;
} else {
if (count == BINARY_NOCOUNT) {
count = 1;
|
| ︙ | ︙ | |||
1202 1203 1204 1205 1206 1207 1208 |
}
}
resultPtr = Tcl_ObjSetVar2(interp, objv[arg],
NULL, valuePtr, TCL_LEAVE_ERR_MSG);
arg++;
if (resultPtr == NULL) {
| | < < | 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 |
}
}
resultPtr = Tcl_ObjSetVar2(interp, objv[arg],
NULL, valuePtr, TCL_LEAVE_ERR_MSG);
arg++;
if (resultPtr == NULL) {
DeleteScanNumberCache(numberCachePtr);
Tcl_DecrRefCount(valuePtr); /* unneeded */
return TCL_ERROR;
}
offset += (count + 1) / 2;
break;
}
case 'c': {
|
| ︙ | ︙ | |||
1242 1243 1244 1245 1246 1247 1248 |
unsigned char *src;
size = sizeof(double);
/* fall through */
scanNumber:
if (arg >= objc) {
| | < < | 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 |
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,
|
| ︙ | ︙ | |||
1277 1278 1279 1280 1281 1282 1283 |
offset += count*size;
}
resultPtr = Tcl_ObjSetVar2(interp, objv[arg],
NULL, valuePtr, TCL_LEAVE_ERR_MSG);
arg++;
if (resultPtr == NULL) {
| | < < | 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 |
offset += count*size;
}
resultPtr = Tcl_ObjSetVar2(interp, objv[arg],
NULL, valuePtr, TCL_LEAVE_ERR_MSG);
arg++;
if (resultPtr == NULL) {
DeleteScanNumberCache(numberCachePtr);
Tcl_DecrRefCount(valuePtr); /* unneeded */
return TCL_ERROR;
}
break;
}
case 'x': {
if (count == BINARY_NOCOUNT) {
|
| ︙ | ︙ | |||
1310 1311 1312 1313 1314 1315 1316 |
} else {
offset -= count;
}
break;
}
case '@': {
if (count == BINARY_NOCOUNT) {
| | < < | < < | | < < | > | 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 |
} 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.
*/
done:
Tcl_ResetResult(interp);
Tcl_SetLongObj(Tcl_GetObjResult(interp), arg - 4);
DeleteScanNumberCache(numberCachePtr);
break;
}
}
return TCL_OK;
badValue:
Tcl_ResetResult(interp);
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "expected ", errorString,
" string but got \"", errorValue, "\" instead", NULL);
return TCL_ERROR;
badCount:
errorString = "missing count for \"@\" field specifier";
goto error;
badIndex:
errorString = "not enough arguments for all format specifiers";
goto error;
badField:
{
Tcl_UniChar ch;
char buf[TCL_UTF_MAX + 1];
Tcl_UtfToUniChar(errorString, &ch);
buf[Tcl_UniCharToUtf(ch, buf)] = '\0';
Tcl_AppendResult(interp, "bad field specifier \"", buf, "\"", NULL);
return TCL_ERROR;
|
| ︙ | ︙ | |||
1663 1664 1665 1666 1667 1668 1669 | * 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. */ | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 |
* 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);
Tcl_IncrRefCount(objPtr);
Tcl_SetHashValue(hPtr, (ClientData) objPtr);
return objPtr;
}
}
/*
* Do not cache wide values; they are already too large to
* use as keys.
*/
case 'w':
uwvalue = ((Tcl_WideUInt) buffer[0])
| (((Tcl_WideUInt) buffer[1]) << 8)
| (((Tcl_WideUInt) buffer[2]) << 16)
| (((Tcl_WideUInt) buffer[3]) << 24)
| (((Tcl_WideUInt) buffer[4]) << 32)
| (((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])
| (((Tcl_WideUInt) buffer[6]) << 8)
| (((Tcl_WideUInt) buffer[5]) << 16)
| (((Tcl_WideUInt) buffer[4]) << 24)
| (((Tcl_WideUInt) buffer[3]) << 32)
| (((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);
}
}
return NULL;
}
/*
*----------------------------------------------------------------------
*
* DeleteScanNumberCache --
*
* Deletes the hash table acting as a scan number cache.
*
* Results:
* None
*
* Side effects:
* Decrements the reference counts of the objects in the cache.
*
*----------------------------------------------------------------------
*/
static void
DeleteScanNumberCache(numberCachePtr)
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;
if (numberCachePtr == NULL) {
return;
}
hEntry = Tcl_FirstHashEntry(numberCachePtr, &search);
while (hEntry != NULL) {
register Tcl_Obj *value = (Tcl_Obj *) Tcl_GetHashValue(hEntry);
if (value != NULL) {
Tcl_DecrRefCount(value);
}
hEntry = Tcl_NextHashEntry(&search);
}
Tcl_DeleteHashTable(numberCachePtr);
}
|
Changes to generic/tclCkalloc.c.
| ︙ | ︙ | |||
9 10 11 12 13 14 15 | * 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. * * This code contributed by Karl Lehenbauer and Mark Diekhans * | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | * 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. * * This code contributed by Karl Lehenbauer and Mark Diekhans * * RCS: @(#) $Id: tclCkalloc.c,v 1.19.4.1 2004/02/07 05:48:00 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" #define FALSE 0 #define TRUE 1 |
| ︙ | ︙ | |||
227 228 229 230 231 232 233 |
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,
memHeaderP->file, memHeaderP->line);
| | | 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
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,
memHeaderP->file, memHeaderP->line);
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;
|
| ︙ | ︙ | |||
250 251 252 253 254 255 256 |
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",
memHeaderP->length, memHeaderP->file,
memHeaderP->line);
| | | 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
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",
memHeaderP->length, memHeaderP->file,
memHeaderP->line);
Tcl_Panic("Memory validation failure");
}
if (nukeGuards) {
memset ((char *) memHeaderP->low_guard, 0, LOW_GUARD_SIZE);
memset ((char *) hiPtr, 0, HIGH_GUARD_SIZE);
}
|
| ︙ | ︙ | |||
374 375 376 377 378 379 380 |
Tcl_ValidateAllMemory (file, line);
result = (struct mem_header *) TclpAlloc((unsigned)size +
sizeof(struct mem_header) + HIGH_GUARD_SIZE);
if (result == NULL) {
fflush(stdout);
TclDumpMemoryInfo(stderr);
| | | 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 |
Tcl_ValidateAllMemory (file, line);
result = (struct mem_header *) TclpAlloc((unsigned)size +
sizeof(struct mem_header) + HIGH_GUARD_SIZE);
if (result == NULL) {
fflush(stdout);
TclDumpMemoryInfo(stderr);
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.
*/
|
| ︙ | ︙ | |||
535 536 537 538 539 540 541 | /* *---------------------------------------------------------------------- * * Tcl_DbCkfree - debugging ckfree * * Verify that the low and high guards are intact, and if so | | | 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 | /* *---------------------------------------------------------------------- * * Tcl_DbCkfree - debugging ckfree * * 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 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 |
| ︙ | ︙ | |||
1006 1007 1008 1009 1010 1011 1012 |
* 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
*/
if ((result == NULL) && size) {
| | | | 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 |
* 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
*/
if ((result == NULL) && 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;
{
char *result;
result = (char *) TclpAlloc(size);
if ((result == NULL) && size) {
fflush(stdout);
Tcl_Panic("unable to alloc %u bytes, %s line %d", size, file, line);
}
return result;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
1081 1082 1083 1084 1085 1086 1087 |
unsigned int size;
{
char *result;
result = TclpRealloc(ptr, size);
if ((result == NULL) && size) {
| | | | 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 |
unsigned int size;
{
char *result;
result = TclpRealloc(ptr, size);
if ((result == NULL) && 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;
{
char *result;
result = (char *) TclpRealloc(ptr, size);
if ((result == NULL) && size) {
fflush(stdout);
Tcl_Panic("unable to realloc %u bytes, %s line %d", size, file, line);
}
return result;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ |
Changes to generic/tclClock.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* * 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. * * Copyright 1991-1995 Karl Lehenbauer and Mark Diekhans. * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* * 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. * * Copyright 1991-1995 Karl Lehenbauer and Mark Diekhans. * 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. * * RCS: @(#) $Id: tclClock.c,v 1.23.2.1 2004/02/07 05:48:00 dgp Exp $ */ #include "tcl.h" #include "tclInt.h" #include "tclPort.h" /* |
| ︙ | ︙ | |||
64 65 66 67 68 69 70 |
int clickType = 2;
int dummy;
unsigned long baseClock, clockVal;
long zone;
Tcl_Obj *baseObjPtr = NULL;
char *scanStr;
Tcl_Time now; /* Current time */
| | | | > | | | | > | > > | > > < | | < | | | | < | | | < < | | | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
int clickType = 2;
int dummy;
unsigned long baseClock, clockVal;
long zone;
Tcl_Obj *baseObjPtr = NULL;
char *scanStr;
Tcl_Time now; /* Current time */
static CONST char *switches[] = {
"clicks", "format", "scan", "seconds", (char *) NULL
};
enum command {
COMMAND_CLICKS, COMMAND_FORMAT, COMMAND_SCAN, COMMAND_SECONDS
};
static CONST char *clicksSwitches[] = {
"-milliseconds", "-microseconds", (char*) NULL
};
static CONST char *formatSwitches[] = {
"-format", "-gmt", (char *) NULL
};
static CONST char *scanSwitches[] = {
"-base", "-gmt", (char *) NULL
};
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;
}
switch ((enum command) index) {
case COMMAND_CLICKS: { /* clicks */
if (objc == 3) {
if (Tcl_GetIndexFromObj(interp, objv[2], clicksSwitches,
"option", 0, &clickType) != TCL_OK) {
return TCL_ERROR;
}
} else if (objc != 2) {
Tcl_WrongNumArgs(interp, 2, objv, "?-milliseconds?");
return TCL_ERROR;
}
switch (clickType) {
case 0: /* milliseconds */
Tcl_GetTime(&now);
Tcl_SetWideIntObj(resultPtr,
((Tcl_WideInt) now.sec * 1000 + now.usec / 1000));
break;
case 1: /* microseconds */
Tcl_GetTime(&now);
Tcl_SetWideIntObj(resultPtr,
((Tcl_WideInt) now.sec * 1000000 + now.usec));
break;
case 2: /* native clicks */
Tcl_SetWideIntObj(resultPtr, (Tcl_WideInt) TclpGetClicks());
break;
}
return TCL_OK;
}
case COMMAND_FORMAT: /* format */
if ((objc < 3) || (objc > 7)) {
wrongFmtArgs:
Tcl_WrongNumArgs(interp, 2, objv,
"clockval ?-format string? ?-gmt boolean?");
return TCL_ERROR;
}
if (Tcl_GetLongFromObj(interp, objv[2], (long*) &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;
}
|
| ︙ | ︙ | |||
300 301 302 303 304 305 306 |
* 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.
*/
| | | | 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 |
* 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.
*/
Tcl_MutexLock(&clockMutex);
if (useGMT) {
CONST char *varValue;
varValue = Tcl_GetVar2(interp, "env", "TZ", TCL_GLOBAL_ONLY);
if (varValue != NULL) {
savedTZEnv = strcpy(ckalloc(strlen(varValue) + 1), varValue);
} else {
savedTZEnv = NULL;
}
Tcl_SetVar2(interp, "env", "TZ", "GMT", TCL_GLOBAL_ONLY);
savedTimeZone = timezone;
timezone = 0;
tzset();
}
#endif
tclockVal = 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.
*/
for (bufSize = 1, p = format; *p != '\0'; p++) {
if (*p == '%') {
|
| ︙ | ︙ | |||
341 342 343 344 345 346 347 |
Tcl_DStringSetLength(&buffer, bufSize);
/* If we haven't locked the clock mutex up above, lock it now. */
#if defined(HAVE_TM_ZONE) || defined(WIN32)
Tcl_MutexLock(&clockMutex);
#endif
| | | | < | 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 |
Tcl_DStringSetLength(&buffer, bufSize);
/* If we haven't locked the clock mutex up above, lock it now. */
#if defined(HAVE_TM_ZONE) || defined(WIN32)
Tcl_MutexLock(&clockMutex);
#endif
result = TclpStrftime(buffer.string, (unsigned int) bufSize, format,
timeDataPtr, useGMT);
#if defined(HAVE_TM_ZONE) || defined(WIN32)
Tcl_MutexUnlock(&clockMutex);
#endif
#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
if (result == 0) {
/*
* 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.
*/
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
"bad format string \"", format, "\"", (char *) NULL);
return TCL_ERROR;
}
Tcl_SetStringObj(Tcl_GetObjResult(interp), buffer.string, -1);
Tcl_DStringFree(&buffer);
return TCL_OK;
}
|
Changes to generic/tclCmdAH.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* * 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. * * 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. * | | | | | | 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 | /* * 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. * * 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. * * RCS: @(#) $Id: tclCmdAH.c,v 1.33.2.2 2004/02/07 05:48:00 dgp Exp $ */ #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 *pathPtr, int mode)); static int GetStatBuf _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *pathPtr, Tcl_FSStatProc *statProc, Tcl_StatBuf *statPtr)); static char * GetTypeFromMode _ANSI_ARGS_((int mode)); static int StoreStatData _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *varName, Tcl_StatBuf *statPtr)); /* *---------------------------------------------------------------------- * * Tcl_BreakObjCmd -- * * This procedure is invoked to process the "break" Tcl command. |
| ︙ | ︙ | |||
859 860 861 862 863 864 865 |
"pathtype", "readable", "readlink", "rename",
"rootname", "separator", "size", "split",
"stat", "system",
"tail", "type", "volumes", "writable",
(char *) NULL
};
enum options {
| | | | | | | | | | | | | 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 |
"pathtype", "readable", "readlink", "rename",
"rootname", "separator", "size", "split",
"stat", "system",
"tail", "type", "volumes", "writable",
(char *) 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_PATHTYPE, FCMD_READABLE, FCMD_READLINK, FCMD_RENAME,
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;
}
if (Tcl_GetIndexFromObj(interp, objv[1], fileOptions, "option", 0,
&index) != TCL_OK) {
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;
}
|
| ︙ | ︙ | |||
925 926 927 928 929 930 931 |
if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
return TCL_ERROR;
}
}
Tcl_SetLongObj(Tcl_GetObjResult(interp), (long) buf.st_atime);
return TCL_OK;
}
| | < | < | < | < | > | | < | > > | < < | < | | > > | | | > | | | | | 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 |
if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
return TCL_ERROR;
}
}
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?");
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 = 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_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_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);
return TCL_OK;
}
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_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;
|
| ︙ | ︙ | |||
1062 1063 1064 1065 1066 1067 1068 |
if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) {
return TCL_ERROR;
}
/* Create link from source to target */
contents = Tcl_FSLink(objv[index], objv[index+1], linkAction);
if (contents == NULL) {
/*
| | > > > > > > > > > > > > > | > | > > > > > > | | | | > | 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 |
if (Tcl_FSConvertToPathType(interp, objv[index]) != 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 three 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) {
/*
* 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 \"",
Tcl_GetString(objv[index]),
"\": no such file or directory",
(char *) NULL);
} else {
Tcl_AppendResult(interp,
"could not create new link \"",
Tcl_GetString(objv[index]),
"\": 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;
|
| ︙ | ︙ | |||
1109 1110 1111 1112 1113 1114 1115 | * 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); } return TCL_OK; } | | < < | | | 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 |
* 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);
}
return TCL_OK;
}
case FCMD_LSTAT: {
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) {
return TCL_ERROR;
}
return StoreStatData(interp, objv[3], &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;
}
|
| ︙ | ︙ | |||
1167 1168 1169 1170 1171 1172 1173 |
if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
return TCL_ERROR;
}
}
Tcl_SetLongObj(Tcl_GetObjResult(interp), (long) buf.st_mtime);
return TCL_OK;
}
| | < | | > > > | | 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 |
if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
return TCL_ERROR;
}
}
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) {
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;
}
fileName = Tcl_FSGetNormalizedPath(interp, objv[2]);
if (fileName == 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;
|
| ︙ | ︙ | |||
1226 1227 1228 1229 1230 1231 1232 | #else value = (geteuid() == buf.st_uid); #endif } Tcl_SetBooleanObj(Tcl_GetObjResult(interp), value); return TCL_OK; } | | | | | | | | | | | | < | < | | 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 |
#else
value = (geteuid() == buf.st_uid);
#endif
}
Tcl_SetBooleanObj(Tcl_GetObjResult(interp), value);
return TCL_OK;
}
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;
case FCMD_READABLE:
if (objc != 3) {
goto only3Args;
}
return CheckAccess(interp, objv[2], R_OK);
case FCMD_READLINK: {
Tcl_Obj *contents;
if (objc != 3) {
goto only3Args;
}
if (Tcl_FSConvertToPathType(interp, objv[2]) != TCL_OK) {
|
| ︙ | ︙ | |||
1273 1274 1275 1276 1277 1278 1279 | Tcl_PosixError(interp), (char *) NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, contents); Tcl_DecrRefCount(contents); return TCL_OK; } | | < | < | | < | | > > < | < | | | | | | | | | | < | | > > > > > > > > > > > > | | | > | < < | | > | < | < < < < < < < < < < | | | < < < | < < < < < < < < < < < | < < | | | > | | < | < | 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 |
Tcl_PosixError(interp), (char *) 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;
}
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;
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;
}
case FCMD_SPLIT: {
Tcl_Obj *res;
if (objc != 3) {
goto only3Args;
}
res = Tcl_FSSplitPath(objv[2], NULL);
if (res == NULL) {
if (interp != NULL) {
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
"could not read \"", Tcl_GetString(objv[2]),
"\": no such file or directory",
(char *) NULL);
}
return TCL_ERROR;
} else {
Tcl_SetObjResult(interp, res);
return TCL_OK;
}
}
case FCMD_STAT: {
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;
}
return StoreStatData(interp, objv[3], &buf);
}
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;
}
}
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;
} else {
Tcl_SetObjResult(interp, dirPtr);
Tcl_DecrRefCount(dirPtr);
return TCL_OK;
}
}
case FCMD_TYPE: {
Tcl_StatBuf buf;
if (objc != 3) {
goto only3Args;
}
if (GetStatBuf(interp, objv[2], Tcl_FSLstat, &buf) != TCL_OK) {
return TCL_ERROR;
}
Tcl_SetStringObj(Tcl_GetObjResult(interp),
GetTypeFromMode((unsigned short) buf.st_mode), -1);
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;
}
|
| ︙ | ︙ | |||
1467 1468 1469 1470 1471 1472 1473 | * Side effects: * None. * *--------------------------------------------------------------------------- */ static int | | | | | | 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 |
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
static int
CheckAccess(interp, pathPtr, mode)
Tcl_Interp *interp; /* Interp for status return. Must not be
* NULL. */
Tcl_Obj *pathPtr; /* Name of file to check. */
int mode; /* Attribute to check; passed as argument to
* access(). */
{
int value;
if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {
value = 0;
} else {
value = (Tcl_FSAccess(pathPtr, mode) == 0);
}
Tcl_SetBooleanObj(Tcl_GetObjResult(interp), value);
return TCL_OK;
}
/*
|
| ︙ | ︙ | |||
1507 1508 1509 1510 1511 1512 1513 | * Side effects: * None. * *--------------------------------------------------------------------------- */ static int | | | | | | | 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 |
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
static int
GetStatBuf(interp, pathPtr, statProc, statPtr)
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
* calling (*statProc)(). */
{
int status;
if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {
return TCL_ERROR;
}
status = (*statProc)(pathPtr, statPtr);
if (status < 0) {
if (interp != NULL) {
Tcl_AppendResult(interp, "could not read \"",
Tcl_GetString(pathPtr), "\": ",
Tcl_PosixError(interp), (char *) NULL);
}
return TCL_ERROR;
}
return TCL_OK;
}
|
| ︙ | ︙ | |||
1556 1557 1558 1559 1560 1561 1562 |
*
*----------------------------------------------------------------------
*/
static int
StoreStatData(interp, varName, statPtr)
Tcl_Interp *interp; /* Interpreter for error reports. */
| | < > > > | < < | 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 |
*
*----------------------------------------------------------------------
*/
static int
StoreStatData(interp, varName, statPtr)
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 *field = Tcl_NewObj();
Tcl_Obj *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 so we
* don't have to make assumptions that might go wrong later.
*/
#define STORE_ARY(fieldName, object) \
Tcl_SetStringObj(field, (fieldName), -1); \
value = (object); \
if (Tcl_ObjSetVar2(interp,varName,field,value,TCL_LEAVE_ERR_MSG) == NULL) { \
Tcl_DecrRefCount(field); \
Tcl_DecrRefCount(value); \
return TCL_ERROR; \
}
Tcl_IncrRefCount(field);
STORE_ARY("dev", Tcl_NewLongObj((long)statPtr->st_dev));
/*
* 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...
*/
|
| ︙ | ︙ | |||
1602 1603 1604 1605 1606 1607 1608 |
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));
#undef STORE_ARY
| < | 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 |
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));
#undef STORE_ARY
Tcl_DecrRefCount(field);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
1889 1890 1891 1892 1893 1894 1895 |
* 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) {
| | | | 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 |
* 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) {
Tcl_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) {
Tcl_Panic("Tcl_ForeachObjCmd: could not reconvert value list %d to a list object\n", i);
}
for (v = 0; v < varcList[i]; v++) {
int k = index[i]++;
Tcl_Obj *valuePtr, *varValuePtr;
int isEmptyObj = 0;
|
| ︙ | ︙ |
Changes to generic/tclCmdIL.c.
| ︙ | ︙ | |||
11 12 13 14 15 16 17 | * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 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. * | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 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. * * RCS: @(#) $Id: tclCmdIL.c,v 1.50.2.4 2004/02/07 05:48:00 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" #include "tclRegexp.h" /* |
| ︙ | ︙ | |||
2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 |
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_LindexObjCmd --
*
* This object-based procedure is invoked to process the "lindex" Tcl
* command. See the user documentation for details on what it does.
*
* Results:
* A standard Tcl object result.
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 |
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_LassignObjCmd --
*
* 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.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
Tcl_LassignObjCmd(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_Obj *valueObj; /* Value to assign to variable, as read from
* the list object or created in the emptyObj
* variable. */
Tcl_Obj *emptyObj = NULL; /* If non-NULL, an empty object created for
* being assigned to variables once we have
* run out of values from the list object. */
Tcl_Obj **listObjv; /* The contents of the list. */
int listObjc; /* The length of the list. */
int i;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv, "list varname ?varname ...?");
return TCL_ERROR;
}
/*
* First assign values out of the list to variables.
*/
for (i=0 ; i+2<objc ; i++) {
/*
* We do this each time round the loop because that is robust
* against shimmering nasties.
*/
if (Tcl_ListObjIndex(interp, objv[1], i, &valueObj) != TCL_OK) {
return TCL_ERROR;
}
if (valueObj == NULL) {
if (emptyObj == NULL) {
TclNewObj(emptyObj);
Tcl_IncrRefCount(emptyObj);
}
valueObj = emptyObj;
}
/*
* Make sure the reference count for the value being assigned
* is greater than one (other reference minimally in the list)
* so we can't get hammered by shimmering.
*/
Tcl_IncrRefCount(valueObj);
if (Tcl_ObjSetVar2(interp, objv[i+2], NULL, valueObj,
TCL_LEAVE_ERR_MSG) == NULL) {
Tcl_DecrRefCount(valueObj);
if (emptyObj != NULL) {
Tcl_DecrRefCount(emptyObj);
}
return TCL_ERROR;
}
Tcl_DecrRefCount(valueObj);
}
if (emptyObj != NULL) {
Tcl_DecrRefCount(emptyObj);
}
/*
* Now place a list of any values left over into the interpreter
* result.
*
* First, figure out how many values were not assigned by getting
* the length of the list. Note that I do not expect this
* operation to fail.
*/
if (Tcl_ListObjGetElements(interp, objv[1],
&listObjc, &listObjv) != TCL_OK) {
return TCL_ERROR;
}
if (listObjc > objc-2) {
/*
* OK, there were left-overs. Make a list of them and slap
* that back in the interpreter result.
*/
Tcl_SetObjResult(interp,
Tcl_NewListObj(listObjc - objc + 2, listObjv + objc - 2));
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_LindexObjCmd --
*
* This object-based procedure is invoked to process the "lindex" Tcl
* command. See the user documentation for details on what it does.
*
* Results:
* A standard Tcl object result.
|
| ︙ | ︙ | |||
2646 2647 2648 2649 2650 2651 2652 |
int
Tcl_LrepeatObjCmd(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. */
{
| | | 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 |
int
Tcl_LrepeatObjCmd(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. */
{
int elementCount, i, result;
Tcl_Obj **dataArray;
/*
* Check arguments for legality:
* lrepeat posInt value ?value ...?
*/
|
| ︙ | ︙ | |||
2681 2682 2683 2684 2685 2686 2687 2688 |
objv += 2;
/*
* Create workspace array large enough to hold each init value
* elementCount times. Note that we don't bother with stack
* allocation for this, as we expect this function to be used
* mainly when stack allocation would be inappropriate anyway.
*
| > > > > < < > > > > > > > > > | > > > > > > | > > | > > > > > > > | > | | | > | < | 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 |
objv += 2;
/*
* Create workspace array large enough to hold each init value
* elementCount times. Note that we don't bother with stack
* allocation for this, as we expect this function to be used
* mainly when stack allocation would be inappropriate anyway.
* 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.
*
* We allocate using attemptckalloc() because if we ask for
* something big but can't get it, we've still got a high chance
* of having a proper failover strategy. If *that* fails to get
* memory, Tcl_Panic() will happen just a few lines lower...
*/
if ((unsigned)elementCount > INT_MAX/sizeof(Tcl_Obj *)/objc) {
Tcl_AppendResult(interp, "overflow of maximum list length", NULL);
return TCL_ERROR;
}
dataArray = (Tcl_Obj **)
attemptckalloc(elementCount * objc * sizeof(Tcl_Obj *));
if (dataArray == NULL) {
Tcl_AppendResult(interp, "insufficient memory to create list", NULL);
return TCL_ERROR;
}
/*
* 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];
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++) {
dataArray[k++] = objv[j];
}
}
}
/*
* Build the result list, clean up and return.
*/
Tcl_SetObjResult(interp, TclNewListObjDirect(elementCount*objc,dataArray));
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_LreplaceObjCmd --
|
| ︙ | ︙ |
Changes to generic/tclCmdMZ.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /* * 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). * * 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. * | > | | 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 | /* * 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). * * 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. * * RCS: @(#) $Id: tclCmdMZ.c,v 1.90.2.6 2004/02/07 05:48:00 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" #include "tclRegexp.h" /* |
| ︙ | ︙ | |||
839 840 841 842 843 844 845 |
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. */
{
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 |
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. */
{
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;
}
code = TclProcessReturn(interp, code, level, returnOpts);
if (explicitResult) {
Tcl_SetObjResult(interp, objv[objc-1]);
}
return code;
}
/*
*----------------------------------------------------------------------
*
* 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:
* When the return code is TCL_ERROR, the values of ::errorInfo
* and ::errorCode may be updated.
*
*----------------------------------------------------------------------
*/
int
TclProcessReturn(interp, code, level, returnOpts)
Tcl_Interp *interp;
int code;
int level;
Tcl_Obj *returnOpts;
{
Interp *iPtr = (Interp *) interp;
Tcl_Obj *valuePtr;
/* Store the merged return options */
if (iPtr->returnOpts != returnOpts) {
Tcl_DecrRefCount(iPtr->returnOpts);
iPtr->returnOpts = returnOpts;
Tcl_IncrRefCount(iPtr->returnOpts);
}
if (level == 0) {
if (code == TCL_ERROR) {
valuePtr = NULL;
Tcl_DictObjGet(NULL, iPtr->returnOpts,
iPtr->returnErrorinfoKey, &valuePtr);
|
| ︙ | ︙ | |||
978 979 980 981 982 983 984 |
valuePtr, TCL_GLOBAL_ONLY);
iPtr->flags |= ERROR_CODE_SET;
}
}
} else {
code = TCL_RETURN;
}
| > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 |
valuePtr, TCL_GLOBAL_ONLY);
iPtr->flags |= ERROR_CODE_SET;
}
}
} else {
code = TCL_RETURN;
}
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(interp, objc, objv, optionsPtrPtr, codePtr, levelPtr)
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 */
{
Interp *iPtr = (Interp *) interp;
int code, level, size;
Tcl_Obj *valuePtr;
Tcl_Obj *returnOpts = Tcl_DuplicateObj(iPtr->defaultReturnOpts);
for (; objc > 1; objv += 2, objc -= 2) {
int optLen;
CONST char *opt = Tcl_GetStringFromObj(objv[0], &optLen);
int compareLen;
CONST char *compare =
Tcl_GetStringFromObj(iPtr->returnOptionsKey, &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_AppendStringsToObj(Tcl_GetObjResult(interp), "bad ",
compare, " value: expected dictionary but got \"",
Tcl_GetString(objv[1]), "\"", (char *) NULL);
return TCL_ERROR;
}
while (!done) {
Tcl_DictObjPut(NULL, returnOpts, keyPtr, valuePtr);
Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done);
}
valuePtr = NULL;
Tcl_DictObjGet(NULL, returnOpts, iPtr->returnOptionsKey, &valuePtr);
if (valuePtr != NULL) {
dict = valuePtr;
Tcl_DictObjRemove(NULL, returnOpts, iPtr->returnOptionsKey);
goto nestedOptions;
}
} else {
Tcl_DictObjPut(NULL, returnOpts, objv[0], objv[1]);
}
}
/* Check for bogus -code value */
Tcl_DictObjGet(NULL, returnOpts, iPtr->returnCodeKey, &valuePtr);
if (TCL_ERROR == Tcl_GetIntFromObj(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_AppendStringsToObj(Tcl_GetObjResult(interp),
"bad completion code \"",
Tcl_GetString(valuePtr),
"\": must be ok, error, return, break, ",
"continue, or an integer", (char *) NULL);
return TCL_ERROR;
}
/* Have a legal string value for a return code; convert to integer */
Tcl_DictObjPut(NULL, returnOpts,
iPtr->returnCodeKey, Tcl_NewIntObj(code));
}
/* Check for bogus -level value */
Tcl_DictObjGet(NULL, returnOpts, iPtr->returnLevelKey, &valuePtr);
if (TCL_ERROR == Tcl_GetIntFromObj(NULL, valuePtr, &level) || (level < 0)) {
/* Value is not a legal level */
Tcl_ResetResult(interp);
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
"bad -level value: expected non-negative integer but got \"",
Tcl_GetString(valuePtr), "\"", (char *) NULL);
return TCL_ERROR;
}
/*
* Convert [return -code return -level X] to
* [return -code ok -level X+1]
*/
if (code == TCL_RETURN) {
level++;
Tcl_DictObjPut(NULL, returnOpts,
iPtr->returnLevelKey, Tcl_NewIntObj(level));
Tcl_DictObjPut(NULL, returnOpts,
iPtr->returnCodeKey, Tcl_NewIntObj(TCL_OK));
}
/*
* Check if we just have the default options. If so, use them.
* A dictionary equality test would be more robust, but seems
* tricky, to say the least.
*/
Tcl_DictObjSize(NULL, returnOpts, &size);
if (size == 2 && code == TCL_OK && level == 1) {
Tcl_DecrRefCount(returnOpts);
returnOpts = iPtr->defaultReturnOpts;
}
if (codePtr != NULL) {
*codePtr = code;
}
if (levelPtr != NULL) {
*levelPtr = level;
}
if ((optionsPtrPtr == NULL) && (returnOpts != iPtr->defaultReturnOpts)) {
/* not passing back the options (?!), so clean them up */
Tcl_DecrRefCount(returnOpts);
} else {
*optionsPtrPtr = returnOpts;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_SourceObjCmd --
*
|
| ︙ | ︙ | |||
2510 2511 2512 2513 2514 2515 2516 |
break;
}
case SUBST_NOVARS: {
flags &= ~TCL_SUBST_VARIABLES;
break;
}
default: {
| | | 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 |
break;
}
case SUBST_NOVARS: {
flags &= ~TCL_SUBST_VARIABLES;
break;
}
default: {
Tcl_Panic("Tcl_SubstObjCmd: bad option index to SubstOptions");
}
}
}
if (i != (objc-1)) {
Tcl_WrongNumArgs(interp, 1, objv,
"?-nobackslashes? ?-nocommands? ?-novariables? string");
return TCL_ERROR;
|
| ︙ | ︙ | |||
2557 2558 2559 2560 2561 2562 2563 |
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. */
{
| | | > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > | 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 |
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. */
{
int i, j, index, mode, matched, result, splitObjs, numMatchesSaved;
char *string, *pattern;
Tcl_Obj *stringObj, *indexVarObj, *matchVarObj;
Tcl_Obj *CONST *savedObjv = objv;
Tcl_RegExp regExpr = NULL;
static CONST char *options[] = {
"-exact", "-glob", "-indexvar", "-matchvar", "-regexp", "--",
NULL
};
enum options {
OPT_EXACT, OPT_GLOB, OPT_INDEXV, OPT_MATCHV, OPT_REGEXP, OPT_LAST
};
mode = OPT_EXACT;
indexVarObj = NULL;
matchVarObj = NULL;
numMatchesSaved = 0;
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;
}
/*
* Check for TIP#75 options specifying the variables to write
* regexp information into.
*/
if (index == OPT_INDEXV) {
i++;
if (i == objc) {
Tcl_AppendResult(interp,
"missing variable name argument to -indexvar option",
(char *) NULL);
return TCL_ERROR;
}
indexVarObj = objv[i];
numMatchesSaved = -1;
} else if (index == OPT_MATCHV) {
i++;
if (i == objc) {
Tcl_AppendResult(interp,
"missing variable name argument to -matchvar option",
(char *) NULL);
return TCL_ERROR;
}
matchVarObj = objv[i];
numMatchesSaved = -1;
} else {
mode = index;
}
}
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", (char *) NULL);
return TCL_ERROR;
}
if (matchVarObj != NULL && mode != OPT_REGEXP) {
Tcl_AppendResult(interp,
"-matchvar option requires -regexp option", (char *) NULL);
return TCL_ERROR;
}
stringObj = objv[i];
objc -= i + 1;
objv += i + 1;
/*
|
| ︙ | ︙ | |||
2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 |
pattern = Tcl_GetString(objv[i]);
matched = 0;
if ((i == objc - 2)
&& (*pattern == 'd')
&& (strcmp(pattern, "default") == 0)) {
matched = 1;
} else {
switch (mode) {
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | < | | > > > > > | > | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 |
pattern = Tcl_GetString(objv[i]);
matched = 0;
if ((i == objc - 2)
&& (*pattern == 'd')
&& (strcmp(pattern, "default") == 0)) {
Tcl_Obj *emptyObj = NULL;
matched = 1;
/*
* 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) {
Tcl_DecrRefCount(emptyObj);
return TCL_ERROR;
}
}
if (matchVarObj != NULL) {
if (emptyObj == NULL) {
TclNewObj(emptyObj);
}
if (Tcl_ObjSetVar2(interp, matchVarObj, NULL, emptyObj,
TCL_LEAVE_ERR_MSG) == NULL) {
if (indexVarObj == NULL) {
Tcl_DecrRefCount(emptyObj);
}
return TCL_ERROR;
}
}
numMatchesSaved = 0;
} 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:
regExpr = Tcl_GetRegExpFromObj(interp, objv[i],
TCL_REG_ADVANCED);
if (regExpr == NULL) {
return TCL_ERROR;
}
matched = Tcl_RegExpExecObj(interp, regExpr, stringObj, 0,
numMatchesSaved, 0);
if (matched < 0) {
return TCL_ERROR;
}
break;
}
}
if (matched == 0) {
continue;
}
/*
* 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]
*/
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 (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);
}
}
if (indexVarObj != NULL) {
if (Tcl_ObjSetVar2(interp, indexVarObj, NULL, indicesObj,
TCL_LEAVE_ERR_MSG) == NULL) {
Tcl_DecrRefCount(indicesObj);
/*
* 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) {
Tcl_DecrRefCount(matchesObj);
/*
* 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 "-".
*/
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 (strcmp(Tcl_GetString(objv[j]), "-") != 0) {
break;
}
}
result = Tcl_EvalObjEx(interp, objv[j], 0);
if (result == TCL_ERROR) {
|
| ︙ | ︙ |
Changes to generic/tclCompCmds.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/*
* tclCompCmds.c --
*
* 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.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/*
* tclCompCmds.c --
*
* 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.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id: tclCompCmds.c,v 1.49.2.2 2004/02/07 05:48:00 dgp Exp $
*/
#include "tclInt.h"
#include "tclCompile.h"
/*
* Prototypes for procedures defined later in this file:
|
| ︙ | ︙ | |||
83 84 85 86 87 88 89 |
Tcl_ResetResult(interp);
Tcl_AppendToObj(Tcl_GetObjResult(interp),
"wrong # args: should be \"append varName ?value value ...?\"",
-1);
return TCL_ERROR;
} else if (numWords == 2) {
/*
| | | 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
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
*/
return TclCompileSetCmd(interp, parsePtr, envPtr);
} else if (numWords > 3) {
/*
* APPEND instructions currently only handle one value
*/
return TCL_OUT_LINE_COMPILE;
|
| ︙ | ︙ | |||
288 289 290 291 292 293 294 |
}
}
/*
* We will compile the catch command. Emit a beginCatch instruction at
* the start of the catch body: the subcommand it controls.
*/
| | | 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
}
}
/*
* We will compile the catch command. Emit a beginCatch instruction at
* the start of the catch body: the subcommand it controls.
*/
envPtr->exceptDepth++;
envPtr->maxExceptDepth =
TclMax(envPtr->exceptDepth, envPtr->maxExceptDepth);
range = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr);
TclEmitInstInt4(INST_BEGIN_CATCH4, range, envPtr);
/*
|
| ︙ | ︙ | |||
322 323 324 325 326 327 328 |
if (code != TCL_OK) {
code = TCL_OUT_LINE_COMPILE;
goto done;
}
envPtr->exceptArrayPtr[range].numCodeBytes =
(envPtr->codeNext - envPtr->codeStart) - startOffset;
| | | 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 |
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"
* result, and jump around the "error case" code.
*/
if (localIndex != -1) {
|
| ︙ | ︙ | |||
367 368 369 370 371 372 373 |
/*
* Update the target of the jump after the "no errors" code, then emit
* an endCatch instruction at the end of the catch command.
*/
if (TclFixupForwardJumpToHere(envPtr, &jumpFixup, 127)) {
| | | 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 |
/*
* Update the target of the jump after the "no errors" code, then emit
* an endCatch instruction at the end of the catch command.
*/
if (TclFixupForwardJumpToHere(envPtr, &jumpFixup, 127)) {
Tcl_Panic("TclCompileCatchCmd: bad jump distance %d\n",
(envPtr->codeNext - envPtr->codeStart) - jumpFixup.codeOffset);
}
TclEmitOpcode(INST_END_CATCH, envPtr);
done:
envPtr->currStackDepth = savedStackDepth + 1;
envPtr->exceptDepth--;
|
| ︙ | ︙ | |||
554 555 556 557 558 559 560 |
if (code == TCL_ERROR) {
Tcl_AddObjErrorInfo(interp,
"\n (\"for\" initial command)", -1);
}
goto done;
}
TclEmitOpcode(INST_POP, envPtr);
| | | 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 |
if (code == TCL_ERROR) {
Tcl_AddObjErrorInfo(interp,
"\n (\"for\" initial command)", -1);
}
goto done;
}
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).
* "for start cond next body" produces then:
* start
* goto A
* B: body : bodyCodeOffset
|
| ︙ | ︙ | |||
627 628 629 630 631 632 633 |
jumpDist = testCodeOffset - jumpEvalCondFixup.codeOffset;
if (TclFixupForwardJump(envPtr, &jumpEvalCondFixup, jumpDist, 127)) {
bodyCodeOffset += 3;
nextCodeOffset += 3;
testCodeOffset += 3;
}
| | | | | | 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 |
jumpDist = testCodeOffset - jumpEvalCondFixup.codeOffset;
if (TclFixupForwardJump(envPtr, &jumpEvalCondFixup, jumpDist, 127)) {
bodyCodeOffset += 3;
nextCodeOffset += 3;
testCodeOffset += 3;
}
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;
}
envPtr->currStackDepth = savedStackDepth + 1;
jumpDist = (envPtr->codeNext - envPtr->codeStart) - 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.
*/
envPtr->exceptArrayPtr[bodyRange].codeOffset = bodyCodeOffset;
envPtr->exceptArrayPtr[bodyRange].continueOffset = nextCodeOffset;
envPtr->exceptArrayPtr[nextRange].codeOffset = nextCodeOffset;
envPtr->exceptArrayPtr[bodyRange].breakOffset =
envPtr->exceptArrayPtr[nextRange].breakOffset =
(envPtr->codeNext - envPtr->codeStart);
/*
* The for command's result is an empty string.
*/
envPtr->currStackDepth = savedStackDepth;
TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
code = TCL_OK;
|
| ︙ | ︙ | |||
773 774 775 776 777 778 779 |
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;
}
| | | | 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 |
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);
/*
* 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.
*/
|
| ︙ | ︙ | |||
843 844 845 846 847 848 849 |
/*create*/ 1, /*flags*/ VAR_SCALAR, procPtr);
if (loopIndex == 0) {
firstValueTemp = tempVar;
}
}
loopCtTemp = TclFindCompiledLocal(NULL, /*nameChars*/ 0,
/*create*/ 1, /*flags*/ VAR_SCALAR, procPtr);
| | | 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 |
/*create*/ 1, /*flags*/ VAR_SCALAR, procPtr);
if (loopIndex == 0) {
firstValueTemp = tempVar;
}
}
loopCtTemp = TclFindCompiledLocal(NULL, /*nameChars*/ 0,
/*create*/ 1, /*flags*/ VAR_SCALAR, procPtr);
/*
* Create and initialize the ForeachInfo and ForeachVarList data
* structures describing this command. Then create a AuxData record
* pointing to the ForeachInfo structure.
*/
infoPtr = (ForeachInfo *) ckalloc((unsigned)
|
| ︙ | ︙ | |||
876 877 878 879 880 881 882 |
infoIndex = TclCreateAuxData((ClientData) infoPtr, &tclForeachInfoType, envPtr);
/*
* Evaluate then store each value list in the associated temporary.
*/
range = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr);
| | | 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 |
infoIndex = TclCreateAuxData((ClientData) infoPtr, &tclForeachInfoType, envPtr);
/*
* 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)) {
if ((i%2 == 0) && (i > 0)) {
code = TclCompileTokens(interp, tokenPtr+1,
tokenPtr->numComponents, envPtr);
|
| ︙ | ︙ | |||
904 905 906 907 908 909 910 |
}
/*
* Initialize the temporary var that holds the count of loop iterations.
*/
TclEmitInstInt4(INST_FOREACH_START4, infoIndex, envPtr);
| | | | 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 |
}
/*
* Initialize the temporary var that holds the count of loop iterations.
*/
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);
TclEmitInstInt4(INST_FOREACH_STEP4, infoIndex, envPtr);
TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup);
/*
* Inline compile the loop body.
*/
envPtr->exceptArrayPtr[range].codeOffset =
(envPtr->codeNext - envPtr->codeStart);
code = TclCompileCmdWord(interp, bodyTokenPtr+1,
|
| ︙ | ︙ | |||
936 937 938 939 940 941 942 |
}
goto done;
}
envPtr->exceptArrayPtr[range].numCodeBytes =
(envPtr->codeNext - envPtr->codeStart)
- envPtr->exceptArrayPtr[range].codeOffset;
TclEmitOpcode(INST_POP, envPtr);
| | | 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 |
}
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
* ensures that we won't have to replace this jump if we later need to
* replace the ifFalse jump with a 4 byte jump.
*/
|
| ︙ | ︙ | |||
985 986 987 988 989 990 991 |
/*
* Set the loop's break target.
*/
envPtr->exceptArrayPtr[range].breakOffset =
(envPtr->codeNext - envPtr->codeStart);
| | | 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 |
/*
* Set the loop's break target.
*/
envPtr->exceptArrayPtr[range].breakOffset =
(envPtr->codeNext - envPtr->codeStart);
/*
* The foreach command's result is an empty string.
*/
envPtr->currStackDepth = savedStackDepth;
TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
envPtr->currStackDepth = savedStackDepth + 1;
|
| ︙ | ︙ | |||
1039 1040 1041 1042 1043 1044 1045 |
* auxiliary data to duplicate. */
{
register ForeachInfo *srcPtr = (ForeachInfo *) clientData;
ForeachInfo *dupPtr;
register ForeachVarList *srcListPtr, *dupListPtr;
int numLists = srcPtr->numLists;
int numVars, i, j;
| | | | 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 |
* auxiliary data to duplicate. */
{
register ForeachInfo *srcPtr = (ForeachInfo *) clientData;
ForeachInfo *dupPtr;
register ForeachVarList *srcListPtr, *dupListPtr;
int numLists = srcPtr->numLists;
int numVars, i, j;
dupPtr = (ForeachInfo *) ckalloc((unsigned)
(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));
dupListPtr->numVars = numVars;
for (j = 0; j < numVars; j++) {
|
| ︙ | ︙ | |||
1202 1203 1204 1205 1206 1207 1208 | goto done; } /* * Compile the test expression then emit the conditional jump * around the "then" part. */ | | | | 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 |
goto done;
}
/*
* 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.
*/
Tcl_Obj *boolObj = Tcl_NewStringObj(testTokenPtr[1].start,
testTokenPtr[1].size);
Tcl_IncrRefCount(boolObj);
code = Tcl_GetBooleanFromObj(NULL, boolObj, &boolVal);
Tcl_DecrRefCount(boolObj);
if (code == TCL_OK) {
/*
|
| ︙ | ︙ | |||
1301 1302 1303 1304 1305 1306 1307 |
}
if (realCond) {
/*
* Jump to the end of the "if" command. Both jumpFalseFixupArray and
* jumpEndFixupArray are indexed by "jumpIndex".
*/
| | | | | 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 |
}
if (realCond) {
/*
* 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]));
/*
* 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.
*/
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
*/
|
| ︙ | ︙ | |||
1383 1384 1385 1386 1387 1388 1389 |
}
}
if (compileScripts) {
/*
* Compile the else command body.
*/
| | | | 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 |
}
}
if (compileScripts) {
/*
* Compile the else command body.
*/
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;
}
}
/*
* 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;
|
| ︙ | ︙ | |||
1421 1422 1423 1424 1425 1426 1427 |
TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
}
}
/*
* Fix the unconditional jumps to the end of the "if" command.
*/
| | | 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 |
TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
}
}
/*
* 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 */
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.
|
| ︙ | ︙ | |||
1443 1444 1445 1446 1447 1448 1449 |
jumpFalseDist += 3;
TclStoreInt1AtPtr(jumpFalseDist, (ifFalsePc + 1));
} else if (opCode == INST_JUMP_FALSE4) {
jumpFalseDist = TclGetInt4AtPtr(ifFalsePc + 1);
jumpFalseDist += 3;
TclStoreInt4AtPtr(jumpFalseDist, (ifFalsePc + 1));
} else {
| | | 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 |
jumpFalseDist += 3;
TclStoreInt1AtPtr(jumpFalseDist, (ifFalsePc + 1));
} else if (opCode == INST_JUMP_FALSE4) {
jumpFalseDist = TclGetInt4AtPtr(ifFalsePc + 1);
jumpFalseDist += 3;
TclStoreInt4AtPtr(jumpFalseDist, (ifFalsePc + 1));
} else {
Tcl_Panic("TclCompileIfCmd: unexpected opcode updating ifFalse jump");
}
}
}
/*
* Free the jumpFixupArray array if malloc'ed storage was used.
*/
|
| ︙ | ︙ | |||
1558 1559 1560 1561 1562 1563 1564 |
goto done;
}
}
} else { /* no incr amount given so use 1 */
haveImmValue = 1;
immValue = 1;
}
| | | 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 |
goto done;
}
}
} else { /* no incr amount given so use 1 */
haveImmValue = 1;
immValue = 1;
}
/*
* Emit the instruction to increment the variable.
*/
if (simpleVarName) {
if (isScalar) {
if (localIndex >= 0) {
|
| ︙ | ︙ | |||
1602 1603 1604 1605 1606 1607 1608 |
} else { /* non-simple variable name */
if (haveImmValue) {
TclEmitInstInt1(INST_INCR_STK_IMM, immValue, envPtr);
} else {
TclEmitOpcode(INST_INCR_STK, envPtr);
}
}
| | | 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 |
} else { /* non-simple variable name */
if (haveImmValue) {
TclEmitInstInt1(INST_INCR_STK_IMM, immValue, envPtr);
} else {
TclEmitOpcode(INST_INCR_STK, envPtr);
}
}
done:
return code;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 |
done:
return code;
}
/*
*----------------------------------------------------------------------
*
* TclCompileLindexCmd --
*
* Procedure called to compile the "lindex" 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,
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 |
done:
return code;
}
/*
*----------------------------------------------------------------------
*
* TclCompileLassignCmd --
*
* 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, indicating that the command should
* be compiled "out of line" by emitting code to invoke its command
* procedure (Tcl_LassignObjCmd) at runtime, which enforces in correct
* error handling.
*
* Side effects:
* Instructions are added to envPtr to execute the "lassign" command
* at runtime.
*
*----------------------------------------------------------------------
*/
int
TclCompileLassignCmd(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 *tokenPtr;
int simpleVarName, isScalar, localIndex, numWords, code, idx;
numWords = parsePtr->numWords;
/*
* Check for command syntax error, but we'll punt that to runtime
*/
if (numWords < 3) {
return TCL_OUT_LINE_COMPILE;
}
/*
* Generate code to push list being taken apart by [lassign].
*/
tokenPtr = parsePtr->tokenPtr + (parsePtr->tokenPtr->numComponents + 1);
if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
TclEmitPush(TclRegisterNewLiteral(envPtr,
tokenPtr[1].start, tokenPtr[1].size), envPtr);
} else {
code = TclCompileTokens(interp, tokenPtr+1,
tokenPtr->numComponents, envPtr);
if (code != TCL_OK) {
return code;
}
}
/*
* Generate code to assign values from the list to variables
*/
for (idx=0 ; idx<numWords-2 ; idx++) {
tokenPtr += tokenPtr->numComponents + 1;
/*
* Generate the next variable name
*/
code = TclPushVarName(interp, tokenPtr, envPtr, TCL_CREATE_VAR,
&localIndex, &simpleVarName, &isScalar);
if (code != TCL_OK) {
return code;
}
/*
* 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);
}
TclEmitOpcode(INST_POP, envPtr);
}
/*
* Generate code to leave the rest of the list on the stack.
*/
TclEmitInstInt4(INST_LIST_RANGE_IMM, idx, envPtr);
TclEmitInt4(-2, envPtr); /* -2 == "end" */
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TclCompileLindexCmd --
*
* Procedure called to compile the "lindex" 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,
|
| ︙ | ︙ | |||
1774 1775 1776 1777 1778 1779 1780 |
int numWords;
numWords = parsePtr->numWords;
/*
* Quit if too few args
*/
| | | | | | | | | | | | 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 |
int numWords;
numWords = parsePtr->numWords;
/*
* Quit if too few args
*/
if (numWords <= 1) {
return TCL_OUT_LINE_COMPILE;
}
varTokenPtr = parsePtr->tokenPtr
+ (parsePtr->tokenPtr->numComponents + 1);
/*
* Push the operands onto the stack.
*/
for (i=1 ; i<numWords ; i++) {
if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
TclEmitPush(
TclRegisterNewLiteral(envPtr, varTokenPtr[1].start,
varTokenPtr[1].size), envPtr);
} else {
code = TclCompileTokens(interp, varTokenPtr+1,
varTokenPtr->numComponents, envPtr);
if (code != TCL_OK) {
return code;
}
}
varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
}
/*
* 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);
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
1989 1990 1991 1992 1993 1994 1995 | * (7) Finally, INST_STORE_* stores the new value in the variable * and cleans up the stack. * *---------------------------------------------------------------------- */ int | | < < < < | | | | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 |
* (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 */
{
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 i;
/* Check argument count */
if (parsePtr->numWords < 3) {
/* Fail at run time, not in compilation */
return TCL_OUT_LINE_COMPILE;
}
/*
* 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 = TclPushVarName(interp, varTokenPtr, envPtr, TCL_CREATE_VAR,
&localIndex, &simpleVarName, &isScalar);
if (result != TCL_OK) {
return result;
}
/* 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 */
if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
TclEmitPush(TclRegisterNewLiteral(envPtr, varTokenPtr[1].start,
varTokenPtr[1].size), envPtr);
} else {
result = TclCompileTokens(interp, varTokenPtr+1,
varTokenPtr->numComponents, envPtr);
if (result != TCL_OK) {
return result;
}
}
}
/*
* Duplicate the variable name if it's been pushed.
*/
if (!simpleVarName || localIndex < 0) {
if (!simpleVarName || isScalar) {
tempDepth = parsePtr->numWords - 2;
} else {
tempDepth = parsePtr->numWords - 1;
}
TclEmitInstInt4(INST_OVER, tempDepth, envPtr);
}
/*
* Duplicate an array index if one's been pushed
*/
if (simpleVarName && !isScalar) {
if (localIndex < 0) {
tempDepth = parsePtr->numWords - 1;
} else {
tempDepth = parsePtr->numWords - 2;
}
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);
} else {
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);
} else {
TclEmitInstInt4(INST_LOAD_ARRAY4, localIndex, envPtr);
}
}
/*
* Emit the correct variety of 'lset' instruction
*/
if (parsePtr->numWords == 4) {
TclEmitOpcode(INST_LSET_LIST, envPtr);
} else {
TclEmitInstInt4(INST_LSET_FLAT, (parsePtr->numWords - 1), envPtr);
}
/*
* 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);
} else {
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);
} else {
TclEmitInstInt4(INST_STORE_ARRAY4, localIndex, envPtr);
}
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TclCompileRegexpCmd --
*
|
| ︙ | ︙ | |||
2348 2349 2350 2351 2352 2353 2354 | * * TclCompileReturnCmd -- * * Procedure called to compile the "return" command. * * Results: * The return value is a standard Tcl result, which is TCL_OK if the | | | | < < < < < < < < | | < > | < < < > | < < > > > | < < < | | > | < | > > | < < | | | | < < < < | > | > | | | > | > > | > > < < > > | | < > > > > > > > > > > > > > > > > > > > > > > > > > | < | | > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > | 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 |
*
* TclCompileReturnCmd --
*
* 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 analysis concludes that the
* command cannot be bytecompiled effectively, a return code of
* TCL__OUT_LINE_COMPILE is returned.
*
* Side effects:
* 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. */
{
/*
* General syntax: [return ?-option value ...? ?result?]
* An even number of words means an explicit result argument is present.
*/
int level = 1, code = TCL_OK, status = TCL_OK;
int numWords = parsePtr->numWords;
int explicitResult = (0 == (numWords % 2));
int numOptionWords = numWords - 1 - explicitResult;
Interp *iPtr = (Interp *) interp;
Tcl_Obj *returnOpts = iPtr->defaultReturnOpts;
Tcl_Token *wordTokenPtr = parsePtr->tokenPtr
+ (parsePtr->tokenPtr->numComponents + 1);
if (numOptionWords > 0) {
/*
* 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.
*/
int objc;
Tcl_Obj **objv = (Tcl_Obj **)
ckalloc(numOptionWords * sizeof(Tcl_Obj *));
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;
}
wordTokenPtr += wordTokenPtr->numComponents + 1;
}
status = TclMergeReturnOptions(interp, objc, objv,
&returnOpts, &code, &level);
cleanup:
while (--objc >= 0) {
Tcl_DecrRefCount(objv[objc]);
}
ckfree((char *)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. */
Tcl_ResetResult(interp);
return TCL_OUT_LINE_COMPILE;
}
}
/* All options are known at compile time, so we're going to
* bytecompile. Emit instructions to push the result on
* the stack */
if (explicitResult) {
if (wordTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
/* Explicit result is a simple word, so we can compile quickly to
* a simple push */
TclEmitPush(TclRegisterNewLiteral(envPtr, wordTokenPtr[1].start,
wordTokenPtr[1].size), envPtr);
} else {
/* More complex tokens get compiled */
status = TclCompileTokens(interp, wordTokenPtr+1,
wordTokenPtr->numComponents, envPtr);
if (TCL_OK != status) {
return status;
}
}
} else {
/* No explict result argument, so default result is empty string */
TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
}
/*
* Check for optimization: When [return] is in a proc, and there's
* no enclosing [catch], and the default return options are in effect,
* then the INST_DONE instruction is equivalent, and considerably more
* efficient.
*/
if (returnOpts == iPtr->defaultReturnOpts) {
/* We have default return options... */
if (envPtr->procPtr != NULL) {
/* ... 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;
}
index--;
}
if (!enclosingCatch) {
/* ... and there is no enclosing catch. */
TclEmitOpcode(INST_DONE, envPtr);
return TCL_OK;
}
}
}
/*
* Could not use the optimization, so we push the return options
* dictionary, and emit the INST_RETURN instruction with code
* and level as operands.
*/
TclEmitPush(TclAddLiteralObj(envPtr, returnOpts, NULL), envPtr);
TclEmitInstInt4(INST_RETURN, code, envPtr);
TclEmitInt4(level, envPtr);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TclCompileSetCmd --
|
| ︙ | ︙ | |||
2548 2549 2550 2551 2552 2553 2554 |
TclEmitOpcode((isAssignment?
INST_STORE_ARRAY_STK : INST_LOAD_ARRAY_STK), envPtr);
}
}
} else {
TclEmitOpcode((isAssignment? INST_STORE_STK : INST_LOAD_STK), envPtr);
}
| | | 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 |
TclEmitOpcode((isAssignment?
INST_STORE_ARRAY_STK : INST_LOAD_ARRAY_STK), envPtr);
}
}
} else {
TclEmitOpcode((isAssignment? INST_STORE_STK : INST_LOAD_STK), envPtr);
}
done:
return code;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
2585 2586 2587 2588 2589 2590 2591 |
* command created by Tcl_ParseCommand. */
CompileEnv *envPtr; /* Holds resulting instructions. */
{
Tcl_Token *opTokenPtr, *varTokenPtr;
Tcl_Obj *opObj;
int index;
int code;
| | | 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 |
* 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
|
| ︙ | ︙ | |||
3036 3037 3038 3039 3040 3041 3042 |
/*
* Generate a test for each arm.
*/
contFixIndex = -1;
fixupArray = (JumpFixup *) ckalloc(sizeof(JumpFixup) * argc);
fixupTargetArray = (int *) ckalloc(sizeof(int) * argc);
| | | 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 |
/*
* Generate a test for each arm.
*/
contFixIndex = -1;
fixupArray = (JumpFixup *) ckalloc(sizeof(JumpFixup) * argc);
fixupTargetArray = (int *) ckalloc(sizeof(int) * argc);
(VOID *) memset(fixupTargetArray, 0, argc * sizeof(int));
fixupCount = 0;
foundDefault = 0;
for (i=0 ; i<argc ; i+=2) {
int code; /* Return codes from sub-compiles. */
int nextArmFixupIndex = -1;
/*
|
| ︙ | ︙ | |||
3063 3064 3065 3066 3067 3068 3069 | case Switch_Glob: TclEmitPush(TclRegisterNewLiteral(envPtr, argv[i], (int) strlen(argv[i])), envPtr); TclEmitInstInt4(INST_OVER, 1, envPtr); TclEmitInstInt1(INST_STR_MATCH, /*nocase*/0, envPtr); break; default: | | | 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 |
case Switch_Glob:
TclEmitPush(TclRegisterNewLiteral(envPtr, argv[i],
(int) strlen(argv[i])), envPtr);
TclEmitInstInt4(INST_OVER, 1, envPtr);
TclEmitInstInt1(INST_STR_MATCH, /*nocase*/0, envPtr);
break;
default:
Tcl_Panic("unknown switch mode: %d",mode);
}
/*
* Process fall-through clauses here...
*/
if (argv[i+1][0]=='-' && argv[i+1][1]=='\0') {
if (contFixIndex == -1) {
contFixIndex = fixupCount;
|
| ︙ | ︙ | |||
3218 3219 3220 3221 3222 3223 3224 |
Tcl_Parse *parsePtr; /* Points to a parse structure for the
* command created by Tcl_ParseCommand. */
CompileEnv *envPtr; /* Holds resulting instructions. */
{
Tcl_Token *varTokenPtr;
int i, numWords;
CONST char *varName, *tail;
| | | | 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 |
Tcl_Parse *parsePtr; /* Points to a parse structure for the
* command created by Tcl_ParseCommand. */
CompileEnv *envPtr; /* Holds resulting instructions. */
{
Tcl_Token *varTokenPtr;
int i, numWords;
CONST char *varName, *tail;
if (envPtr->procPtr == NULL) {
return TCL_OUT_LINE_COMPILE;
}
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;
|
| ︙ | ︙ | |||
3366 3367 3368 3369 3370 3371 3372 |
if (loopMayEnd) {
TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpEvalCondFixup);
testCodeOffset = 0; /* avoid compiler warning */
} else {
testCodeOffset = (envPtr->codeNext - envPtr->codeStart);
}
| < | 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 |
if (loopMayEnd) {
TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpEvalCondFixup);
testCodeOffset = 0; /* avoid compiler warning */
} else {
testCodeOffset = (envPtr->codeNext - envPtr->codeStart);
}
/*
* Compile the loop body.
*/
bodyCodeOffset = (envPtr->codeNext - envPtr->codeStart);
code = TclCompileCmdWord(interp, bodyTokenPtr+1,
|
| ︙ | ︙ | |||
3410 3411 3412 3413 3414 3415 3416 |
if (code == TCL_ERROR) {
Tcl_AddObjErrorInfo(interp,
"\n (\"while\" test expression)", -1);
}
goto error;
}
envPtr->currStackDepth = savedStackDepth + 1;
| | | 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 |
if (code == TCL_ERROR) {
Tcl_AddObjErrorInfo(interp,
"\n (\"while\" test expression)", -1);
}
goto error;
}
envPtr->currStackDepth = savedStackDepth + 1;
jumpDist = (envPtr->codeNext - envPtr->codeStart) - bodyCodeOffset;
if (jumpDist > 127) {
TclEmitInstInt4(INST_JUMP_TRUE4, -jumpDist, envPtr);
} else {
TclEmitInstInt1(INST_JUMP_TRUE1, -jumpDist, envPtr);
}
} else {
|
| ︙ | ︙ | |||
3435 3436 3437 3438 3439 3440 3441 |
* 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);
| | | 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 |
* 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);
/*
* The while command's result is an empty string.
*/
pushResult:
envPtr->currStackDepth = savedStackDepth;
TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
|
| ︙ | ︙ | |||
3525 3526 3527 3528 3529 3530 3531 | * 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; | | | | | 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 |
* 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] == ')') {
/*
* last char is ')' => potential array reference.
*/
for (i=0,p=name ; i<nameChars ; i++,p++) {
if (*p == '(') {
elName = p + 1;
elNameChars = nameChars - i - 2;
nameChars = i;
break;
}
}
if ((elName != NULL) && elNameChars) {
/*
* An array element, the element name is a simple
|
| ︙ | ︙ | |||
3606 3607 3608 3609 3610 3611 3612 | elemTokenPtr = (Tcl_Token *) ckalloc(n * sizeof(Tcl_Token)); allocedTokens = 1; elemTokenPtr->type = TCL_TOKEN_TEXT; elemTokenPtr->start = elName; elemTokenPtr->size = remainingChars; elemTokenPtr->numComponents = 0; elemTokenCount = n; | | | | | | 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 |
elemTokenPtr = (Tcl_Token *) ckalloc(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)));
} else {
/*
* Use the already available tokens.
*/
elemTokenPtr = &varTokenPtr[2];
elemTokenCount = n - 1;
}
}
}
if (simpleVarName) {
|
| ︙ | ︙ |
Changes to generic/tclCompExpr.c.
1 2 3 4 5 6 7 8 9 10 11 | /* * tclCompExpr.c -- * * This file contains the code to compile Tcl expressions. * * Copyright (c) 1997 Sun Microsystems, Inc. * Copyright (c) 1998-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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * tclCompExpr.c -- * * This file contains the code to compile Tcl expressions. * * Copyright (c) 1997 Sun Microsystems, Inc. * Copyright (c) 1998-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. * * RCS: @(#) $Id: tclCompExpr.c,v 1.14.2.3 2004/02/07 05:48:00 dgp Exp $ */ #include "tclInt.h" #include "tclCompile.h" /* * The stuff below is a bit of a hack so that this file can be used in |
| ︙ | ︙ | |||
347 348 349 350 351 352 353 |
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) {
| | | 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
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) {
Tcl_Panic("CompileSubExpr: token type %d not TCL_TOKEN_SUB_EXPR\n",
exprTokenPtr->type);
}
code = TCL_OK;
/*
* Switch on the type of the first token after the subexpression token.
* After processing it, advance tokenPtr to point just after the
|
| ︙ | ︙ | |||
545 546 547 548 549 550 551 |
if (code != TCL_OK) {
goto done;
}
tokenPtr = endPtr;
break;
default:
| | | | 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 |
if (code != TCL_OK) {
goto done;
}
tokenPtr = endPtr;
break;
default:
Tcl_Panic("CompileSubExpr: unexpected operator %d requiring special treatment\n",
opIndex);
} /* end switch on operator requiring special treatment */
infoPtr->hasOperators = 1;
break;
default:
Tcl_Panic("CompileSubExpr: unexpected token type %d\n",
tokenPtr->type);
}
/*
* 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
|
| ︙ | ︙ | |||
608 609 610 611 612 613 614 |
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. */
{
JumpFixup shortCircuitFixup; /* Used to fix up the short circuit jump
* after the first subexpression. */
| | > | < | < < < | < < < < < < < < < < < < < < < < < < < < | < | > | > | > > > > > > > > > > > | < > > > > | | > > | > > > > > | | | 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 |
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. */
{
JumpFixup shortCircuitFixup; /* Used to fix up the short circuit jump
* after the first subexpression. */
JumpFixup shortCircuitFixup2;/* Used to fix up the second jump to the
* short-circuit target. */
JumpFixup endFixup; /* Used to fix up jump to the end. */
Tcl_Token *tokenPtr;
int code;
int savedStackDepth = envPtr->currStackDepth;
/*
* Emit code for the first operand.
*/
tokenPtr = exprTokenPtr+2;
code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
if (code != TCL_OK) {
goto done;
}
tokenPtr += (tokenPtr->numComponents + 1);
/*
* Emit the short-circuit jump.
*/
TclEmitForwardJump(envPtr,
((opIndex==OP_LAND)? TCL_FALSE_JUMP : TCL_TRUE_JUMP),
&shortCircuitFixup);
/*
* Emit code for the second operand.
*/
code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
if (code != TCL_OK) {
goto done;
}
tokenPtr += (tokenPtr->numComponents + 1);
/*
* The result is the boolean value of the second operand. We
* code this in a somewhat contorted manner to be able to reuse
* the shortCircuit value and save one INST_JUMP.
*/
TclEmitForwardJump(envPtr,
((opIndex==OP_LAND)? TCL_FALSE_JUMP : TCL_TRUE_JUMP),
&shortCircuitFixup2);
if (opIndex == OP_LAND) {
TclEmitPush(TclRegisterNewLiteral(envPtr, "1", 1), envPtr);
} else {
TclEmitPush(TclRegisterNewLiteral(envPtr, "0", 1), envPtr);
}
TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &endFixup);
/*
* Fixup the short-circuit jumps and push the shortCircuit value.
* Note that shortCircuitFixup2 is always a short jump.
*/
TclFixupForwardJumpToHere(envPtr, &shortCircuitFixup2, 127);
if (TclFixupForwardJumpToHere(envPtr, &shortCircuitFixup, 127)) {
/*
* shortCircuit jump grown by 3 bytes: update endFixup.
*/
endFixup.codeOffset += 3;
}
if (opIndex == OP_LAND) {
TclEmitPush(TclRegisterNewLiteral(envPtr, "0", 1), envPtr);
} else {
TclEmitPush(TclRegisterNewLiteral(envPtr, "1", 1), envPtr);
}
TclFixupForwardJumpToHere(envPtr, &endFixup, 127);
*endPtrPtr = tokenPtr;
done:
envPtr->currStackDepth = savedStackDepth + 1;
return code;
}
|
| ︙ | ︙ |
Changes to generic/tclCompile.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/*
* 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").
*
* Copyright (c) 1996-1998 Sun Microsystems, Inc.
* 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.
*
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/*
* 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").
*
* Copyright (c) 1996-1998 Sun Microsystems, Inc.
* 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.
*
* RCS: @(#) $Id: tclCompile.c,v 1.49.2.3 2004/02/07 05:48:00 dgp Exp $
*/
#include "tclInt.h"
#include "tclCompile.h"
/*
* Table of all AuxData types.
|
| ︙ | ︙ | |||
50 51 52 53 54 55 56 |
* Note that the load, store, and incr instructions do not distinguish local
* from global variables; the bytecode interpreter at runtime uses the
* existence of a procedure call frame to distinguish these.
*/
InstructionDesc tclInstructionTable[] = {
/* Name Bytes stackEffect #Opnds Operand types Stack top, next */
| | | | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
* Note that the load, store, and incr instructions do not distinguish local
* from global variables; the bytecode interpreter at runtime uses the
* existence of a procedure call frame to distinguish these.
*/
InstructionDesc tclInstructionTable[] = {
/* Name Bytes stackEffect #Opnds Operand types Stack top, next */
{"done", 1, -1, 0, {OPERAND_NONE}},
/* Finish ByteCode execution and return stktop (top stack item) */
{"push1", 2, +1, 1, {OPERAND_UINT1}},
/* Push object at ByteCode objArray[op1] */
{"push4", 5, +1, 1, {OPERAND_UINT4}},
/* Push object at ByteCode objArray[op4] */
{"pop", 1, -1, 0, {OPERAND_NONE}},
/* Pop the topmost stack object */
{"dup", 1, +1, 0, {OPERAND_NONE}},
/* Duplicate the topmost stack object and push the result */
{"concat1", 2, INT_MIN, 1, {OPERAND_UINT1}},
/* Concatenate the top op1 items and push result */
{"invokeStk1", 2, INT_MIN, 1, {OPERAND_UINT1}},
/* Invoke command named objv[0]; <objc,objv> = <op1,top op1> */
|
| ︙ | ︙ | |||
93 94 95 96 97 98 99 |
/* Store scalar variable at op1<=255 in frame; value is stktop */
{"storeScalar4", 5, 0, 1, {OPERAND_UINT4}},
/* Store scalar variable at op1 > 255 in frame; value is stktop */
{"storeScalarStk", 1, -1, 0, {OPERAND_NONE}},
/* Store scalar; value is stktop, scalar name is stknext */
{"storeArray1", 2, -1, 1, {OPERAND_UINT1}},
/* Store array element; array at op1<=255, value is top then elem */
| | | | | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
/* Store scalar variable at op1<=255 in frame; value is stktop */
{"storeScalar4", 5, 0, 1, {OPERAND_UINT4}},
/* Store scalar variable at op1 > 255 in frame; value is stktop */
{"storeScalarStk", 1, -1, 0, {OPERAND_NONE}},
/* Store scalar; value is stktop, scalar name is stknext */
{"storeArray1", 2, -1, 1, {OPERAND_UINT1}},
/* Store array element; array at op1<=255, value is top then elem */
{"storeArray4", 5, -1, 1, {OPERAND_UINT4}},
/* Store array element; array at op1>=256, value is top then elem */
{"storeArrayStk", 1, -2, 0, {OPERAND_NONE}},
/* Store array element; value is stktop, then elem, array names */
{"storeStk", 1, -1, 0, {OPERAND_NONE}},
/* Store general variable; value is stktop, then unparsed name */
{"incrScalar1", 2, 0, 1, {OPERAND_UINT1}},
/* Incr scalar at index op1<=255 in frame; incr amount is stktop */
{"incrScalarStk", 1, -1, 0, {OPERAND_NONE}},
/* Incr scalar; incr amount is stktop, scalar's name is stknext */
{"incrArray1", 2, -1, 1, {OPERAND_UINT1}},
/* Incr array elem; arr at slot op1<=255, amount is top then elem */
{"incrArrayStk", 1, -2, 0, {OPERAND_NONE}},
/* Incr array element; amount is top then elem then array names */
{"incrStk", 1, -1, 0, {OPERAND_NONE}},
/* Incr general variable; amount is stktop then unparsed var name */
{"incrScalar1Imm", 3, +1, 2, {OPERAND_UINT1, OPERAND_INT1}},
/* Incr scalar at slot op1 <= 255; amount is 2nd operand byte */
{"incrScalarStkImm", 2, 0, 1, {OPERAND_INT1}},
/* Incr scalar; scalar name is stktop; incr amount is op1 */
{"incrArray1Imm", 3, 0, 2, {OPERAND_UINT1, OPERAND_INT1}},
/* Incr array elem; array at slot op1 <= 255, elem is stktop,
* amount is 2nd operand byte */
{"incrArrayStkImm", 2, -1, 1, {OPERAND_INT1}},
/* Incr array element; elem is top then array name, amount is op1 */
{"incrStkImm", 2, 0, 1, {OPERAND_INT1}},
/* Incr general variable; unparsed name is top, amount is op1 */
{"jump1", 2, 0, 1, {OPERAND_INT1}},
/* Jump relative to (pc + op1) */
{"jump4", 5, 0, 1, {OPERAND_INT4}},
/* Jump relative to (pc + op4) */
{"jumpTrue1", 2, -1, 1, {OPERAND_INT1}},
|
| ︙ | ︙ | |||
223 224 225 226 227 228 229 |
/* Str Length: push (strlen stktop) */
{"strindex", 1, -1, 0, {OPERAND_NONE}},
/* Str Index: push (strindex stknext stktop) */
{"strmatch", 2, -1, 1, {OPERAND_INT1}},
/* Str Match: push (strmatch stknext stktop) opnd == nocase */
{"list", 5, INT_MIN, 1, {OPERAND_UINT4}},
/* List: push (stk1 stk2 ... stktop) */
| | | | 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
/* Str Length: push (strlen stktop) */
{"strindex", 1, -1, 0, {OPERAND_NONE}},
/* Str Index: push (strindex stknext stktop) */
{"strmatch", 2, -1, 1, {OPERAND_INT1}},
/* Str Match: push (strmatch stknext stktop) opnd == nocase */
{"list", 5, INT_MIN, 1, {OPERAND_UINT4}},
/* List: push (stk1 stk2 ... stktop) */
{"listIndex", 1, -1, 0, {OPERAND_NONE}},
/* List Index: push (listindex stknext stktop) */
{"listLength", 1, 0, 0, {OPERAND_NONE}},
/* List Len: push (listlength stktop) */
{"appendScalar1", 2, 0, 1, {OPERAND_UINT1}},
/* Append scalar variable at op1<=255 in frame; value is stktop */
{"appendScalar4", 5, 0, 1, {OPERAND_UINT4}},
/* Append scalar variable at op1 > 255 in frame; value is stktop */
{"appendArray1", 2, -1, 1, {OPERAND_UINT1}},
/* Append array element; array at op1<=255, value is top then elem */
|
| ︙ | ︙ | |||
251 252 253 254 255 256 257 |
/* Lappend array element; array at op1<=255, value is top then elem */
{"lappendArray4", 5, -1, 1, {OPERAND_UINT4}},
/* Lappend array element; array at op1>=256, value is top then elem */
{"lappendArrayStk", 1, -2, 0, {OPERAND_NONE}},
/* Lappend array element; value is stktop, then elem, array names */
{"lappendStk", 1, -1, 0, {OPERAND_NONE}},
/* Lappend general variable; value is stktop, then unparsed name */
| | | | > | | > > > > > > > > | 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
/* Lappend array element; array at op1<=255, value is top then elem */
{"lappendArray4", 5, -1, 1, {OPERAND_UINT4}},
/* Lappend array element; array at op1>=256, value is top then elem */
{"lappendArrayStk", 1, -2, 0, {OPERAND_NONE}},
/* Lappend array element; value is stktop, then elem, array names */
{"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.
*/
{"return", 9, -2, 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) */
{"listverify", 1, 0, 0, {OPERAND_NONE}},
/* Test that top of stack is a valid list; error if not */
{"invokeExp", INT_MIN, INT_MIN, 2, {OPERAND_UINT4, OPERAND_ULIST1}},
/* Invoke with expansion: <objc,objv> = expanded <op1,top op1> */
{"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) */
{0}
};
/*
* Prototypes for procedures defined later in this file:
*/
|
| ︙ | ︙ | |||
361 362 363 364 365 366 367 |
int length, result;
char *string;
#ifdef TCL_COMPILE_DEBUG
if (!traceInitialized) {
if (Tcl_LinkVar(interp, "tcl_traceCompile",
(char *) &tclTraceCompile, TCL_LINK_INT) != TCL_OK) {
| | | 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
int length, result;
char *string;
#ifdef TCL_COMPILE_DEBUG
if (!traceInitialized) {
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
string = Tcl_GetStringFromObj(objPtr, &length);
TclInitCompileEnv(interp, &compEnv, string, length);
|
| ︙ | ︙ | |||
766 767 768 769 770 771 772 773 774 775 776 777 778 779 |
if (envPtr->mallocedCmdMap) {
ckfree((char *) envPtr->cmdMapPtr);
}
if (envPtr->mallocedAuxDataArray) {
ckfree((char *) envPtr->auxDataArrayPtr);
}
}
/*
*----------------------------------------------------------------------
*
* TclCompileScript --
*
* Compile a Tcl script in a string.
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 |
if (envPtr->mallocedCmdMap) {
ckfree((char *) envPtr->cmdMapPtr);
}
if (envPtr->mallocedAuxDataArray) {
ckfree((char *) envPtr->auxDataArrayPtr);
}
}
/*
*----------------------------------------------------------------------
*
* TclWordKnownAtCompileTime --
*
* Test whether the value of a token is completely known at compile
* time.
*
* Results:
* Returns true if the tokenPtr argument points to a word value that
* is completely known at compile time. Generally, values that are
* known at compile time can be compiled to their values, while values
* that cannot be known until substitution at runtime must be compiled
* to bytecode instructions that perform that substitution. For several
* commands, whether or not arguments are known at compile time determine
* whether it is worthwhile to compile at all.
*
* Side effects:
* When returning true, appends the known value of the word to
* the unshared Tcl_Obj (*valuePtr), unless valuePtr is NULL.
*
*----------------------------------------------------------------------
*/
int
TclWordKnownAtCompileTime(tokenPtr, valuePtr)
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 numComponents = tokenPtr->numComponents;
Tcl_Obj *tempPtr = NULL;
if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
if (valuePtr != NULL) {
Tcl_AppendToObj(valuePtr, tokenPtr->start, tokenPtr->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);
}
continue;
case TCL_TOKEN_BS:
if (tempPtr != NULL) {
char utfBuf[TCL_UTF_MAX];
int length =
Tcl_UtfBackslash(tokenPtr->start, NULL, utfBuf);
Tcl_AppendToObj(tempPtr, utfBuf, length);
}
continue;
default:
if (tempPtr != NULL) {
Tcl_DecrRefCount(tempPtr);
}
return 0;
}
}
if (valuePtr != NULL) {
Tcl_AppendObjToObj(valuePtr, tempPtr);
Tcl_DecrRefCount(tempPtr);
}
return 1;
}
/*
*----------------------------------------------------------------------
*
* TclCompileScript --
*
* Compile a Tcl script in a string.
|
| ︙ | ︙ | |||
1207 1208 1209 1210 1211 1212 1213 | } numObjsToConcat++; count -= tokenPtr->numComponents; tokenPtr += tokenPtr->numComponents; break; default: | | | | 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 |
}
numObjsToConcat++;
count -= tokenPtr->numComponents;
tokenPtr += tokenPtr->numComponents;
break;
default:
Tcl_Panic("Unexpected token type in TclCompileTokens: %d; %.*s",
tokenPtr->type, tokenPtr->size, tokenPtr->start);
}
}
/*
* Push any accumulated characters appearing at the end.
*/
|
| ︙ | ︙ | |||
1513 1514 1515 1516 1517 1518 1519 |
codePtr->auxDataArrayPtr = NULL;
}
p += auxDataArrayBytes;
nextPtr = EncodeCmdLocMap(envPtr, codePtr, (unsigned char *) p);
#ifdef TCL_COMPILE_DEBUG
if (((size_t)(nextPtr - p)) != cmdLocBytes) {
| | | 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 |
codePtr->auxDataArrayPtr = NULL;
}
p += auxDataArrayBytes;
nextPtr = EncodeCmdLocMap(envPtr, codePtr, (unsigned char *) p);
#ifdef TCL_COMPILE_DEBUG
if (((size_t)(nextPtr - p)) != cmdLocBytes) {
Tcl_Panic("TclInitByteCodeObj: encoded cmd location bytes %d != expected size %d\n", (nextPtr - p), cmdLocBytes);
}
#endif
/*
* Record various compilation-related statistics about the new ByteCode
* structure. Don't include overhead for statistics-related fields.
*/
|
| ︙ | ︙ | |||
1907 1908 1909 1910 1911 1912 1913 |
* 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)) {
| | | 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 |
* 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)) {
Tcl_Panic("EnterCmdStartData: bad command index %d\n", cmdIndex);
}
if (cmdIndex >= envPtr->cmdMapEnd) {
/*
* Expand the command location array by allocating more storage from
* the heap. The currently allocated CmdLocation entries are stored
* from cmdMapPtr[0] up to cmdMapPtr[envPtr->cmdMapEnd] (inclusive).
|
| ︙ | ︙ | |||
1939 1940 1941 1942 1943 1944 1945 |
envPtr->cmdMapPtr = (CmdLocation *) newPtr;
envPtr->cmdMapEnd = newElems;
envPtr->mallocedCmdMap = 1;
}
if (cmdIndex > 0) {
if (codeOffset < envPtr->cmdMapPtr[cmdIndex-1].codeOffset) {
| | | 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 |
envPtr->cmdMapPtr = (CmdLocation *) newPtr;
envPtr->cmdMapEnd = newElems;
envPtr->mallocedCmdMap = 1;
}
if (cmdIndex > 0) {
if (codeOffset < envPtr->cmdMapPtr[cmdIndex-1].codeOffset) {
Tcl_Panic("EnterCmdStartData: cmd map not sorted by code offset");
}
}
cmdLocPtr = &(envPtr->cmdMapPtr[cmdIndex]);
cmdLocPtr->codeOffset = codeOffset;
cmdLocPtr->srcOffset = srcOffset;
cmdLocPtr->numSrcBytes = -1;
|
| ︙ | ︙ | |||
1984 1985 1986 1987 1988 1989 1990 |
* 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)) {
| | | | 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 |
* 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)) {
Tcl_Panic("EnterCmdExtentData: bad command index %d\n", cmdIndex);
}
if (cmdIndex > envPtr->cmdMapEnd) {
Tcl_Panic("EnterCmdExtentData: missing start data for command %d\n",
cmdIndex);
}
cmdLocPtr = &(envPtr->cmdMapPtr[cmdIndex]);
cmdLocPtr->numSrcBytes = numSrcBytes;
cmdLocPtr->numCodeBytes = numCodeBytes;
}
|
| ︙ | ︙ | |||
2421 2422 2423 2424 2425 2426 2427 | rangePtr->continueOffset += 3; } break; case CATCH_EXCEPTION_RANGE: rangePtr->catchOffset += 3; break; default: | | | 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 |
rangePtr->continueOffset += 3;
}
break;
case CATCH_EXCEPTION_RANGE:
rangePtr->catchOffset += 3;
break;
default:
Tcl_Panic("TclFixupForwardJump: bad ExceptionRange type %d\n",
rangePtr->type);
}
}
return 1; /* the jump was grown */
}
/*
|
| ︙ | ︙ | |||
2647 2648 2649 2650 2651 2652 2653 |
int prevCodeOffset, prevSrcOffset, i;
codeDeltaNext = codeLengthNext = srcDeltaNext = srcLengthNext = 0;
prevCodeOffset = prevSrcOffset = 0;
for (i = 0; i < numCmds; i++) {
codeDelta = (mapPtr[i].codeOffset - prevCodeOffset);
if (codeDelta < 0) {
| | | | | 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 |
int prevCodeOffset, prevSrcOffset, i;
codeDeltaNext = codeLengthNext = srcDeltaNext = srcLengthNext = 0;
prevCodeOffset = prevSrcOffset = 0;
for (i = 0; i < numCmds; i++) {
codeDelta = (mapPtr[i].codeOffset - prevCodeOffset);
if (codeDelta < 0) {
Tcl_Panic("GetCmdLocEncodingSize: bad code offset");
} else if (codeDelta <= 127) {
codeDeltaNext++;
} else {
codeDeltaNext += 5; /* 1 byte for 0xFF, 4 for positive delta */
}
prevCodeOffset = mapPtr[i].codeOffset;
codeLen = mapPtr[i].numCodeBytes;
if (codeLen < 0) {
Tcl_Panic("GetCmdLocEncodingSize: bad code length");
} else if (codeLen <= 127) {
codeLengthNext++;
} else {
codeLengthNext += 5; /* 1 byte for 0xFF, 4 for length */
}
srcDelta = (mapPtr[i].srcOffset - prevSrcOffset);
if ((-127 <= srcDelta) && (srcDelta <= 127)) {
srcDeltaNext++;
} else {
srcDeltaNext += 5; /* 1 byte for 0xFF, 4 for delta */
}
prevSrcOffset = mapPtr[i].srcOffset;
srcLen = mapPtr[i].numSrcBytes;
if (srcLen < 0) {
Tcl_Panic("GetCmdLocEncodingSize: bad source length");
} else if (srcLen <= 127) {
srcLengthNext++;
} else {
srcLengthNext += 5; /* 1 byte for 0xFF, 4 for length */
}
}
|
| ︙ | ︙ | |||
2732 2733 2734 2735 2736 2737 2738 |
*/
codePtr->codeDeltaStart = p;
prevOffset = 0;
for (i = 0; i < numCmds; i++) {
codeDelta = (mapPtr[i].codeOffset - prevOffset);
if (codeDelta < 0) {
| | | | 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 |
*/
codePtr->codeDeltaStart = p;
prevOffset = 0;
for (i = 0; i < numCmds; i++) {
codeDelta = (mapPtr[i].codeOffset - prevOffset);
if (codeDelta < 0) {
Tcl_Panic("EncodeCmdLocMap: bad code offset");
} else if (codeDelta <= 127) {
TclStoreInt1AtPtr(codeDelta, p);
p++;
} else {
TclStoreInt1AtPtr(0xFF, p);
p++;
TclStoreInt4AtPtr(codeDelta, p);
p += 4;
}
prevOffset = mapPtr[i].codeOffset;
}
/*
* Encode the code length for each command.
*/
codePtr->codeLengthStart = p;
for (i = 0; i < numCmds; i++) {
codeLen = mapPtr[i].numCodeBytes;
if (codeLen < 0) {
Tcl_Panic("EncodeCmdLocMap: bad code length");
} else if (codeLen <= 127) {
TclStoreInt1AtPtr(codeLen, p);
p++;
} else {
TclStoreInt1AtPtr(0xFF, p);
p++;
TclStoreInt4AtPtr(codeLen, p);
|
| ︙ | ︙ | |||
2793 2794 2795 2796 2797 2798 2799 |
* Encode the source length for each command.
*/
codePtr->srcLengthStart = p;
for (i = 0; i < numCmds; i++) {
srcLen = mapPtr[i].numSrcBytes;
if (srcLen < 0) {
| | | 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 |
* Encode the source length for each command.
*/
codePtr->srcLengthStart = p;
for (i = 0; i < numCmds; i++) {
srcLen = mapPtr[i].numSrcBytes;
if (srcLen < 0) {
Tcl_Panic("EncodeCmdLocMap: bad source length");
} else if (srcLen <= 127) {
TclStoreInt1AtPtr(srcLen, p);
p++;
} else {
TclStoreInt1AtPtr(0xFF, p);
p++;
TclStoreInt4AtPtr(srcLen, p);
|
| ︙ | ︙ | |||
2936 2937 2938 2939 2940 2941 2942 | fprintf(stdout, "continue %d, break %d\n", rangePtr->continueOffset, rangePtr->breakOffset); break; case CATCH_EXCEPTION_RANGE: fprintf(stdout, "catch %d\n", rangePtr->catchOffset); break; default: | | | 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 |
fprintf(stdout, "continue %d, break %d\n",
rangePtr->continueOffset, rangePtr->breakOffset);
break;
case CATCH_EXCEPTION_RANGE:
fprintf(stdout, "catch %d\n", rangePtr->catchOffset);
break;
default:
Tcl_Panic("TclPrintByteCodeObj: bad ExceptionRange type %d\n",
rangePtr->type);
}
}
}
/*
* If there were no commands (e.g., an expression or an empty string
|
| ︙ | ︙ | |||
3110 3111 3112 3113 3114 3115 3116 |
unsigned char *pc; /* Points to first byte of instruction. */
{
Proc *procPtr = codePtr->procPtr;
unsigned char opCode = *pc;
register InstructionDesc *instDesc = &tclInstructionTable[opCode];
unsigned char *codeStart = codePtr->codeStart;
unsigned int pcOffset = (pc - codeStart);
| | | | | | < | | < > > > > > > > > > > > > > > > > > > > > > > | | 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 |
unsigned char *pc; /* Points to first byte of instruction. */
{
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, numBytes = 1;
fprintf(stdout, "(%u) %s ", pcOffset, instDesc->name);
for (i = 0; i < instDesc->numOperands; i++) {
switch (instDesc->opTypes[i]) {
case OPERAND_INT1:
opnd = TclGetInt1AtPtr(pc+numBytes); numBytes++;
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);
}
break;
case OPERAND_INT4:
opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
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);
}
break;
case OPERAND_UINT1:
opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
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) {
Tcl_Panic("TclPrintInstruction: bad local var index %u (%u locals)\n",
(unsigned int) 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);
} else {
fprintf(stdout, "%u # var ", (unsigned int) opnd);
TclPrintSource(stdout, localPtr->name, 40);
}
} else {
fprintf(stdout, "%u ", (unsigned int) opnd);
}
break;
case OPERAND_UINT4:
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;
if (opnd >= localCt) {
Tcl_Panic("TclPrintInstruction: bad local var index %u (%u locals)\n",
(unsigned int) 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);
} else {
fprintf(stdout, "%u # var ", (unsigned int) opnd);
TclPrintSource(stdout, localPtr->name, 40);
}
} else {
fprintf(stdout, "%u ", (unsigned int) opnd);
}
break;
case OPERAND_ULIST1:
opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
fprintf(stdout, "{");
while (opnd) {
fprintf(stdout, "%u ", opnd);
opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
}
fprintf(stdout, "0}");
break;
case OPERAND_IDX4:
opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
if (opnd >= -1) {
fprintf(stdout, "%d ", opnd);
} else if (opnd == -2) {
fprintf(stdout, "end ");
} else {
fprintf(stdout, "end-%d ", -2-opnd);
}
break;
case OPERAND_NONE:
default:
break;
}
}
fprintf(stdout, "\n");
return numBytes;
}
/*
*----------------------------------------------------------------------
*
* TclPrintObject --
*
|
| ︙ | ︙ |
Changes to generic/tclCompile.h.
1 2 3 4 5 6 7 8 9 10 | /* * tclCompile.h -- * * Copyright (c) 1996-1998 Sun Microsystems, Inc. * Copyright (c) 1998-2000 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /* * tclCompile.h -- * * Copyright (c) 1996-1998 Sun Microsystems, Inc. * Copyright (c) 1998-2000 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. * * RCS: @(#) $Id: tclCompile.h,v 1.36.2.3 2004/02/07 05:48:00 dgp Exp $ */ #ifndef _TCLCOMPILATION #define _TCLCOMPILATION 1 #ifndef _TCLINT #include "tclInt.h" |
| ︙ | ︙ | |||
144 145 146 147 148 149 150 |
* 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.
*/
typedef struct AuxDataType {
| | | | | | | | | | | | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
* 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.
*/
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. */
} AuxDataType;
/*
* The definition of the AuxData structure that holds information created
* during compilation by CompileProcs and used by instructions during
* execution.
*/
typedef struct AuxData {
AuxDataType *type; /* pointer to the AuxData type associated with
* this ClientData. */
ClientData clientData; /* The compilation data itself. */
} AuxData;
/*
* Structure defining the compilation environment. After compilation, fields
* describing bytecode instructions are copied out into the more compact
* ByteCode structure defined below.
|
| ︙ | ︙ | |||
205 206 207 208 209 210 211 |
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. */
| | | | | | | | | | | | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
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. */
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.*/
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. */
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. */
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. */
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. */
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. */
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. */
LiteralEntry staticLiteralSpace[COMPILEENV_INIT_NUM_OBJECTS];
/* Initial storage of LiteralEntry array. */
ExceptionRange staticExceptArraySpace[COMPILEENV_INIT_EXCEPT_RANGES];
/* Initial ExceptionRange array storage. */
CmdLocation staticCmdMapSpace[COMPILEENV_INIT_CMD_MAP_SIZE];
/* Initial storage for cmd location map. */
AuxData staticAuxDataArraySpace[COMPILEENV_INIT_AUX_DATA_SIZE];
/* Initial storage for aux data array. */
} 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,
|
| ︙ | ︙ | |||
299 300 301 302 303 304 305 |
* 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. */
unsigned int flags; /* flags describing state for the codebyte.
| | | | 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
* 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. */
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. */
Proc *procPtr; /* If the ByteCode was compiled from a
* procedure body, this is a pointer to its
* Proc structure; otherwise NULL. This
|
| ︙ | ︙ | |||
336 337 338 339 340 341 342 |
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. */
| | | 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 |
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. */
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
|
| ︙ | ︙ | |||
433 434 435 436 437 438 439 | /* Opcodes 34 to 39 */ #define INST_JUMP1 34 #define INST_JUMP4 35 #define INST_JUMP_TRUE1 36 #define INST_JUMP_TRUE4 37 #define INST_JUMP_FALSE1 38 | | | 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 | /* Opcodes 34 to 39 */ #define INST_JUMP1 34 #define INST_JUMP4 35 #define INST_JUMP_TRUE1 36 #define INST_JUMP_TRUE4 37 #define INST_JUMP_FALSE1 38 #define INST_JUMP_FALSE4 39 /* Opcodes 40 to 64 */ #define INST_LOR 40 #define INST_LAND 41 #define INST_BITOR 42 #define INST_BITXOR 43 #define INST_BITAND 44 |
| ︙ | ︙ | |||
511 512 513 514 515 516 517 | /* TIP #22 - LINDEX operator with flat arg list */ #define INST_LIST_INDEX_MULTI 94 /* * TIP #33 - 'lset' command. Code gen also required a Forth-like | | | | > > > > | > > > > > > > > > > > > > | | > > > | | 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 |
/* TIP #22 - LINDEX operator with flat arg list */
#define INST_LIST_INDEX_MULTI 94
/*
* TIP #33 - 'lset' command. Code gen also required a Forth-like
* OVER operation.
*/
#define INST_OVER 95
#define INST_LSET_LIST 96
#define INST_LSET_FLAT 97
/* TIP#90 - 'return' command. */
#define INST_RETURN 98
/* TIP#123 - exponentiation operator. */
#define INST_EXPON 99
/* TIP #157 - {expand}... language syntax support. */
#define INST_LIST_VERIFY 100
#define INST_INVOKE_EXP 101
/*
* TIP #57 - 'lassign' command. Code generation requires immediate
* LINDEX and LRANGE operators.
*/
#define INST_LIST_INDEX_IMM 102
#define INST_LIST_RANGE_IMM 103
/* The last opcode */
#define LAST_INST_OPCODE 103
/*
* 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
typedef enum InstOperandType {
OPERAND_NONE,
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_ULIST1, /* List of one byte unsigned integers. */
OPERAND_IDX4 /* Four byte signed index (actually an
* integer, but displayed differently.) */
} 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
* computations. The value INT_MIN signals
* that the instruction's worst case effect
* is (1-opnd1).
*/
int numOperands; /* Number of operands. */
InstOperandType opTypes[MAX_INSTRUCTION_OPERANDS];
|
| ︙ | ︙ | |||
595 596 597 598 599 600 601 | #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 | | | | 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 |
#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. */
|
| ︙ | ︙ | |||
654 655 656 657 658 659 660 | * 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; | | | 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 |
* 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
typedef struct JumpFixupArray {
JumpFixup *fixup; /* Points to start of jump fixup array. */
int next; /* Index of next free array entry. */
int end; /* Index of last usable entry in array. */
int mallocedArray; /* 1 if array was expanded and fixups points
* into the heap, else 0. */
|
| ︙ | ︙ | |||
715 716 717 718 719 720 721 | /* *---------------------------------------------------------------- * Procedures exported by tclBasic.c to be used within the engine. *---------------------------------------------------------------- */ | | | | | | 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 | /* *---------------------------------------------------------------- * 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)); /* *---------------------------------------------------------------- * Procedures exported by the engine to be used by tclBasic.c *---------------------------------------------------------------- */ |
| ︙ | ︙ | |||
748 749 750 751 752 753 754 | EXTERN int TclCompileExpr _ANSI_ARGS_((Tcl_Interp *interp, CONST char *script, int numBytes, CompileEnv *envPtr)); EXTERN int TclCompileExprWords _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Token *tokenPtr, int numWords, CompileEnv *envPtr)); EXTERN int TclCompileScript _ANSI_ARGS_((Tcl_Interp *interp, | | > | | | 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 | EXTERN int TclCompileExpr _ANSI_ARGS_((Tcl_Interp *interp, CONST char *script, int numBytes, CompileEnv *envPtr)); EXTERN int TclCompileExprWords _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Token *tokenPtr, int numWords, CompileEnv *envPtr)); EXTERN int TclCompileScript _ANSI_ARGS_((Tcl_Interp *interp, CONST char *script, int numBytes, CompileEnv *envPtr)); EXTERN int TclCompileScriptTokens _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Token *tokens, Tcl_Token *lastTokenPtr, CompileEnv *envPtr)); EXTERN int TclCompileTokens _ANSI_ARGS_((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)); |
| ︙ | ︙ | |||
803 804 805 806 807 808 809 | #ifdef TCL_COMPILE_STATS EXTERN char * TclLiteralStats _ANSI_ARGS_(( LiteralTable *tablePtr)); EXTERN int TclLog2 _ANSI_ARGS_((int value)); #endif #ifdef TCL_COMPILE_DEBUG EXTERN void TclPrintByteCodeObj _ANSI_ARGS_((Tcl_Interp *interp, | | | 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 | #ifdef TCL_COMPILE_STATS EXTERN char * TclLiteralStats _ANSI_ARGS_(( LiteralTable *tablePtr)); EXTERN int TclLog2 _ANSI_ARGS_((int value)); #endif #ifdef TCL_COMPILE_DEBUG EXTERN void TclPrintByteCodeObj _ANSI_ARGS_((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)); |
| ︙ | ︙ | |||
826 827 828 829 830 831 832 833 834 835 836 837 838 839 | EXTERN void TclVerifyGlobalLiteralTable _ANSI_ARGS_(( Interp *iPtr)); EXTERN void TclVerifyLocalLiteralTable _ANSI_ARGS_(( CompileEnv *envPtr)); #endif EXTERN int TclCompileVariableCmd _ANSI_ARGS_(( Tcl_Interp *interp, Tcl_Parse *parsePtr, CompileEnv *envPtr)); /* *---------------------------------------------------------------- * Macros used by Tcl bytecode compilation and execution modules * inside the Tcl core but not used outside. *---------------------------------------------------------------- */ | > > | 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 | EXTERN void TclVerifyGlobalLiteralTable _ANSI_ARGS_(( Interp *iPtr)); EXTERN void TclVerifyLocalLiteralTable _ANSI_ARGS_(( CompileEnv *envPtr)); #endif EXTERN int TclCompileVariableCmd _ANSI_ARGS_(( Tcl_Interp *interp, Tcl_Parse *parsePtr, CompileEnv *envPtr)); EXTERN int TclWordKnownAtCompileTime _ANSI_ARGS_(( Tcl_Token *tokenPtr, Tcl_Obj *valuePtr)); /* *---------------------------------------------------------------- * Macros used by Tcl bytecode compilation and execution modules * inside the Tcl core but not used outside. *---------------------------------------------------------------- */ |
| ︙ | ︙ | |||
878 879 880 881 882 883 884 |
*
* EXTERN void TclEmitOpcode _ANSI_ARGS_((unsigned char op,
* CompileEnv *envPtr));
*/
#define TclEmitOpcode(op, envPtr) \
if ((envPtr)->codeNext == (envPtr)->codeEnd) \
| | | | > | > > > > > > > > > > > > > | | | | | | | > > > > > > > > > > > > > > > > > > > | | | | | | 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 |
*
* EXTERN void TclEmitOpcode _ANSI_ARGS_((unsigned char op,
* CompileEnv *envPtr));
*/
#define TclEmitOpcode(op, envPtr) \
if ((envPtr)->codeNext == (envPtr)->codeEnd) \
TclExpandCodeArray(envPtr); \
*(envPtr)->codeNext++ = (unsigned char) (op);\
TclUpdateStackReqs(op, 0, envPtr)
/*
* Macros to emit an integer operand.
* The ANSI C "prototype" for these macros are:
*
* EXTERN void TclEmitInt1 _ANSI_ARGS_((int i, CompileEnv *envPtr));
* EXTERN void TclEmitInt4 _ANSI_ARGS_((int i, CompileEnv *envPtr));
*/
#define TclEmitInt1(i, 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:
*
* EXTERN void TclEmitInstInt1 _ANSI_ARGS_((unsigned char op, int i,
* CompileEnv *envPtr));
* EXTERN void TclEmitInstInt4 _ANSI_ARGS_((unsigned char op, int i,
* CompileEnv *envPtr));
*/
#define TclEmitInstInt1(op, i, envPtr) \
if (((envPtr)->codeNext + 2) > (envPtr)->codeEnd) { \
TclExpandCodeArray(envPtr); \
} \
*(envPtr)->codeNext++ = (unsigned char) (op); \
*(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i));\
TclUpdateStackReqs(op, i, envPtr)
#define TclEmitInstInt4(op, i, envPtr) \
if (((envPtr)->codeNext + 5) > (envPtr)->codeEnd) { \
TclExpandCodeArray(envPtr); \
} \
*(envPtr)->codeNext++ = (unsigned char) (op); \
*(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) );\
TclUpdateStackReqs(op, i, envPtr)
/*
* Macro to emit an immediate list of index deltas in the code stream.
* The ANSI C "prototypes" for this macro is:
*
* EXTERN void TclEmitImmList1 _ANSI_ARGS_((Tcl_Obj *listPtr,
* CompileEnv *envPtr));
*/
#define TclEmitImmDeltaList1(listPtr, envPtr) \
{ \
int numBytes = Tcl_DStringLength(listPtr) + 1; \
while (((envPtr)->codeNext + numBytes) > (envPtr)->codeEnd) { \
TclExpandCodeArray(envPtr); \
} \
memcpy((VOID *) (envPtr)->codeNext, \
(VOID *)Tcl_DStringValue(listPtr), (size_t) numBytes); \
(envPtr)->codeNext += numBytes; \
}
/*
* 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:
*
* EXTERN void TclEmitPush _ANSI_ARGS_((int objIndex, CompileEnv *envPtr));
*/
#define TclEmitPush(objIndex, envPtr) \
{\
register int objIndexCopy = (objIndex);\
if (objIndexCopy <= 255) { \
TclEmitInstInt1(INST_PUSH1, objIndexCopy, (envPtr)); \
} 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:
*
* EXTERN void TclStoreInt1AtPtr _ANSI_ARGS_((int i, unsigned char *p));
* EXTERN void TclStoreInt4AtPtr _ANSI_ARGS_((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); \
*(p+2) = (unsigned char) ((unsigned int) (i) >> 8); \
*(p+3) = (unsigned char) ((unsigned int) (i) )
/*
|
| ︙ | ︙ | |||
999 1000 1001 1002 1003 1004 1005 |
* JumpFixup *fixupPtr, int threshold));
*/
#define TclFixupForwardJumpToHere(envPtr, fixupPtr, threshold) \
TclFixupForwardJump((envPtr), (fixupPtr), \
(envPtr)->codeNext-(envPtr)->codeStart-(fixupPtr)->codeOffset, \
(threshold))
| | | | | 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 |
* 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:
*
* 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));
*/
/*
* The TclGetInt1AtPtr macro is tricky because we want to do sign
* extension on the 1-byte value. Unfortunately the "char" type isn't
|
| ︙ | ︙ | |||
1033 1034 1035 1036 1037 1038 1039 | # else # define TclGetInt1AtPtr(p) (((int) *((char *) p)) \ | ((*(p) & 0200) ? (-256) : 0)) # endif #endif #define TclGetInt4AtPtr(p) (((int) TclGetInt1AtPtr(p) << 24) | \ | | | | | | 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 | # else # define TclGetInt1AtPtr(p) (((int) *((char *) p)) \ | ((*(p) & 0200) ? (-256) : 0)) # endif #endif #define TclGetInt4AtPtr(p) (((int) TclGetInt1AtPtr(p) << 24) | \ (*((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))) /* * 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)); |
| ︙ | ︙ |
Changes to generic/tclConfig.c.
1 2 3 4 5 6 7 8 9 10 11 | /* * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * 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. * * RCS: @(#) $Id: tclConfig.c,v 1.3.2.2 2004/02/07 05:48:00 dgp Exp $ */ #include "tclInt.h" /* |
| ︙ | ︙ | |||
185 186 187 188 189 190 191 | * Side effects: * See the manual for what this command does. * *---------------------------------------------------------------------- */ static int | | | | | < < | < | | | | | | | | | | | | | | | | | | < | | | | | | | | | | | | < | < | | < < < | | | | | | 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
* Side effects:
* See the manual for what this command does.
*
*----------------------------------------------------------------------
*/
static int
QueryConfigObjCmd(clientData, interp, objc, objv)
ClientData clientData;
Tcl_Interp *interp;
int objc;
struct Tcl_Obj * CONST *objv;
{
Tcl_Obj *pkgName = (Tcl_Obj*) clientData;
Tcl_Obj *pDB, *pkgDict, *val;
Tcl_DictSearch s;
int n, i, res, done, index;
Tcl_Obj *key, **vals;
static CONST char *subcmdStrings[] = {
"get", "list", NULL
};
enum subcmds {
CFG_GET, CFG_LIST
};
if ((objc < 2) || (objc > 3)) {
Tcl_WrongNumArgs (interp, 0, NULL, "list | get key");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], subcmdStrings,
"subcommand", 0, &index) != TCL_OK) {
return TCL_ERROR;
}
pDB = GetConfigDict(interp);
res = Tcl_DictObjGet(interp, pDB, pkgName, &pkgDict);
if (res!=TCL_OK || pkgDict==NULL) {
/* Maybe a Tcl_Panic is better, because the package data has to be present */
Tcl_SetObjResult(interp, Tcl_NewStringObj("package not known", -1));
return TCL_ERROR;
}
switch ((enum subcmds) index) {
case CFG_GET:
if (objc != 3) {
Tcl_WrongNumArgs(interp, 0, NULL, "get key");
return TCL_ERROR;
}
res = Tcl_DictObjGet(interp, pkgDict, objv [2], &val);
if (res!=TCL_OK || val==NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("key not known", -1));
return TCL_ERROR;
}
Tcl_SetObjResult(interp, val);
return TCL_OK;
case CFG_LIST:
if (objc != 2) {
Tcl_WrongNumArgs(interp, 0, NULL, "list");
return TCL_ERROR;
}
Tcl_DictObjSize(interp, pkgDict, &n);
if (n == 0) {
Tcl_SetObjResult(interp, Tcl_NewListObj(0, NULL));
return TCL_OK;
}
vals = (Tcl_Obj**) ckalloc(n * sizeof(Tcl_Obj*));
for (i=0, Tcl_DictObjFirst(interp, pkgDict, &s, &key, NULL, &done);
!done; Tcl_DictObjNext(&s, &key, NULL, &done), i++) {
vals[i] = key;
}
Tcl_SetObjResult(interp, TclNewListObjDirect(n, vals));
return TCL_OK;
default:
Tcl_Panic("QueryConfigObjCmd: Unknown subcommand to 'pkgconfig'. This can't happen");
break;
}
return TCL_ERROR;
}
/*
*-------------------------------------------------------------------------
*
|
| ︙ | ︙ |
Changes to generic/tclDecls.h.
1 2 3 4 5 6 7 8 9 10 | /* * tclDecls.h -- * * Declarations of functions in the platform independent public Tcl API. * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /* * tclDecls.h -- * * Declarations of functions in the platform independent public Tcl API. * * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclDecls.h,v 1.95.2.7 2004/02/07 05:48:00 dgp Exp $ */ #ifndef _TCLDECLS #define _TCLDECLS /* * WARNING: This file is automatically generated by the tools/genStubs.tcl |
| ︙ | ︙ | |||
2866 2867 2868 2869 2870 2871 2872 | EXTERN int Tcl_FSEqualPaths _ANSI_ARGS_((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_(( | | | | | | 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 | EXTERN int Tcl_FSEqualPaths _ANSI_ARGS_((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* pathPtr)); #endif #ifndef Tcl_FSJoinToPath_TCL_DECLARED #define Tcl_FSJoinToPath_TCL_DECLARED /* 464 */ EXTERN Tcl_Obj* Tcl_FSJoinToPath _ANSI_ARGS_((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* 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)); #endif |
| ︙ | ︙ | |||
2902 2903 2904 2905 2906 2907 2908 | EXTERN Tcl_Obj* Tcl_FSNewNativePath _ANSI_ARGS_(( Tcl_Filesystem* fromFilesystem, ClientData clientData)); #endif #ifndef Tcl_FSGetNativePath_TCL_DECLARED #define Tcl_FSGetNativePath_TCL_DECLARED /* 469 */ | | | < | | 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 | EXTERN Tcl_Obj* Tcl_FSNewNativePath _ANSI_ARGS_(( 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* pathPtr)); #endif #ifndef Tcl_FSFileSystemInfo_TCL_DECLARED #define Tcl_FSFileSystemInfo_TCL_DECLARED /* 470 */ EXTERN Tcl_Obj* Tcl_FSFileSystemInfo _ANSI_ARGS_((Tcl_Obj* pathPtr)); #endif #ifndef Tcl_FSPathSeparator_TCL_DECLARED #define Tcl_FSPathSeparator_TCL_DECLARED /* 471 */ EXTERN Tcl_Obj* Tcl_FSPathSeparator _ANSI_ARGS_((Tcl_Obj* pathPtr)); #endif #ifndef Tcl_FSListVolumes_TCL_DECLARED #define Tcl_FSListVolumes_TCL_DECLARED /* 472 */ EXTERN Tcl_Obj* Tcl_FSListVolumes _ANSI_ARGS_((void)); #endif #ifndef Tcl_FSRegister_TCL_DECLARED |
| ︙ | ︙ | |||
2946 2947 2948 2949 2950 2951 2952 | EXTERN CONST char* Tcl_FSGetTranslatedStringPath _ANSI_ARGS_(( 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_(( | | | | 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 | EXTERN CONST char* Tcl_FSGetTranslatedStringPath _ANSI_ARGS_(( 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* pathPtr)); #endif #ifndef Tcl_FSGetPathType_TCL_DECLARED #define Tcl_FSGetPathType_TCL_DECLARED /* 478 */ EXTERN Tcl_PathType Tcl_FSGetPathType _ANSI_ARGS_((Tcl_Obj * pathPtr)); #endif #ifndef Tcl_OutputBuffered_TCL_DECLARED #define Tcl_OutputBuffered_TCL_DECLARED /* 479 */ EXTERN int Tcl_OutputBuffered _ANSI_ARGS_((Tcl_Channel chan)); #endif #ifndef Tcl_FSMountsChanged_TCL_DECLARED |
| ︙ | ︙ | |||
3741 3742 3743 3744 3745 3746 3747 |
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 */
| | | | | | | | | | 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 |
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* pathPtr)); /* 463 */
Tcl_Obj* (*tcl_FSJoinToPath) _ANSI_ARGS_((Tcl_Obj * pathPtr, int objc, Tcl_Obj *CONST objv[])); /* 464 */
ClientData (*tcl_FSGetInternalRep) _ANSI_ARGS_((Tcl_Obj* pathPtr, 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* pathPtr)); /* 469 */
Tcl_Obj* (*tcl_FSFileSystemInfo) _ANSI_ARGS_((Tcl_Obj* pathPtr)); /* 470 */
Tcl_Obj* (*tcl_FSPathSeparator) _ANSI_ARGS_((Tcl_Obj* pathPtr)); /* 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* pathPtr)); /* 477 */
Tcl_PathType (*tcl_FSGetPathType) _ANSI_ARGS_((Tcl_Obj * pathPtr)); /* 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 */
|
| ︙ | ︙ |
Changes to generic/tclDictObj.c.
1 2 3 4 5 6 7 8 9 10 11 | /* * tclDictObj.c -- * * This file contains procedures 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. * | | > > > > > > > > > > > > > > > > > > | 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 | /* * tclDictObj.c -- * * This file contains procedures 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. * * RCS: @(#) $Id: tclDictObj.c,v 1.10.2.2 2004/02/07 05:48:00 dgp Exp $ */ #include "tclInt.h" /* * Flag values for TraceDictPath(). * * 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, TraceDictPath() will return the special * value DICT_PATH_NON_EXISTENT if the path is not traceable. */ #define DICT_PATH_UPDATE 1 #define DICT_PATH_EXISTS 2 #define DICT_PATH_NON_EXISTENT ((Tcl_Obj *) (void *) 1) /* * Prototypes for procedures defined later in this file: */ static int DictAppendCmd _ANSI_ARGS_((Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv)); static int DictCreateCmd _ANSI_ARGS_((Tcl_Interp *interp, |
| ︙ | ︙ | |||
54 55 56 57 58 59 60 | Tcl_Obj *copyPtr)); static void FreeDictInternalRep _ANSI_ARGS_((Tcl_Obj *dictPtr)); static int SetDictFromAny _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr)); static void UpdateStringOfDict _ANSI_ARGS_((Tcl_Obj *dictPtr)); static Tcl_Obj * TraceDictPath _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *rootPtr, int keyc, Tcl_Obj *CONST keyv[], | | | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | Tcl_Obj *copyPtr)); static void FreeDictInternalRep _ANSI_ARGS_((Tcl_Obj *dictPtr)); static int SetDictFromAny _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr)); static void UpdateStringOfDict _ANSI_ARGS_((Tcl_Obj *dictPtr)); static Tcl_Obj * TraceDictPath _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *rootPtr, int keyc, Tcl_Obj *CONST keyv[], int flags)); struct Dict; static void DeleteDict _ANSI_ARGS_((struct Dict *dict)); /* * Internal representation of a dictionary. * * The internal representation of a dictionary object is a hash table |
| ︙ | ︙ | |||
367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
if (objc & 1) {
if (interp != NULL) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("missing value to go with key", -1));
}
return TCL_ERROR;
}
/*
* Build the hash of key/value pairs.
*/
dict = (Dict *) ckalloc(sizeof(Dict));
Tcl_InitObjHashTable(&dict->table);
for (i=0 ; i<objc ; i+=2) {
| > > > > > > > > > | 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 |
if (objc & 1) {
if (interp != NULL) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("missing value to go with key", -1));
}
return TCL_ERROR;
}
/*
* If the list is shared its string rep must not be lost so it
* still is the same list.
*/
if (Tcl_IsShared(objPtr)) {
(void) Tcl_GetString(objPtr);
}
/*
* Build the hash of key/value pairs.
*/
dict = (Dict *) ckalloc(sizeof(Dict));
Tcl_InitObjHashTable(&dict->table);
for (i=0 ; i<objc ; i+=2) {
|
| ︙ | ︙ | |||
532 533 534 535 536 537 538 | * 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 | | > | | > | | | | | | | | > > > | > | 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 |
* 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 is DICT_PATH_EXISTS,
* 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.)
*
*----------------------------------------------------------------------
*/
static Tcl_Obj *
TraceDictPath(interp, dictPtr, keyc, keyv, flags)
Tcl_Interp *interp;
Tcl_Obj *dictPtr, *CONST keyv[];
int keyc, flags;
{
Dict *dict, *newDict;
int i;
if (dictPtr->typePtr != &tclDictType) {
if (SetDictFromAny(interp, dictPtr) != TCL_OK) {
return NULL;
}
}
dict = (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) {
if (flags == DICT_PATH_EXISTS) {
return DICT_PATH_NON_EXISTENT;
}
if (interp != NULL) {
Tcl_ResetResult(interp);
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
"key \"", TclGetString(keyv[i]),
"\" not known in dictionary", NULL);
}
return NULL;
}
tmpObj = (Tcl_Obj *) Tcl_GetHashValue(hPtr);
if (tmpObj->typePtr != &tclDictType) {
if (SetDictFromAny(interp, tmpObj) != TCL_OK) {
return NULL;
}
}
newDict = (Dict *) tmpObj->internalRep.otherValuePtr;
if (flags == DICT_PATH_UPDATE) {
if (Tcl_IsShared(tmpObj)) {
Tcl_DecrRefCount(tmpObj);
tmpObj = Tcl_DuplicateObj(tmpObj);
Tcl_IncrRefCount(tmpObj);
Tcl_SetHashValue(hPtr, (ClientData) tmpObj);
dict->epoch++;
newDict = (Dict *) tmpObj->internalRep.otherValuePtr;
}
newDict->chain = dictPtr;
}
|
| ︙ | ︙ | |||
650 651 652 653 654 655 656 |
Tcl_Obj *dictPtr, *keyPtr, *valuePtr;
{
Dict *dict;
Tcl_HashEntry *hPtr;
int isNew;
if (Tcl_IsShared(dictPtr)) {
| | | 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 |
Tcl_Obj *dictPtr, *keyPtr, *valuePtr;
{
Dict *dict;
Tcl_HashEntry *hPtr;
int isNew;
if (Tcl_IsShared(dictPtr)) {
Tcl_Panic("Tcl_DictObjPut called with shared object");
}
if (dictPtr->typePtr != &tclDictType) {
int result = SetDictFromAny(interp, dictPtr);
if (result != TCL_OK) {
return result;
}
|
| ︙ | ︙ | |||
748 749 750 751 752 753 754 |
Tcl_Interp *interp;
Tcl_Obj *dictPtr, *keyPtr;
{
Dict *dict;
Tcl_HashEntry *hPtr;
if (Tcl_IsShared(dictPtr)) {
| | | 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 |
Tcl_Interp *interp;
Tcl_Obj *dictPtr, *keyPtr;
{
Dict *dict;
Tcl_HashEntry *hPtr;
if (Tcl_IsShared(dictPtr)) {
Tcl_Panic("Tcl_DictObjRemove called with shared object");
}
if (dictPtr->typePtr != &tclDictType) {
int result = SetDictFromAny(interp, dictPtr);
if (result != TCL_OK) {
return result;
}
|
| ︙ | ︙ | |||
925 926 927 928 929 930 931 |
Tcl_HashEntry *hPtr;
/*
* 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) {
| | | 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 |
Tcl_HashEntry *hPtr;
/*
* 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");
}
hPtr = Tcl_NextHashEntry(&searchPtr->search);
if (hPtr == NULL) {
Tcl_DictObjDone(searchPtr);
*donePtr = 1;
return;
|
| ︙ | ︙ | |||
1012 1013 1014 1015 1016 1017 1018 |
Tcl_Obj *dictPtr, *CONST keyv[], *valuePtr;
{
Dict *dict;
Tcl_HashEntry *hPtr;
int isNew;
if (Tcl_IsShared(dictPtr)) {
| | | | | 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 |
Tcl_Obj *dictPtr, *CONST keyv[], *valuePtr;
{
Dict *dict;
Tcl_HashEntry *hPtr;
int isNew;
if (Tcl_IsShared(dictPtr)) {
Tcl_Panic("Tcl_DictObjPutKeyList called with shared object");
}
if (keyc < 1) {
Tcl_Panic("Tcl_DictObjPutKeyList called with empty key list");
}
dictPtr = TraceDictPath(interp, dictPtr, keyc-1, keyv, DICT_PATH_UPDATE);
if (dictPtr == NULL) {
return TCL_ERROR;
}
dict = (Dict *) dictPtr->internalRep.otherValuePtr;
hPtr = Tcl_CreateHashEntry(&dict->table, (char *)keyv[keyc-1], &isNew);
Tcl_IncrRefCount(valuePtr);
|
| ︙ | ︙ | |||
1068 1069 1070 1071 1072 1073 1074 |
int keyc;
Tcl_Obj *dictPtr, *CONST keyv[];
{
Dict *dict;
Tcl_HashEntry *hPtr;
if (Tcl_IsShared(dictPtr)) {
| | | | | 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 |
int keyc;
Tcl_Obj *dictPtr, *CONST keyv[];
{
Dict *dict;
Tcl_HashEntry *hPtr;
if (Tcl_IsShared(dictPtr)) {
Tcl_Panic("Tcl_DictObjRemoveKeyList called with shared object");
}
if (keyc < 1) {
Tcl_Panic("Tcl_DictObjRemoveKeyList called with empty key list");
}
dictPtr = TraceDictPath(interp, dictPtr, keyc-1, keyv, DICT_PATH_UPDATE);
if (dictPtr == NULL) {
return TCL_ERROR;
}
dict = (Dict *) dictPtr->internalRep.otherValuePtr;
hPtr = Tcl_FindHashEntry(&dict->table, (char *)keyv[keyc-1]);
if (hPtr != NULL) {
|
| ︙ | ︙ | |||
1306 1307 1308 1309 1310 1311 1312 |
* 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.
*/
| | | 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 |
* 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 = TraceDictPath(interp, objv[2], objc-4, objv+3, 0);
if (dictPtr == NULL) {
return TCL_ERROR;
}
result = Tcl_DictObjGet(interp, dictPtr, objv[objc-1], &valuePtr);
if (result != TCL_OK) {
return result;
}
|
| ︙ | ︙ | |||
1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 |
DictReplaceCmd(interp, objc, objv)
Tcl_Interp *interp;
int objc;
Tcl_Obj *CONST *objv;
{
Tcl_Obj *dictPtr;
int i, result;
if ((objc < 3) || !(objc & 1)) {
Tcl_WrongNumArgs(interp, 2, objv, "dictionary ?key value ...?");
return TCL_ERROR;
}
dictPtr = objv[2];
if (Tcl_IsShared(dictPtr)) {
dictPtr = Tcl_DuplicateObj(dictPtr);
}
for (i=3 ; i<objc ; i+=2) {
result = Tcl_DictObjPut(interp, dictPtr, objv[i], objv[i+1]);
if (result != TCL_OK) {
return TCL_ERROR;
}
}
Tcl_SetObjResult(interp, dictPtr);
return TCL_OK;
}
| > > > > > | 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 |
DictReplaceCmd(interp, objc, objv)
Tcl_Interp *interp;
int objc;
Tcl_Obj *CONST *objv;
{
Tcl_Obj *dictPtr;
int i, result;
int allocatedDict = 0;
if ((objc < 3) || !(objc & 1)) {
Tcl_WrongNumArgs(interp, 2, objv, "dictionary ?key value ...?");
return TCL_ERROR;
}
dictPtr = objv[2];
if (Tcl_IsShared(dictPtr)) {
dictPtr = Tcl_DuplicateObj(dictPtr);
allocatedDict = 1;
}
for (i=3 ; i<objc ; i+=2) {
result = Tcl_DictObjPut(interp, dictPtr, objv[i], objv[i+1]);
if (result != TCL_OK) {
if (allocatedDict) {
Tcl_DecrRefCount(dictPtr);
}
return TCL_ERROR;
}
}
Tcl_SetObjResult(interp, dictPtr);
return TCL_OK;
}
|
| ︙ | ︙ | |||
1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 |
DictRemoveCmd(interp, objc, objv)
Tcl_Interp *interp;
int objc;
Tcl_Obj *CONST *objv;
{
Tcl_Obj *dictPtr;
int i, result;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 2, objv, "dictionary ?key ...?");
return TCL_ERROR;
}
dictPtr = objv[2];
if (Tcl_IsShared(dictPtr)) {
dictPtr = Tcl_DuplicateObj(dictPtr);
}
for (i=3 ; i<objc ; i++) {
result = Tcl_DictObjRemove(interp, dictPtr, objv[i]);
if (result != TCL_OK) {
return TCL_ERROR;
}
}
Tcl_SetObjResult(interp, dictPtr);
return TCL_OK;
}
| > > > > > | 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 |
DictRemoveCmd(interp, objc, objv)
Tcl_Interp *interp;
int objc;
Tcl_Obj *CONST *objv;
{
Tcl_Obj *dictPtr;
int i, result;
int allocatedDict = 0;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 2, objv, "dictionary ?key ...?");
return TCL_ERROR;
}
dictPtr = objv[2];
if (Tcl_IsShared(dictPtr)) {
dictPtr = Tcl_DuplicateObj(dictPtr);
allocatedDict = 1;
}
for (i=3 ; i<objc ; i++) {
result = Tcl_DictObjRemove(interp, dictPtr, objv[i]);
if (result != TCL_OK) {
if (allocatedDict) {
Tcl_DecrRefCount(dictPtr);
}
return TCL_ERROR;
}
}
Tcl_SetObjResult(interp, dictPtr);
return TCL_OK;
}
|
| ︙ | ︙ | |||
1594 1595 1596 1597 1598 1599 1600 |
int result;
if (objc < 4) {
Tcl_WrongNumArgs(interp, 2, objv, "dictionary key ?key ...?");
return TCL_ERROR;
}
| | > > > > | 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 |
int result;
if (objc < 4) {
Tcl_WrongNumArgs(interp, 2, objv, "dictionary key ?key ...?");
return TCL_ERROR;
}
dictPtr = TraceDictPath(interp, objv[2], objc-4, objv+3, 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;
|
| ︙ | ︙ | |||
1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 |
int objc;
Tcl_Obj *CONST *objv;
{
Tcl_Obj *dictPtr, *valuePtr, *resultPtr;
int result, isWide = 0;
long incrValue = 1;
Tcl_WideInt wideIncrValue = 0;
if (objc < 4 || objc > 5) {
Tcl_WrongNumArgs(interp, 2, objv, "varName key ?increment?");
return TCL_ERROR;
}
if (objc == 5) {
| > | 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 |
int objc;
Tcl_Obj *CONST *objv;
{
Tcl_Obj *dictPtr, *valuePtr, *resultPtr;
int result, isWide = 0;
long incrValue = 1;
Tcl_WideInt wideIncrValue = 0;
int allocatedDict = 0;
if (objc < 4 || objc > 5) {
Tcl_WrongNumArgs(interp, 2, objv, "varName key ?increment?");
return TCL_ERROR;
}
if (objc == 5) {
|
| ︙ | ︙ | |||
1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 |
isWide = 1;
}
}
}
dictPtr = Tcl_ObjGetVar2(interp, objv[2], NULL, 0);
if (dictPtr == NULL) {
dictPtr = Tcl_NewDictObj();
if (isWide) {
valuePtr = Tcl_NewWideIntObj(wideIncrValue);
} else {
valuePtr = Tcl_NewLongObj(incrValue);
}
Tcl_DictObjPut(interp, dictPtr, objv[3], valuePtr);
} else {
long lValue;
Tcl_WideInt wValue;
if (Tcl_IsShared(dictPtr)) {
dictPtr = Tcl_DuplicateObj(dictPtr);
}
if (Tcl_DictObjGet(interp, dictPtr, objv[3], &valuePtr) != TCL_OK) {
return TCL_ERROR;
}
if (valuePtr == NULL) {
if (isWide) {
valuePtr = Tcl_NewWideIntObj(wideIncrValue);
} else {
valuePtr = Tcl_NewLongObj(incrValue);
| > > > > > | 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 |
isWide = 1;
}
}
}
dictPtr = Tcl_ObjGetVar2(interp, objv[2], NULL, 0);
if (dictPtr == NULL) {
allocatedDict = 1;
dictPtr = Tcl_NewDictObj();
if (isWide) {
valuePtr = Tcl_NewWideIntObj(wideIncrValue);
} else {
valuePtr = Tcl_NewLongObj(incrValue);
}
Tcl_DictObjPut(interp, dictPtr, objv[3], valuePtr);
} else {
long lValue;
Tcl_WideInt wValue;
if (Tcl_IsShared(dictPtr)) {
allocatedDict = 1;
dictPtr = Tcl_DuplicateObj(dictPtr);
}
if (Tcl_DictObjGet(interp, dictPtr, objv[3], &valuePtr) != TCL_OK) {
if (allocatedDict) {
Tcl_DecrRefCount(dictPtr);
}
return TCL_ERROR;
}
if (valuePtr == NULL) {
if (isWide) {
valuePtr = Tcl_NewWideIntObj(wideIncrValue);
} else {
valuePtr = Tcl_NewLongObj(incrValue);
|
| ︙ | ︙ | |||
1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 |
* Note that these operations on wide ints should work
* fine where they are the same as normal longs, though
* the compiler might complain about trivially satisifed
* tests.
*/
result = Tcl_GetWideIntFromObj(interp, valuePtr, &wValue);
if (result != TCL_OK) {
return result;
}
/*
* Determine if we should have got a standard long instead.
*/
if (Tcl_IsShared(valuePtr)) {
if (isWide) {
| > > > | 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 |
* Note that these operations on wide ints should work
* fine where they are the same as normal longs, though
* the compiler might complain about trivially satisifed
* tests.
*/
result = Tcl_GetWideIntFromObj(interp, valuePtr, &wValue);
if (result != TCL_OK) {
if (allocatedDict) {
Tcl_DecrRefCount(dictPtr);
}
return result;
}
/*
* Determine if we should have got a standard long instead.
*/
if (Tcl_IsShared(valuePtr)) {
if (isWide) {
|
| ︙ | ︙ | |||
1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 |
if (dictPtr->bytes != NULL) {
Tcl_InvalidateStringRep(dictPtr);
}
goto valueAlreadyInDictionary;
}
}
if (Tcl_DictObjPut(interp, dictPtr, objv[3], valuePtr) != TCL_OK) {
Tcl_DecrRefCount(valuePtr);
return TCL_ERROR;
}
}
valueAlreadyInDictionary:
resultPtr = Tcl_ObjSetVar2(interp, objv[2], NULL, dictPtr,
TCL_LEAVE_ERR_MSG);
| > > > > > > > > < | > | 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 |
if (dictPtr->bytes != NULL) {
Tcl_InvalidateStringRep(dictPtr);
}
goto valueAlreadyInDictionary;
}
}
if (Tcl_DictObjPut(interp, dictPtr, objv[3], valuePtr) != TCL_OK) {
/*
* This shouldn't happen since dictPtr is known
* from above to be a valid dictionary.
*/
if (allocatedDict) {
Tcl_DecrRefCount(dictPtr);
}
Tcl_DecrRefCount(valuePtr);
return TCL_ERROR;
}
}
valueAlreadyInDictionary:
Tcl_IncrRefCount(dictPtr);
resultPtr = Tcl_ObjSetVar2(interp, objv[2], NULL, dictPtr,
TCL_LEAVE_ERR_MSG);
Tcl_DecrRefCount(dictPtr);
if (resultPtr == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
}
/*
|
| ︙ | ︙ | |||
1906 1907 1908 1909 1910 1911 1912 1913 1914 |
if (allocatedValue) {
Tcl_DictObjPut(interp, dictPtr, objv[3], valuePtr);
} else if (dictPtr->bytes != NULL) {
Tcl_InvalidateStringRep(dictPtr);
}
resultPtr = Tcl_ObjSetVar2(interp, objv[2], NULL, dictPtr,
TCL_LEAVE_ERR_MSG);
| > < < | < > | 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 |
if (allocatedValue) {
Tcl_DictObjPut(interp, dictPtr, objv[3], valuePtr);
} else if (dictPtr->bytes != NULL) {
Tcl_InvalidateStringRep(dictPtr);
}
Tcl_IncrRefCount(dictPtr);
resultPtr = Tcl_ObjSetVar2(interp, objv[2], NULL, dictPtr,
TCL_LEAVE_ERR_MSG);
Tcl_DecrRefCount(dictPtr);
if (resultPtr == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
}
/*
|
| ︙ | ︙ | |||
1980 1981 1982 1983 1984 1985 1986 1987 1988 |
for (i=4 ; i<objc ; i++) {
Tcl_AppendObjToObj(valuePtr, objv[i]);
}
Tcl_DictObjPut(interp, dictPtr, objv[3], valuePtr);
resultPtr = Tcl_ObjSetVar2(interp, objv[2], NULL, dictPtr,
TCL_LEAVE_ERR_MSG);
| > < < | < > | 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 |
for (i=4 ; i<objc ; i++) {
Tcl_AppendObjToObj(valuePtr, objv[i]);
}
Tcl_DictObjPut(interp, dictPtr, objv[3], valuePtr);
Tcl_IncrRefCount(dictPtr);
resultPtr = Tcl_ObjSetVar2(interp, objv[2], NULL, dictPtr,
TCL_LEAVE_ERR_MSG);
Tcl_DecrRefCount(dictPtr);
if (resultPtr == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
}
/*
|
| ︙ | ︙ | |||
2184 2185 2186 2187 2188 2189 2190 2191 2192 |
if (result != TCL_OK) {
if (allocatedDict) {
Tcl_DecrRefCount(dictPtr);
}
return TCL_ERROR;
}
resultPtr = Tcl_ObjSetVar2(interp, objv[2], NULL, dictPtr,
TCL_LEAVE_ERR_MSG);
| > < < | < > | 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 |
if (result != TCL_OK) {
if (allocatedDict) {
Tcl_DecrRefCount(dictPtr);
}
return TCL_ERROR;
}
Tcl_IncrRefCount(dictPtr);
resultPtr = Tcl_ObjSetVar2(interp, objv[2], NULL, dictPtr,
TCL_LEAVE_ERR_MSG);
Tcl_DecrRefCount(dictPtr);
if (resultPtr == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
}
/*
|
| ︙ | ︙ | |||
2245 2246 2247 2248 2249 2250 2251 2252 2253 |
if (result != TCL_OK) {
if (allocatedDict) {
Tcl_DecrRefCount(dictPtr);
}
return TCL_ERROR;
}
resultPtr = Tcl_ObjSetVar2(interp, objv[2], NULL, dictPtr,
TCL_LEAVE_ERR_MSG);
| > < < | < > | 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 |
if (result != TCL_OK) {
if (allocatedDict) {
Tcl_DecrRefCount(dictPtr);
}
return TCL_ERROR;
}
Tcl_IncrRefCount(dictPtr);
resultPtr = Tcl_ObjSetVar2(interp, objv[2], NULL, dictPtr,
TCL_LEAVE_ERR_MSG);
Tcl_DecrRefCount(dictPtr);
if (resultPtr == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
}
/*
|
| ︙ | ︙ | |||
2488 2489 2490 2491 2492 2493 2494 |
if (result == TCL_OK) {
Tcl_SetObjResult(interp, resultObj);
} else {
Tcl_DecrRefCount(resultObj);
}
return result;
}
| | | 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 |
if (result == TCL_OK) {
Tcl_SetObjResult(interp, resultObj);
} else {
Tcl_DecrRefCount(resultObj);
}
return result;
}
Tcl_Panic("unexpected fallthrough");
/* Control never reaches this point. */
return TCL_ERROR;
abnormalResult:
Tcl_DictObjDone(&search);
Tcl_DecrRefCount(keyObj);
Tcl_DecrRefCount(valueObj);
|
| ︙ | ︙ | |||
2567 2568 2569 2570 2571 2572 2573 |
case DICT_REMOVE: return DictRemoveCmd(interp, objc, objv);
case DICT_REPLACE: return DictReplaceCmd(interp, objc, objv);
case DICT_SET: return DictSetCmd(interp, objc, objv);
case DICT_SIZE: return DictSizeCmd(interp, objc, objv);
case DICT_UNSET: return DictUnsetCmd(interp, objc, objv);
case DICT_VALUES: return DictValuesCmd(interp, objc, objv);
}
| | | 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 |
case DICT_REMOVE: return DictRemoveCmd(interp, objc, objv);
case DICT_REPLACE: return DictReplaceCmd(interp, objc, objv);
case DICT_SET: return DictSetCmd(interp, objc, objv);
case DICT_SIZE: return DictSizeCmd(interp, objc, objv);
case DICT_UNSET: return DictUnsetCmd(interp, objc, objv);
case DICT_VALUES: return DictValuesCmd(interp, objc, objv);
}
Tcl_Panic("unexpected fallthrough!");
/*
* Next line is NOT REACHED - stops compliler complaint though...
*/
return TCL_ERROR;
}
|
Changes to generic/tclEncoding.c.
1 2 3 4 5 6 7 8 9 10 | /* * tclEncoding.c -- * * Contains the implementation of the encoding conversion package. * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /* * tclEncoding.c -- * * Contains the implementation of the encoding conversion package. * * 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. * * RCS: @(#) $Id: tclEncoding.c,v 1.16.4.1 2004/02/07 05:48:00 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" typedef size_t (LengthProc)_ANSI_ARGS_((CONST char *src)); |
| ︙ | ︙ | |||
2760 2761 2762 2763 2764 2765 2766 |
subTablePtr = &dataPtr->subTables[state];
encodingPtr = subTablePtr->encodingPtr;
if (encodingPtr == NULL) {
encodingPtr = (Encoding *) Tcl_GetEncoding(NULL, subTablePtr->name);
if ((encodingPtr == NULL)
|| (encodingPtr->toUtfProc != TableToUtfProc)) {
| | | 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 |
subTablePtr = &dataPtr->subTables[state];
encodingPtr = subTablePtr->encodingPtr;
if (encodingPtr == NULL) {
encodingPtr = (Encoding *) Tcl_GetEncoding(NULL, subTablePtr->name);
if ((encodingPtr == NULL)
|| (encodingPtr->toUtfProc != TableToUtfProc)) {
Tcl_Panic("EscapeToUtfProc: invalid sub table");
}
subTablePtr->encodingPtr = encodingPtr;
}
return encodingPtr;
}
/*
|
| ︙ | ︙ |
Changes to generic/tclEvent.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* * tclEvent.c -- * * This file implements some general event related interfaces including * background errors, exit handlers, and the "vwait" and "update" * command procedures. * * Copyright (c) 1990-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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* * tclEvent.c -- * * This file implements some general event related interfaces including * background errors, exit handlers, and the "vwait" and "update" * command procedures. * * Copyright (c) 1990-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. * * RCS: @(#) $Id: tclEvent.c,v 1.29.2.2 2004/02/07 05:48:00 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" /* * The data structure below is used to report background errors. One |
| ︙ | ︙ | |||
613 614 615 616 617 618 619 |
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
| | | 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 |
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) status);
Tcl_Panic("AppExitProc returned unexpectedly");
} else {
/* use default handling */
Tcl_Finalize();
TclpExit(status);
|
| ︙ | ︙ | |||
738 739 740 741 742 743 744 |
TclInitSubsystems(argv0)
CONST char *argv0; /* Name of executable from argv[0] to main()
* in native multi-byte encoding. */
{
ThreadSpecificData *tsdPtr;
if (inFinalize != 0) {
| | | 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 |
TclInitSubsystems(argv0)
CONST char *argv0; /* Name of executable from argv[0] to main()
* in native multi-byte encoding. */
{
ThreadSpecificData *tsdPtr;
if (inFinalize != 0) {
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.
|
| ︙ | ︙ | |||
1176 1177 1178 1179 1180 1181 1182 |
}
switch ((enum updateOptions) optionIndex) {
case REGEXP_IDLETASKS: {
flags = TCL_WINDOW_EVENTS|TCL_IDLE_EVENTS|TCL_DONT_WAIT;
break;
}
default: {
| | | 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 |
}
switch ((enum updateOptions) optionIndex) {
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?");
return TCL_ERROR;
}
|
| ︙ | ︙ |
Changes to generic/tclExecute.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* * tclExecute.c -- * * 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. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* * tclExecute.c -- * * 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. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclExecute.c,v 1.101.2.6 2004/02/07 05:48:00 dgp Exp $ */ #include "tclInt.h" #include "tclCompile.h" #ifndef TCL_NO_MATH # include "tclMath.h" |
| ︙ | ︙ | |||
57 58 59 60 61 62 63 64 65 66 67 68 69 70 | * 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. */ # define DBL_MAX 1.79769313486231570e+308 # endif /* MAXDOUBLE */ #endif /* !DBL_MAX */ /* * Boolean flag indicating whether the Tcl bytecode interpreter has been * initialized. */ static int execInitialized = 0; TCL_DECLARE_MUTEX(execMutex) | > > > > > > > > > > | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | * 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. */ # define DBL_MAX 1.79769313486231570e+308 # endif /* MAXDOUBLE */ #endif /* !DBL_MAX */ /* * 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. */ #ifndef ASYNC_CHECK_COUNT_MASK # define ASYNC_CHECK_COUNT_MASK 15 #endif /* !ASYNC_CHECK_COUNT_MASK */ /* * Boolean flag indicating whether the Tcl bytecode interpreter has been * initialized. */ static int execInitialized = 0; TCL_DECLARE_MUTEX(execMutex) |
| ︙ | ︙ | |||
136 137 138 139 140 141 142 | * 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 | | | | | | | | | | | | | 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
* 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
* 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, 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("ERROR: bad usage of macro NEXT_INST_F");\
}\
} else {\
pc += (pcAdjustment);\
switch (nCleanup) {\
case 1: goto cleanup1;\
case 2: goto cleanup2;\
default: Tcl_Panic("ERROR: bad usage of macro NEXT_INST_F");\
}\
}
#define NEXT_INST_V(pcAdjustment, nCleanup, resultHandling) \
pc += (pcAdjustment);\
cleanup = (nCleanup);\
if (resultHandling) {\
if ((resultHandling) > 0) {\
Tcl_IncrRefCount(objResultPtr);\
}\
goto cleanupV_pushObjResultPtr;\
} else {\
goto cleanupV;\
}
|
| ︙ | ︙ | |||
451 452 453 454 455 456 457 |
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) {
| | | 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 |
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) {
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);
#endif /* TCL_COMPILE_STATS */
}
|
| ︙ | ︙ | |||
549 550 551 552 553 554 555 |
void
TclDeleteExecEnv(eePtr)
ExecEnv *eePtr; /* Execution environment to free. */
{
if (eePtr->stackPtr[-1] == (Tcl_Obj *) ((char *) 1)) {
ckfree((char *) (eePtr->stackPtr-1));
} else {
| | | 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 |
void
TclDeleteExecEnv(eePtr)
ExecEnv *eePtr; /* Execution environment to free. */
{
if (eePtr->stackPtr[-1] == (Tcl_Obj *) ((char *) 1)) {
ckfree((char *) (eePtr->stackPtr-1));
} else {
Tcl_Panic("ERROR: freeing an execEnv whose stack is still in use.\n");
}
TclDecrRefCount(eePtr->errorInfo);
TclDecrRefCount(eePtr->errorCode);
ckfree((char *) eePtr);
}
/*
|
| ︙ | ︙ | |||
742 743 744 745 746 747 748 |
if (objPtr->typePtr == &tclByteCodeType) {
codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
if (((Interp *) *codePtr->interpHandle != iPtr)
|| (codePtr->compileEpoch != iPtr->compileEpoch)) {
if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
if ((Interp *) *codePtr->interpHandle != iPtr) {
| | | 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 |
if (objPtr->typePtr == &tclByteCodeType) {
codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
if (((Interp *) *codePtr->interpHandle != iPtr)
|| (codePtr->compileEpoch != iPtr->compileEpoch)) {
if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
if ((Interp *) *codePtr->interpHandle != iPtr) {
Tcl_Panic("Tcl_ExprObj: compiled expression jumped interps");
}
codePtr->compileEpoch = iPtr->compileEpoch;
} else {
(*tclByteCodeType.freeIntRepProc)(objPtr);
objPtr->typePtr = (Tcl_ObjType *) NULL;
}
}
|
| ︙ | ︙ | |||
958 959 960 961 962 963 964 |
|| (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) {
| | | 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 |
|| (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) {
Tcl_Panic("Tcl_EvalObj: compiled script jumped interps");
}
codePtr->compileEpoch = iPtr->compileEpoch;
} else {
/*
* This byteCode is invalid: free it and recompile
*/
tclByteCodeType.freeIntRepProc(objPtr);
|
| ︙ | ︙ | |||
1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 |
Tcl_Obj *valuePtr, *value2Ptr, *objPtr;
char *bytes;
int length;
long i = 0; /* Init. avoids compiler warning. */
Tcl_WideInt w;
int isWide;
register int cleanup;
Tcl_Obj *objResultPtr;
char *part1, *part2;
Var *varPtr, *arrayPtr;
CallFrame *varFramePtr = iPtr->varFramePtr;
#ifdef TCL_COMPILE_DEBUG
int traceInstructions = (tclTraceExec == 3);
char cmdNameBuf[21];
#endif
/*
* The execution uses a unified stack: first the catch stack, immediately
* above it 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
| > > > > | 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 |
Tcl_Obj *valuePtr, *value2Ptr, *objPtr;
char *bytes;
int length;
long i = 0; /* Init. avoids compiler warning. */
Tcl_WideInt w;
int isWide;
register int cleanup;
int objc = 0;
Tcl_Obj *objResultPtr;
Tcl_Obj **objv = NULL, **stackObjArray = NULL;
char *part1, *part2;
Var *varPtr, *arrayPtr;
CallFrame *varFramePtr = iPtr->varFramePtr;
#ifdef TCL_COMPILE_DEBUG
int traceInstructions = (tclTraceExec == 3);
char cmdNameBuf[21];
#endif
int instructionCount = 0; /* Counter that is used to work out
* when to call Tcl_AsyncReady() */
/*
* The execution uses a unified stack: first the catch stack, immediately
* above it 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
|
| ︙ | ︙ | |||
1201 1202 1203 1204 1205 1206 1207 1208 1209 |
fflush(stdout);
}
#endif /* TCL_COMPILE_DEBUG */
#ifdef TCL_COMPILE_STATS
iPtr->stats.instructionCount[*pc]++;
#endif
switch (*pc) {
case INST_RETURN:
| > > > > > > > > > > > > > > > > > > > | > > > > | > > | | | > > | | 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 |
fflush(stdout);
}
#endif /* TCL_COMPILE_DEBUG */
#ifdef TCL_COMPILE_STATS
iPtr->stats.instructionCount[*pc]++;
#endif
/*
* Check for asynchronous handlers [Bug 746722]; we
* do the check every 16th instruction.
*/
if (!(instructionCount++ & ASYNC_CHECK_COUNT_MASK) && Tcl_AsyncReady()) {
DECACHE_STACK_INFO();
result = Tcl_AsyncInvoke(interp, result);
CACHE_STACK_INFO();
if (result == TCL_ERROR) {
goto checkForCatch;
}
}
switch (*pc) {
case INST_RETURN:
{
int code = TclGetInt4AtPtr(pc+1);
int level = TclGetUInt4AtPtr(pc+5);
Tcl_Obj *returnOpts = POP_OBJECT();
DECACHE_STACK_INFO();
Tcl_ResetResult(interp);
result = TclProcessReturn(interp, code, level, returnOpts);
CACHE_STACK_INFO();
Tcl_DecrRefCount(returnOpts);
if (result != TCL_OK) {
Tcl_SetObjResult(interp, *tosPtr);
cleanup = 1;
goto processExceptionReturn;
}
NEXT_INST_F(9, 0, 0);
}
case INST_DONE:
if (tosPtr <= eePtr->stackPtr + initStackTop) {
tosPtr--;
goto abnormalReturn;
}
/*
|
| ︙ | ︙ | |||
1305 1306 1307 1308 1309 1310 1311 |
}
*p = '\0';
}
TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
NEXT_INST_V(2, opnd, 1);
}
| | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < < < < < < < < < | 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 |
}
*p = '\0';
}
TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
NEXT_INST_V(2, opnd, 1);
}
case INST_LIST_VERIFY:
{
int numElements = 0;
valuePtr = *tosPtr;
result = Tcl_ListObjLength(interp, valuePtr, &numElements);
if (result != TCL_OK) {
TRACE_WITH_OBJ(("%.30s => ERROR: ", O2S(valuePtr)),
Tcl_GetObjResult(interp));
goto checkForCatch;
}
NEXT_INST_F(1, 0, 0);
}
case INST_INVOKE_EXP:
{
int numWords = TclGetUInt4AtPtr(pc+1);
int spaceAvailable = eePtr->endPtr - tosPtr;
unsigned char *deltaPtr, *deltaPtrStart = pc+5;
Tcl_Obj **wordv = tosPtr - (numWords - 1);
int objIdx, wordIdx, wordToExpand = -1;
/*
* Compute number of objects needed to store the
* command after expansion is complete.
*/
opnd = objc = numWords;
for (deltaPtr = deltaPtrStart; *deltaPtr; deltaPtr++) {
int numElements;
wordToExpand += TclGetUInt1AtPtr(deltaPtr);
Tcl_ListObjLength(NULL, wordv[wordToExpand], &numElements);
objc += numElements - 1;
}
/*
* We'll store the expanded command in the stack expansion
* space just above tosPtr, assuming there is room. Otherwise,
* allocate enough heap storage to store the expanded command.
*/
objv = stackObjArray = tosPtr + 1;
if (objc > spaceAvailable) {
objv = (Tcl_Obj **) ckalloc((unsigned)
(objc * sizeof(Tcl_Obj *)));
} else {
tosPtr += objc;
}
objIdx = 0;
deltaPtr = deltaPtrStart;
wordToExpand = TclGetUInt1AtPtr(deltaPtr) - 1;
for (wordIdx = 0; wordIdx < numWords; wordIdx++) {
/*
* Copy words (expanding some) from wordv to objv.
* Note that we do not increment refCounts. We
* rely on the references in wordv (on the execution
* stack) to be sufficient to keep the values around
* as long as we need them.
*/
if (wordIdx == wordToExpand) {
int i, numElements;
Tcl_Obj **elements, *temp = wordv[wordIdx];
/*
* Make sure the list we expand is unshared.
* If it is not shared, then the stack holds the
* only reference to it, and there is no danger
* the list will shimmer to another type (and
* possibly free the elements of the list) before
* we are done with the command evaluation.
*/
if (Tcl_IsShared(temp)) {
Tcl_DecrRefCount(temp);
temp = Tcl_DuplicateObj(temp);
Tcl_IncrRefCount(temp);
wordv[wordIdx] = temp;
}
Tcl_ListObjGetElements(NULL, temp, &numElements, &elements);
for (i=0; i<numElements; i++) {
objv[objIdx++] = elements[i];
}
++deltaPtr;
if (*deltaPtr) {
wordToExpand += TclGetUInt1AtPtr(deltaPtr);
} else {
wordToExpand = -1;
}
} else {
objv[objIdx++] = wordv[wordIdx];
}
}
pcAdjustment = (deltaPtr - pc) + 1;
goto doInvocation;
}
case INST_INVOKE_STK4:
opnd = TclGetUInt4AtPtr(pc+1);
objc = opnd;
objv = stackObjArray = (tosPtr - (objc-1));
pcAdjustment = 5;
goto doInvocation;
case INST_INVOKE_STK1:
opnd = TclGetUInt1AtPtr(pc+1);
objc = opnd;
objv = stackObjArray = (tosPtr - (objc-1));
pcAdjustment = 2;
doInvocation:
{
/*
* We keep the stack reference count as a (char *), as that
* works nicely as a portable pointer-sized counter.
*/
char **preservedStackRefCountPtr;
#ifdef TCL_COMPILE_DEBUG
if (tclTraceExec >= 2) {
if (traceInstructions) {
strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
TRACE(("%u => call ", objc));
} else {
fprintf(stdout, "%d: (%u) invoking ",
|
| ︙ | ︙ | |||
1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 |
* because all others are liable to change due to the
* trace procedures.
*/
preservedStackRefCountPtr = (char **) (eePtr->stackPtr-1);
++*preservedStackRefCountPtr;
/*
* Finally, let TclEvalObjvInternal handle the command.
*/
DECACHE_STACK_INFO();
Tcl_ResetResult(interp);
result = TclEvalObjvInternal(interp, objc, objv, bytes, length, 0);
CACHE_STACK_INFO();
/*
* 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) {
/*
* Push the call's object result and continue execution
* with the next instruction.
*/
| > > > > > > > > > > > > > > | 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 |
* because all others are liable to change due to the
* trace procedures.
*/
preservedStackRefCountPtr = (char **) (eePtr->stackPtr-1);
++*preservedStackRefCountPtr;
/*
* Reset the instructionCount variable, since we're about
* to check for async stuff anyway while processing
* TclEvalObjvInternal.
*/
instructionCount = 1;
/*
* Finally, let TclEvalObjvInternal handle the command.
*/
DECACHE_STACK_INFO();
Tcl_ResetResult(interp);
result = TclEvalObjvInternal(interp, objc, objv, bytes, length, 0);
CACHE_STACK_INFO();
/*
* 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 (objv != stackObjArray) {
ckfree((char *) objv);
} else if (*pc == INST_INVOKE_EXP) {
tosPtr -= objc;
}
if (result == TCL_OK) {
/*
* Push the call's object result and continue execution
* with the next instruction.
*/
|
| ︙ | ︙ | |||
2140 2141 2142 2143 2144 2145 2146 |
pcAdjustment = 2; /* FALSE */
doJumpTrue:
{
int b;
valuePtr = *tosPtr;
| > > > > > | > > > > | | > > > > > | 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 |
pcAdjustment = 2; /* FALSE */
doJumpTrue:
{
int b;
valuePtr = *tosPtr;
/*
* The following will be partially resolved at compile
* time and optimised away.
*/
if (((sizeof(long) == sizeof(int)) &&
(valuePtr->typePtr == &tclIntType))
|| (valuePtr->typePtr == &tclBooleanType)) {
b = (int) valuePtr->internalRep.longValue;
} else if ((sizeof(long) != sizeof(int)) &&
(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;
}
}
#ifndef TCL_COMPILE_DEBUG
NEXT_INST_F((b? opnd : pcAdjustment), 1, 0);
#else
if (b) {
if ((*pc == INST_JUMP_TRUE1) || (*pc == INST_JUMP_TRUE4)) {
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_TRUE4)) {
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)));
}
NEXT_INST_F(pcAdjustment, 1, 0);
}
#endif
}
/*
* 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:
{
/*
* Operands must be boolean or numeric. No int->double
* conversions are performed.
*/
|
| ︙ | ︙ | |||
2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 |
/*
* 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 */
case INST_LIST_INDEX_MULTI:
{
/*
* 'lindex' with multiple index args:
*
* Determine the count of index args.
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 |
/*
* 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 */
case INST_LIST_INDEX_IMM:
{
/*** lindex with objc==3 and index in bytecode stream ***/
int listc, idx;
Tcl_Obj **listv;
/*
* Pop the list and get the index
*/
valuePtr = *tosPtr;
opnd = TclGetInt4AtPtr(pc+1);
/*
* Get the contents of the list, making sure that it
* really is a list in the process.
*/
result = Tcl_ListObjGetElements(interp, valuePtr, &listc, &listv);
if (result != TCL_OK) {
TRACE_WITH_OBJ(("\"%.30s\" %d => ERROR: ", O2S(valuePtr), opnd),
Tcl_GetObjResult(interp));
goto checkForCatch;
}
/*
* Select the list item based on the index. Negative
* operand == end-based indexing.
*/
if (opnd < -1) {
idx = opnd+1 + listc;
} else {
idx = opnd;
}
if (idx >= 0 && idx < listc) {
objResultPtr = listv[idx];
} else {
TclNewObj(objResultPtr);
}
TRACE_WITH_OBJ(("\"%.30s\" %d => ", O2S(valuePtr), opnd), objResultPtr);
NEXT_INST_F(5, 1, 1);
}
case INST_LIST_INDEX_MULTI:
{
/*
* 'lindex' with multiple index args:
*
* Determine the count of index args.
|
| ︙ | ︙ | |||
2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 |
}
/*
* Set result
*/
TRACE(("=> %s\n", O2S(objResultPtr)));
NEXT_INST_F(1, 2, -1);
/*
* End of INST_LIST and related instructions.
* ---------------------------------------------------------
*/
case INST_STR_EQ:
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 |
}
/*
* Set result
*/
TRACE(("=> %s\n", O2S(objResultPtr)));
NEXT_INST_F(1, 2, -1);
case INST_LIST_RANGE_IMM:
{
/*** lrange with objc==4 and both indices in bytecode stream ***/
int listc, fromIdx, toIdx;
Tcl_Obj **listv;
/*
* Pop the list and get the indices
*/
valuePtr = *tosPtr;
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 = Tcl_ListObjGetElements(interp, valuePtr, &listc, &listv);
if (result != TCL_OK) {
TRACE_WITH_OBJ(("\"%.30s\" %d %d => ERROR: ", O2S(valuePtr),
fromIdx, toIdx), Tcl_GetObjResult(interp));
goto checkForCatch;
}
/*
* Skip a lot of work if we're about to throw the result away
* (common with uses of [lassign].)
*/
#ifndef TCL_COMPILE_DEBUG
if (*(pc+9) == INST_POP) {
NEXT_INST_F(10, 1, 0);
}
#endif
/*
* Adjust the indices for end-based handling.
*/
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);
}
/*
* End of INST_LIST and related instructions.
* ---------------------------------------------------------
*/
case INST_STR_EQ:
|
| ︙ | ︙ | |||
3729 3730 3731 3732 3733 3734 3735 |
* Call one of the built-in Tcl math functions.
*/
BuiltinFunc *mathFuncPtr;
if ((opnd < 0) || (opnd > LAST_BUILTIN_FUNC)) {
TRACE(("UNRECOGNIZED BUILTIN FUNC CODE %d\n", opnd));
| | | 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 |
* Call one of the built-in Tcl math functions.
*/
BuiltinFunc *mathFuncPtr;
if ((opnd < 0) || (opnd > LAST_BUILTIN_FUNC)) {
TRACE(("UNRECOGNIZED BUILTIN FUNC CODE %d\n", opnd));
Tcl_Panic("TclExecuteByteCode: unrecognized builtin function code %d", opnd);
}
mathFuncPtr = &(tclBuiltinFuncTable[opnd]);
DECACHE_STACK_INFO();
result = (*mathFuncPtr->proc)(interp, eePtr,
mathFuncPtr->clientData);
CACHE_STACK_INFO();
if (result != TCL_OK) {
|
| ︙ | ︙ | |||
4111 4112 4113 4114 4115 4116 4117 |
case INST_PUSH_RETURN_CODE:
objResultPtr = Tcl_NewLongObj(result);
TRACE(("=> %u\n", result));
NEXT_INST_F(1, 0, 1);
default:
| | | 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 |
case INST_PUSH_RETURN_CODE:
objResultPtr = Tcl_NewLongObj(result);
TRACE(("=> %u\n", result));
NEXT_INST_F(1, 0, 1);
default:
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".
*/
|
| ︙ | ︙ | |||
4309 4310 4311 4312 4313 4314 4315 |
TclDecrRefCount(valuePtr);
}
if (tosPtr < initTosPtr) {
fprintf(stderr, "\nTclExecuteByteCode: abnormal return at pc %u: stack top %d < entry stack top %d\n",
(unsigned int)(pc - codePtr->codeStart),
(unsigned int) (tosPtr - eePtr->stackPtr),
(unsigned int) initStackTop);
| | | 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 |
TclDecrRefCount(valuePtr);
}
if (tosPtr < initTosPtr) {
fprintf(stderr, "\nTclExecuteByteCode: abnormal return at pc %u: stack top %d < entry stack top %d\n",
(unsigned int)(pc - codePtr->codeStart),
(unsigned int) (tosPtr - eePtr->stackPtr),
(unsigned int) initStackTop);
Tcl_Panic("TclExecuteByteCode execution failure: end stack top < start stack top");
}
eePtr->tosPtr = initTosPtr - codePtr->maxExceptDepth;
}
return result;
}
#ifdef TCL_COMPILE_DEBUG
|
| ︙ | ︙ | |||
4422 4423 4424 4425 4426 4427 4428 |
unsigned int codeEnd = (unsigned int)
(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);
| | | < | | 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 |
unsigned int codeEnd = (unsigned int)
(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);
Tcl_Panic("TclExecuteByteCode execution failure: bad pc");
}
if ((unsigned int) opCode > LAST_INST_OPCODE) {
fprintf(stderr, "\nBad opcode %d at pc %u in TclExecuteByteCode\n",
(unsigned int) opCode, relativePc);
Tcl_Panic("TclExecuteByteCode execution failure: bad opcode");
}
if ((stackTop < stackLowerBound) || (stackTop > stackUpperBound)) {
int numChars;
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) {
Tcl_Obj *message = Tcl_NewStringObj("\n executing ", -1);
Tcl_IncrRefCount(message);
TclAppendLimitedToObj(message, cmd, numChars, 100, NULL);
fprintf(stderr,"%s\n", Tcl_GetString(message));
Tcl_DecrRefCount(message);
} else {
fprintf(stderr, "\n");
}
Tcl_Panic("TclExecuteByteCode execution failure: bad stack top");
}
}
#endif /* TCL_COMPILE_DEBUG */
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
5639 5640 5641 5642 5643 5644 5645 |
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)) {
| | | 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 |
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)) {
Tcl_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
|
| ︙ | ︙ |
Changes to generic/tclFCmd.c.
1 2 3 4 5 6 7 8 9 10 11 | /* * tclFCmd.c * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * tclFCmd.c * * 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. * * RCS: @(#) $Id: tclFCmd.c,v 1.21.2.2 2004/02/07 05:48:00 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" /* * Declarations for local procedures defined in this file: |
| ︙ | ︙ | |||
237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
for (i = 2; i < objc; i++) {
if (Tcl_FSConvertToPathType(interp, objv[i]) != TCL_OK) {
result = TCL_ERROR;
break;
}
split = Tcl_FSSplitPath(objv[i],&pobjc);
if (pobjc == 0) {
errno = ENOENT;
errfile = objv[i];
break;
}
for (j = 0; j < pobjc; j++) {
target = Tcl_FSJoinPath(split, j + 1);
| > | 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
for (i = 2; i < objc; i++) {
if (Tcl_FSConvertToPathType(interp, objv[i]) != TCL_OK) {
result = TCL_ERROR;
break;
}
split = Tcl_FSSplitPath(objv[i],&pobjc);
Tcl_IncrRefCount(split);
if (pobjc == 0) {
errno = ENOENT;
errfile = objv[i];
break;
}
for (j = 0; j < pobjc; j++) {
target = Tcl_FSJoinPath(split, j + 1);
|
| ︙ | ︙ | |||
520 521 522 523 524 525 526 527 528 529 530 531 532 533 |
&& S_ISDIR(targetStatBuf.st_mode)) {
errno = EISDIR;
Tcl_AppendResult(interp, "can't overwrite directory \"",
Tcl_GetString(target), "\" with file \"",
Tcl_GetString(source), "\"", (char *) NULL);
goto done;
}
}
if (copyFlag == 0) {
result = Tcl_FSRenameFile(source, target);
if (result == TCL_OK) {
goto done;
}
| > > > > > > > > > > > > > > > > | 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 |
&& S_ISDIR(targetStatBuf.st_mode)) {
errno = EISDIR;
Tcl_AppendResult(interp, "can't overwrite directory \"",
Tcl_GetString(target), "\" with file \"",
Tcl_GetString(source), "\"", (char *) 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.
*/
#if !defined(__WIN32__) && !defined(MAC_TCL)
{
Tcl_Obj* perm = Tcl_NewStringObj("u+w",-1);
Tcl_IncrRefCount(perm);
Tcl_FSFileAttrsSet(NULL, 2, target, perm);
Tcl_DecrRefCount(perm);
}
#endif
}
if (copyFlag == 0) {
result = Tcl_FSRenameFile(source, target);
if (result == TCL_OK) {
goto done;
}
|
| ︙ | ︙ | |||
549 550 551 552 553 554 555 |
* the low-level Tcl_FSRenameFileProc in the filesystem is allowed
* to implement cross-filesystem moves itself, if it desires.
*/
}
actualSource = source;
Tcl_IncrRefCount(actualSource);
| < < | > > > > > > | > > | 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 |
* 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
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.
|
| ︙ | ︙ | |||
577 578 579 580 581 582 583 584 585 586 587 588 589 590 |
} else {
int counter = 0;
while (1) {
Tcl_Obj *path = Tcl_FSLink(actualSource, NULL, 0);
if (path == NULL) {
break;
}
Tcl_DecrRefCount(actualSource);
actualSource = path;
counter++;
/* Arbitrary limit of 20 links to follow */
if (counter > 20) {
/* Too many links */
Tcl_SetErrno(EMLINK);
| > > > > > > > > > > > | 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 |
} 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 */
if (counter > 20) {
/* Too many links */
Tcl_SetErrno(EMLINK);
|
| ︙ | ︙ | |||
792 793 794 795 796 797 798 |
Tcl_Obj *pathPtr; /* Path whose basename to extract. */
{
int objc;
Tcl_Obj *splitPtr;
Tcl_Obj *resultPtr = NULL;
splitPtr = Tcl_FSSplitPath(pathPtr, &objc);
| > | > | 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 |
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) == '~')) {
Tcl_DecrRefCount(splitPtr);
if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {
return NULL;
}
splitPtr = Tcl_FSSplitPath(pathPtr, &objc);
Tcl_IncrRefCount(splitPtr);
}
/*
* Return the last component, unless it is the only component, and it
* is the root of an absolute path.
*/
|
| ︙ | ︙ |
Changes to generic/tclFileName.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* * tclFileName.c -- * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* * tclFileName.c -- * * 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. * * RCS: @(#) $Id: tclFileName.c,v 1.41.2.3 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" #include "tclRegexp.h" /* |
| ︙ | ︙ | |||
71 72 73 74 75 76 77 | */ 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)); | | < > > > > | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | */ 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, int 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)); static int DoGlob _ANSI_ARGS_((Tcl_Interp *interp, char *separators, Tcl_Obj *pathPtr, int flags, char *pattern, Tcl_GlobTypeData *types)); #ifdef MAC_UNDERSTANDS_UNIX_PATHS /* *---------------------------------------------------------------------- * * FileNameInit -- * |
| ︙ | ︙ | |||
343 344 345 346 347 348 349 | * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_PathType | | | | > | | | 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
Tcl_PathType
TclpGetNativePathType(pathPtr, driveNameLengthPtr, driveNameRef)
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(pathPtr, &pathLen);
if (path[0] == '~') {
/*
* This case is common to all platforms.
* Paths that begin with ~ are absolute.
*/
if (driveNameLengthPtr != NULL) {
|
| ︙ | ︙ | |||
607 608 609 610 611 612 613 614 615 616 617 618 619 620 |
/*
* Perform the splitting, using objectified, vfs-aware code.
*/
tmpPtr = Tcl_NewStringObj(path, -1);
Tcl_IncrRefCount(tmpPtr);
resultPtr = Tcl_FSSplitPath(tmpPtr, argcPtr);
Tcl_DecrRefCount(tmpPtr);
/* Calculate space required for the result */
size = 1;
for (i = 0; i < *argcPtr; i++) {
Tcl_ListObjIndex(NULL, resultPtr, i, &eltPtr);
| > | 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 |
/*
* Perform the splitting, using objectified, vfs-aware code.
*/
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 */
size = 1;
for (i = 0; i < *argcPtr; i++) {
Tcl_ListObjIndex(NULL, resultPtr, i, &eltPtr);
|
| ︙ | ︙ | |||
1051 1052 1053 1054 1055 1056 1057 | *--------------------------------------------------------------------------- * * 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. | | > > > > > | > | | | | | | > > > > > > > > > > | 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 |
*---------------------------------------------------------------------------
*
* 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.
*
* 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 owned by the caller (which should increment its
* refCount) - typically an object with refCount of zero.
*
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
Tcl_Obj*
Tcl_FSJoinToPath(pathPtr, objc, objv)
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 (pathPtr == NULL) {
lobj = Tcl_NewListObj(0, NULL);
} else {
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;
}
/*
*---------------------------------------------------------------------------
*
* TclpNativeJoinPath --
|
| ︙ | ︙ | |||
1424 1425 1426 1427 1428 1429 1430 | * * Side effects: * None. * *---------------------------------------------------------------------- */ | | | | | 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 |
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
CONST char *
TclGetExtension(name)
CONST char *name; /* File name to parse. */
{
CONST char *p, *lastSep;
/*
* First find the last directory separator.
*/
lastSep = NULL; /* Needed only to prevent gcc warnings. */
switch (tclPlatform) {
|
| ︙ | ︙ | |||
1581 1582 1583 1584 1585 1586 1587 |
enum pathDirOptions {PATH_NONE = -1 , PATH_GENERAL = 0, PATH_DIR = 1};
Tcl_GlobTypeData *globTypes = NULL;
globFlags = 0;
join = 0;
dir = PATH_NONE;
typePtr = NULL;
| < | 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 |
enum pathDirOptions {PATH_NONE = -1 , PATH_GENERAL = 0, PATH_DIR = 1};
Tcl_GlobTypeData *globTypes = NULL;
globFlags = 0;
join = 0;
dir = PATH_NONE;
typePtr = NULL;
for (i = 1; i < objc; i++) {
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
|
| ︙ | ︙ | |||
1607 1608 1609 1610 1611 1612 1613 |
}
switch (index) {
case GLOB_NOCOMPLAIN: /* -nocomplain */
globFlags |= TCL_GLOBMODE_NO_COMPLAIN;
break;
case GLOB_DIR: /* -dir */
if (i == (objc-1)) {
| | | | | | | | | | | | | | 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 |
}
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;
}
}
endOfForLoop:
if (objc - i < 1) {
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));
return TCL_ERROR;
}
separators = NULL; /* lint. */
switch (tclPlatform) {
case TCL_PLATFORM_UNIX:
separators = "/";
|
| ︙ | ︙ | |||
1707 1708 1709 1710 1711 1712 1713 |
/* It's really a directory */
dir = PATH_DIR;
} else {
Tcl_DString pref;
char *search, *find;
Tcl_DStringInit(&pref);
if (last == first) {
| > | > > > > > > | 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 |
/* 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. 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 */
Tcl_DStringAppend(&pref, last, first+pathlength-last);
pathOrDir = Tcl_NewStringObj(first, last-first-1);
}
/* Need to quote 'prefix' */
|
| ︙ | ︙ | |||
1828 1829 1830 1831 1832 1833 1834 | globTypes->macCreator = item; Tcl_IncrRefCount(item); continue; } } } /* | | < | < | < < < < < | 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 |
globTypes->macCreator = item;
Tcl_IncrRefCount(item);
continue;
}
}
}
/*
* Error cases. We reset
* the 'join' flag to zero, since we haven't yet
* made use of it.
*/
badTypesArg:
resultPtr = Tcl_GetObjResult(interp);
Tcl_AppendToObj(resultPtr, "bad argument to \"-types\": ", -1);
Tcl_AppendObjToObj(resultPtr, look);
result = TCL_ERROR;
join = 0;
goto endOfGlob;
badMacTypesArg:
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"only one MacOS type or creator argument"
" to \"-types\" allowed", -1));
result = TCL_ERROR;
join = 0;
goto endOfGlob;
}
}
}
/*
* 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);
}
for (i = 0; i < objc; i++) {
string = Tcl_GetStringFromObj(objv[i], &length);
|
| ︙ | ︙ | |||
1961 1962 1963 1964 1965 1966 1967 | } /* *---------------------------------------------------------------------- * * TclGlob -- * | | | > > > > | | | | | < | < | | > > > | | < < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > | | > | | < < > > > > > > | < < | > > > > > > | > > > > > > > > > | < < | > > > > > > > > > | < | > | < | < > > > | > | | > > > > > > > > | > > | < < > | > > > > > > > > > > > > > > > | | | | | < | | | | | | | < | < < > | < | 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 |
}
/*
*----------------------------------------------------------------------
*
* TclGlob --
*
* 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 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, 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.
*
* Side effects:
* The 'pattern' is written to.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
TclGlob(interp, pattern, pathPrefix, 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 *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;
char *tail, *start;
int result;
Tcl_Obj *oldResult;
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 (pathPrefix == NULL) {
separators = (strchr(pattern, ':') == NULL) ? "/" : ":";
} else {
separators = ":";
}
#else
separators = ":";
#endif
break;
}
if (pathPrefix == NULL) {
char c;
Tcl_DString buffer;
Tcl_DStringInit(&buffer);
start = pattern;
/*
* Perform tilde substitution, if needed.
*/
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;
}
}
/*
* 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.
*/
head = DoTildeSubst(NULL, start+1, &buffer);
} else {
head = DoTildeSubst(interp, start+1, &buffer);
}
*tail = c;
if (head == NULL) {
if (globFlags & TCL_GLOBMODE_NO_COMPLAIN) {
return TCL_OK;
} else {
return TCL_ERROR;
}
}
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;
}
/*
* 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.
*/
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);
}
/*
* ':' 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.
*/
oldResult = Tcl_GetObjResult(interp);
Tcl_IncrRefCount(oldResult);
Tcl_ResetResult(interp);
if (*tail == '\0' && pathPrefix != NULL) {
/*
* An empty pattern
*/
result = Tcl_FSMatchInDirectory(interp, Tcl_GetObjResult(interp),
pathPrefix, NULL, types);
} else {
result = DoGlob(interp, separators, pathPrefix,
globFlags & TCL_GLOBMODE_DIR, 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);
result = TCL_OK;
}
} 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
* 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.
*/
/*
* Ensure sole ownership. We also assume that oldResult
* is a valid list in the code below.
*/
if (Tcl_IsShared(oldResult)) {
Tcl_DecrRefCount(oldResult);
oldResult = Tcl_DuplicateObj(oldResult);
Tcl_IncrRefCount(oldResult);
}
if (globFlags & TCL_GLOBMODE_TAILS) {
int objc, i;
Tcl_Obj **objv;
int prefixLen;
/* If this length has never been set, set it here */
CONST char *pre = Tcl_GetStringFromObj(pathPrefix, &prefixLen);
if (prefixLen > 0) {
if (strchr(separators, pre[prefixLen-1]) == NULL) {
prefixLen++;
}
}
Tcl_ListObjGetElements(NULL, Tcl_GetObjResult(interp),
&objc, &objv);
#ifdef MAC_TCL
/* adjust prefixLen if DoGlob prepended a ':' */
if ((prefixLen > 0) && (objc > 0) && (pre[0] != ':')) {
CONST char *str = Tcl_GetStringFromObj(objv[0],NULL);
if (str[0] == ':') {
prefixLen++;
}
}
#endif
for (i = 0; i< objc; i++) {
Tcl_Obj* elt;
int len;
char *oldStr = Tcl_GetStringFromObj(objv[i],&len);
if (len == prefixLen) {
if ((pattern[0] == '\0')
|| (strchr(separators, pattern[0]) == NULL)) {
elt = Tcl_NewStringObj(".",1);
} else {
elt = Tcl_NewStringObj("/",1);
}
} else {
elt = Tcl_NewStringObj(oldStr + prefixLen,
len - prefixLen);
}
Tcl_ListObjAppendElement(interp, oldResult, elt);
}
} else {
Tcl_ListObjAppendList(interp, oldResult, Tcl_GetObjResult(interp));
}
Tcl_SetObjResult(interp, oldResult);
}
/*
* Release our temporary copy. All code paths above must
* end here so we free our reference.
*/
Tcl_DecrRefCount(oldResult);
return result;
}
/*
*----------------------------------------------------------------------
*
* SkipToChar --
|
| ︙ | ︙ | |||
2219 2220 2221 2222 2223 2224 2225 | * None. * *---------------------------------------------------------------------- */ static int SkipToChar(stringPtr, match) | | | | | | | | | | < < | | | | | | > > | | | < | < < < < < < | | | | | | | | > > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > | | > | > | > | > | < | < | | | > > > > > > > > > > | | | | < | | | | < < < < < < < | < < > > > > | < | > > > > > > > > > > > > > > > > > | > > | | | | | | | | | | | | | > > | > > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | < < < < < < < < < < < | | | | | | | | | | | | | | > > | | | | | < | < | < | | < < < < < < < < < < < < < < < < < < < < < < < < < | < | < < | < < | < < | > | < < | < < < < < < < < < < < < < < < < < < < < | 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 |
* None.
*
*----------------------------------------------------------------------
*/
static int
SkipToChar(stringPtr, match)
char **stringPtr; /* Pointer string to check. */
int match; /* Character to find. */
{
int quoted, level;
register char *p;
quoted = 0;
level = 0;
for (p = *stringPtr; *p != '\0'; p++) {
if (quoted) {
quoted = 0;
continue;
}
if ((level == 0) && (*p == match)) {
*stringPtr = p;
return 1;
}
if (*p == '{') {
level++;
} else if (*p == '}') {
level--;
} else if (*p == '\\') {
quoted = 1;
}
}
*stringPtr = p;
return 0;
}
/*
*----------------------------------------------------------------------
*
* 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 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).
*
* 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 remaining arguments. After an error the
* result in interp will hold an error message.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static int
DoGlob(interp, separators, pathPtr, flags, pattern, types)
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
* boundaries. */
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;
/*
* Consume any leading directory separators, leaving pattern pointing
* just past the last initial separator.
*/
count = 0;
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 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, pattern[1]) != NULL) {
pattern++;
} else {
break;
}
} else if (strchr(separators, *pattern) == NULL) {
break;
}
count++;
}
/*
* 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
* (particularly on MacOS)
*/
#if 0
/*
* Deal with path separators. On the Mac, we have to watch out
* for multiple separators, since they are special in Mac-style
* paths.
*/
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_MAC:
#ifdef MAC_UNDERSTANDS_UNIX_PATHS
if (*separators == '/') {
if (((length == 0) && (count == 0))
|| ((length > 0) && (lastChar != ':'))) {
Tcl_DStringAppend(&append, ":", 1);
}
} else {
#endif
if (count == 0) {
if ((length > 0) && (lastChar != ':')) {
Tcl_DStringAppend(&append, ":", 1);
}
} else {
if (lastChar == ':') {
count--;
}
while (count-- > 0) {
Tcl_DStringAppend(&append, ":", 1);
}
}
#ifdef MAC_UNDERSTANDS_UNIX_PATHS
}
#endif
break;
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.
*/
if (*name == ':') {
Tcl_DStringAppend(&append, ":", 1);
if (count > 1) {
Tcl_DStringAppend(&append, "/", 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(&append, "/", 1);
}
}
break;
case TCL_PLATFORM_UNIX:
/*
* 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
/*
* 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 = pattern; *p != '\0'; p++) {
if (quoted) {
quoted = 0;
} else if (*p == '\\') {
quoted = 1;
if (strchr(separators, p[1]) != NULL) {
/* Quoted directory separator. */
break;
}
} else if (strchr(separators, *p) != NULL) {
/* Unquoted directory separator. */
break;
} else if (*p == '{') {
openBrace = p;
p++;
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);
return TCL_ERROR;
}
}
/*
* Substitute the alternate patterns from the braces and recurse.
*/
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.
*/
Tcl_DStringAppend(&newName, pattern, openBrace-pattern);
baseLength = Tcl_DStringLength(&newName);
*closeBrace = '\0';
for (p = openBrace; p != closeBrace; ) {
p++;
element = p;
SkipToChar(&p, ',');
Tcl_DStringSetLength(&newName, baseLength);
Tcl_DStringAppend(&newName, element, p-element);
Tcl_DStringAppend(&newName, closeBrace+1, -1);
result = DoGlob(interp, separators, pathPtr, flags,
Tcl_DStringValue(&newName), types);
if (result != TCL_OK) {
break;
}
}
*closeBrace = '}';
Tcl_DStringFree(&newName);
return result;
}
/*
* 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.
*/
char savedChar = *p;
*p = '\0';
firstSpecialChar = strpbrk(pattern, "*[]?\\");
*p = savedChar;
} else {
firstSpecialChar = strpbrk(pattern, "*[]?\\");
}
if (firstSpecialChar != NULL) {
int ret;
/*
* 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.
*/
if (*p == '\0') {
ret = Tcl_FSMatchInDirectory(interp, Tcl_GetObjResult(interp),
pathPtr, pattern, types);
} else {
Tcl_Obj* resultPtr;
/*
* 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;
*p = '\0';
resultPtr = Tcl_NewListObj(0, NULL);
ret = Tcl_FSMatchInDirectory(interp, resultPtr,
pathPtr, pattern, &dirOnly);
*p = save;
if (ret == TCL_OK) {
int resLength;
ret = Tcl_ListObjLength(interp, resultPtr, &resLength);
if (ret == TCL_OK) {
int i;
for (i =0; i< resLength; i++) {
Tcl_Obj *elt;
Tcl_ListObjIndex(interp, resultPtr, i, &elt);
ret = DoGlob(interp, separators, elt, 1, p+1, types);
if (ret != TCL_OK) {
break;
}
}
}
}
Tcl_DecrRefCount(resultPtr);
}
return ret;
} else {
/*
* We reach here with no pattern char in current section
*/
if (*p != '\0') {
Tcl_Obj *joined;
int ret;
/*
* If it's not the end of the string, we must recurse
*/
if (pathPtr != NULL) {
if (flags) {
joined = TclNewFSPathObj(pathPtr, pattern, p-pattern);
} else {
joined = Tcl_DuplicateObj(pathPtr);
Tcl_AppendToObj(joined, pattern, p-pattern);
}
} else {
joined = Tcl_NewStringObj(pattern, p-pattern);
}
Tcl_IncrRefCount(joined);
ret = DoGlob(interp, separators, joined, 1, p, types);
Tcl_DecrRefCount(joined);
return ret;
} else {
/*
* 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 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 *joined;
int length;
Tcl_DString append;
Tcl_DStringInit(&append);
Tcl_DStringAppend(&append, pattern, p-pattern);
if (pathPtr != NULL) {
Tcl_GetStringFromObj(pathPtr, &length);
} else {
length = 0;
}
switch (tclPlatform) {
case TCL_PLATFORM_MAC: {
if (strchr(Tcl_DStringValue(&append), ':') == NULL) {
Tcl_DStringAppend(&append, ":", 1);
}
break;
}
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);
}
}
#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(&append), winbuf);
Tcl_DStringFree(&append);
Tcl_DStringAppend(&append, winbuf, -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;
}
}
/* Common for all platforms */
if (pathPtr != NULL) {
if (flags) {
joined = TclNewFSPathObj(pathPtr, Tcl_DStringValue(&append),
Tcl_DStringLength(&append));
} else {
joined = Tcl_DuplicateObj(pathPtr);
Tcl_AppendToObj(joined, Tcl_DStringValue(&append),
Tcl_DStringLength(&append));
}
} else {
joined = Tcl_NewStringObj(Tcl_DStringValue(&append),
Tcl_DStringLength(&append));
}
Tcl_IncrRefCount(joined);
Tcl_DStringFree(&append);
Tcl_FSMatchInDirectory(interp, Tcl_GetObjResult(interp), joined,
NULL, types);
Tcl_DecrRefCount(joined);
return TCL_OK;
}
}
}
/*
*---------------------------------------------------------------------------
*
* Tcl_AllocStatBuf
*
|
| ︙ | ︙ |
Changes to generic/tclFileSystem.h.
1 2 3 4 5 6 7 8 9 10 11 | /* * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * 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. * * RCS: @(#) $Id: tclFileSystem.h,v 1.2.2.3 2004/02/07 05:48:01 dgp Exp $ */ /* * struct FilesystemRecord -- * * A filesystem record is used to keep track of each * filesystem currently registered with the core, |
| ︙ | ︙ | |||
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
* time the corresponding epoch counter changes.
*/
typedef struct ThreadSpecificData {
int initialized;
int cwdPathEpoch;
int filesystemEpoch;
Tcl_Obj *cwdPathPtr;
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.
*/
| > | | | | | | | | 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 |
* 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.
*/
int TclFSCwdPointerEquals _ANSI_ARGS_((Tcl_Obj** pathPtrPtr));
int TclFSMakePathFromNormalized _ANSI_ARGS_((Tcl_Interp *interp,
Tcl_Obj *pathPtr, 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 *pathPtr, Tcl_Obj *cwdPtr));
Tcl_Obj* TclFSInternalToNormalized _ANSI_ARGS_((
Tcl_Filesystem *fromFilesystem, ClientData clientData,
FilesystemRecord **fsRecPtrPtr));
int TclFSEnsureEpochOk _ANSI_ARGS_((Tcl_Obj* pathPtr,
Tcl_Filesystem **fsPtrPtr));
void TclFSSetPathDetails _ANSI_ARGS_((Tcl_Obj *pathPtr,
FilesystemRecord *fsRecPtr, ClientData clientData ));
Tcl_Obj* TclFSNormalizeAbsolutePath _ANSI_ARGS_((Tcl_Interp* interp,
Tcl_Obj *pathPtr, ClientData *clientDataPtr));
/*
* Private shared variables for use by tclIOUtil.c and tclPathObj.c
*/
extern Tcl_Filesystem tclNativeFilesystem;
extern Tcl_ThreadDataKey tclFsDataKey;
/*
* Private shared functions for use by tclIOUtil.c and tclPathObj.c
*/
Tcl_PathType TclFSGetPathType _ANSI_ARGS_((Tcl_Obj *pathPtr,
Tcl_Filesystem **filesystemPtrPtr,
int *driveNameLengthPtr));
Tcl_PathType TclGetPathType _ANSI_ARGS_((Tcl_Obj *pathPtr,
Tcl_Filesystem **filesystemPtrPtr,
int *driveNameLengthPtr, Tcl_Obj **driveNameRef));
Tcl_FSPathInFilesystemProc TclNativePathInFilesystem;
|
Changes to generic/tclHash.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* * tclHash.c -- * * Implementation of in-memory hash tables for Tcl and Tcl-based * applications. * * 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. * | | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | /* * tclHash.c -- * * Implementation of in-memory hash tables for Tcl and Tcl-based * applications. * * 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. * * RCS: @(#) $Id: tclHash.c,v 1.12.4.2 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" /* * Prevent macros from clashing with function definitions. */ #if TCL_PRESERVE_BINARY_COMPATABILITY # undef Tcl_FindHashEntry |
| ︙ | ︙ | |||
188 189 190 191 192 193 194 |
* 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)
| | | 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
* 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)
Tcl_Panic("Tcl_InitCustomHashTable: TCL_SMALL_HASH_TABLE is %d, not 4\n",
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;
|
| ︙ | ︙ | |||
543 544 545 546 547 548 549 |
#endif
if (*bucketPtr == entryPtr) {
*bucketPtr = entryPtr->nextPtr;
} else {
for (prevPtr = *bucketPtr; ; prevPtr = prevPtr->nextPtr) {
if (prevPtr == NULL) {
| | | 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 |
#endif
if (*bucketPtr == entryPtr) {
*bucketPtr = entryPtr->nextPtr;
} else {
for (prevPtr = *bucketPtr; ; prevPtr = prevPtr->nextPtr) {
if (prevPtr == NULL) {
Tcl_Panic("malformed bucket chain in Tcl_DeleteHashEntry");
}
if (prevPtr->nextPtr == entryPtr) {
prevPtr->nextPtr = entryPtr->nextPtr;
break;
}
}
}
|
| ︙ | ︙ | |||
622 623 624 625 626 627 628 |
}
/*
* Free up the bucket array, if it was dynamically allocated.
*/
if (tablePtr->buckets != tablePtr->staticBuckets) {
| > > > | > | 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 |
}
/*
* Free up the bucket array, if it was dynamically allocated.
*/
if (tablePtr->buckets != tablePtr->staticBuckets) {
if (typePtr->flags & TCL_HASH_KEY_SYSTEM_HASH) {
TclpSysFree((char *) tablePtr->buckets);
} else {
ckfree((char *) tablePtr->buckets);
}
}
/*
* Arrange for panics if the table is used again without
* re-initialization.
*/
|
| ︙ | ︙ | |||
741 742 743 744 745 746 747 748 749 750 751 752 753 754 |
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;
/*
* Compute a histogram of bucket usage.
*/
for (i = 0; i < NUM_COUNTERS; i++) {
count[i] = 0;
| > > > > > > > > > > > > > > > > > > > > | 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 |
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;
Tcl_HashKeyType *typePtr;
#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_HashStats on deleted table");
return NULL;
}
#endif
/*
* Compute a histogram of bucket usage.
*/
for (i = 0; i < NUM_COUNTERS; i++) {
count[i] = 0;
|
| ︙ | ︙ | |||
770 771 772 773 774 775 776 |
average += (tmp+1.0)*(tmp/tablePtr->numEntries)/2.0;
}
}
/*
* Print out the histogram and a few other pieces of information.
*/
| | > > | > | 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 |
average += (tmp+1.0)*(tmp/tablePtr->numEntries)/2.0;
}
}
/*
* Print out the histogram and a few other pieces of information.
*/
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);
for (i = 0; i < NUM_COUNTERS; i++) {
sprintf(p, "number of buckets with %d entries: %d\n",
i, count[i]);
p += strlen(p);
|
| ︙ | ︙ | |||
1036 1037 1038 1039 1040 1041 1042 | * * BogusFind -- * * This procedure is invoked when an Tcl_FindHashEntry is called * on a table that has been deleted. * * Results: | | | | 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 |
*
* BogusFind --
*
* This procedure is invoked when an Tcl_FindHashEntry is called
* on a table that has been deleted.
*
* Results:
* If Tcl_Panic returns (which it shouldn't) this procedure returns
* NULL.
*
* Side effects:
* Generates a panic.
*
*----------------------------------------------------------------------
*/
/* 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. */
{
Tcl_Panic("called Tcl_FindHashEntry on deleted table");
return NULL;
}
/*
*----------------------------------------------------------------------
*
* BogusCreate --
|
| ︙ | ︙ | |||
1082 1083 1084 1085 1086 1087 1088 |
BogusCreate(tablePtr, key, newPtr)
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. */
{
| | | 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 |
BogusCreate(tablePtr, key, newPtr)
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. */
{
Tcl_Panic("called Tcl_CreateHashEntry on deleted table");
return NULL;
}
#endif
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
1118 1119 1120 1121 1122 1123 1124 |
int oldSize, count, index;
Tcl_HashEntry **oldBuckets;
register Tcl_HashEntry **oldChainPtr, **newChainPtr;
register Tcl_HashEntry *hPtr;
Tcl_HashKeyType *typePtr;
VOID *key;
| < < < < < < < < < < < < < < < < < < < > > > > > > > > > > > > > > > > > > > > > > > > | 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 |
int oldSize, count, index;
Tcl_HashEntry **oldBuckets;
register Tcl_HashEntry **oldChainPtr, **newChainPtr;
register Tcl_HashEntry *hPtr;
Tcl_HashKeyType *typePtr;
VOID *key;
#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
oldSize = tablePtr->numBuckets;
oldBuckets = tablePtr->buckets;
/*
* Allocate and initialize the new bucket array, and set up
* hashing constants for new array size.
*/
tablePtr->numBuckets *= 4;
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;
}
tablePtr->rebuildSize *= 4;
tablePtr->downShift -= 2;
tablePtr->mask = (tablePtr->mask << 2) + 3;
/*
* Rehash all of the existing entries into the new bucket array.
*/
for (oldChainPtr = oldBuckets; oldSize > 0; oldSize--, oldChainPtr++) {
for (hPtr = *oldChainPtr; hPtr != NULL; hPtr = *oldChainPtr) {
*oldChainPtr = hPtr->nextPtr;
|
| ︙ | ︙ | |||
1196 1197 1198 1199 1200 1201 1202 |
}
/*
* Free up the old bucket array, if it was dynamically allocated.
*/
if (oldBuckets != tablePtr->staticBuckets) {
| > > > | | | > | 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 |
}
/*
* Free up the old bucket array, if it was dynamically allocated.
*/
if (oldBuckets != tablePtr->staticBuckets) {
if (typePtr->flags & TCL_HASH_KEY_SYSTEM_HASH) {
TclpSysFree((char *) oldBuckets);
} else {
ckfree((char *) oldBuckets);
}
}
}
|
Changes to generic/tclIO.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* * tclIO.c -- * * This file provides the generic portions (those that are the same on * all platforms and for all channel types) of Tcl's IO facilities. * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* * tclIO.c -- * * This file provides the generic portions (those that are the same on * all platforms and for all channel types) of Tcl's IO facilities. * * 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. * * RCS: @(#) $Id: tclIO.c,v 1.68.2.1 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" #include "tclIO.h" #include <assert.h> |
| ︙ | ︙ | |||
754 755 756 757 758 759 760 |
* 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) {
| | | | 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 |
* 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) {
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;
}
Tcl_Panic("Tcl_RegisterChannel: duplicate channel names");
}
Tcl_SetHashValue(hPtr, (ClientData) chanPtr);
}
statePtr->refCount++;
}
/*
|
| ︙ | ︙ | |||
1122 1123 1124 1125 1126 1127 1128 |
*/
if (chanName != (char *) NULL) {
char *tmp = ckalloc((unsigned) (strlen(chanName) + 1));
statePtr->channelName = tmp;
strcpy(tmp, chanName);
} else {
| | | 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 |
*/
if (chanName != (char *) NULL) {
char *tmp = ckalloc((unsigned) (strlen(chanName) + 1));
statePtr->channelName = tmp;
strcpy(tmp, chanName);
} else {
Tcl_Panic("Tcl_CreateChannel: NULL channel name");
}
statePtr->flags = mask;
/*
* Set the channel to system default encoding.
*/
|
| ︙ | ︙ | |||
2241 2242 2243 2244 2245 2246 2247 |
/*
* The caller guarantees that there are no more buffers
* queued for output.
*/
if (statePtr->outQueueHead != (ChannelBuffer *) NULL) {
| | | 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 |
/*
* The caller guarantees that there are no more buffers
* queued for output.
*/
if (statePtr->outQueueHead != (ChannelBuffer *) NULL) {
Tcl_Panic("TclFlush, closed channel: queued output left");
}
/*
* If the EOF character is set in the channel, append that to the
* output device.
*/
|
| ︙ | ︙ | |||
2399 2400 2401 2402 2403 2404 2405 |
} else {
for (prevCSPtr = tsdPtr->firstCSPtr;
prevCSPtr && (prevCSPtr->nextCSPtr != statePtr);
prevCSPtr = prevCSPtr->nextCSPtr) {
/* Empty loop body. */
}
if (prevCSPtr == (ChannelState *) NULL) {
| | | 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 |
} else {
for (prevCSPtr = tsdPtr->firstCSPtr;
prevCSPtr && (prevCSPtr->nextCSPtr != statePtr);
prevCSPtr = prevCSPtr->nextCSPtr) {
/* Empty loop body. */
}
if (prevCSPtr == (ChannelState *) NULL) {
Tcl_Panic("FlushChannel: damaged channel list");
}
prevCSPtr->nextCSPtr = statePtr->nextCSPtr;
}
statePtr->nextCSPtr = (ChannelState *) NULL;
TclpCutFileChannel(chan);
|
| ︙ | ︙ | |||
2446 2447 2448 2449 2450 2451 2452 |
* not be referenced in any
* interpreter. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
ChannelState *statePtr = ((Channel *) chan)->state;
if (statePtr->nextCSPtr != (ChannelState *) NULL) {
| | | 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 |
* not be referenced in any
* interpreter. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
ChannelState *statePtr = ((Channel *) chan)->state;
if (statePtr->nextCSPtr != (ChannelState *) NULL) {
Tcl_Panic("Tcl_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
|
| ︙ | ︙ | |||
2523 2524 2525 2526 2527 2528 2529 |
*/
chanPtr = (Channel *) chan;
statePtr = chanPtr->state;
chanPtr = statePtr->topChanPtr;
if (statePtr->refCount > 0) {
| | | 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 |
*/
chanPtr = (Channel *) chan;
statePtr = chanPtr->state;
chanPtr = statePtr->topChanPtr;
if (statePtr->refCount > 0) {
Tcl_Panic("called Tcl_Close on channel with refCount > 0");
}
/*
* 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)
|
| ︙ | ︙ | |||
5050 5051 5052 5053 5054 5055 5056 |
if (statePtr->flags & CHANNEL_STICKY_EOF) {
goto done;
}
statePtr->flags &= (~(CHANNEL_BLOCKED | CHANNEL_EOF));
bufPtr = AllocChannelBuffer(len);
for (i = 0; i < len; i++) {
| | < | 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 |
if (statePtr->flags & CHANNEL_STICKY_EOF) {
goto done;
}
statePtr->flags &= (~(CHANNEL_BLOCKED | CHANNEL_EOF));
bufPtr = AllocChannelBuffer(len);
for (i = 0; i < len; i++) {
bufPtr->buf[bufPtr->nextAdded++] = str[i];
}
if (statePtr->inQueueHead == (ChannelBuffer *) NULL) {
bufPtr->nextPtr = (ChannelBuffer *) NULL;
statePtr->inQueueHead = bufPtr;
statePtr->inQueueTail = bufPtr;
} else if (atEnd) {
bufPtr->nextPtr = (ChannelBuffer *) NULL;
|
| ︙ | ︙ | |||
6062 6063 6064 6065 6066 6067 6068 |
Tcl_DStringAppend(&ds, genericopt, -1);
if (optionList && (*optionList)) {
Tcl_DStringAppend(&ds, " ", 1);
Tcl_DStringAppend(&ds, optionList, -1);
}
if (Tcl_SplitList(interp, Tcl_DStringValue(&ds),
&argc, &argv) != TCL_OK) {
| | | 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 |
Tcl_DStringAppend(&ds, genericopt, -1);
if (optionList && (*optionList)) {
Tcl_DStringAppend(&ds, " ", 1);
Tcl_DStringAppend(&ds, optionList, -1);
}
if (Tcl_SplitList(interp, Tcl_DStringValue(&ds),
&argc, &argv) != TCL_OK) {
Tcl_Panic("malformed option list in channel driver");
}
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "bad option \"", optionName,
"\": should be one of ", (char *) NULL);
argc--;
for (i = 0; i < argc; i++) {
Tcl_AppendResult(interp, "-", argv[i], ", ", (char *) NULL);
|
| ︙ | ︙ | |||
8079 8080 8081 8082 8083 8084 8085 |
statePtr->flags &= ~INPUT_SAW_CR;
}
}
copied = dst - result;
break;
}
default: {
| | | 8078 8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 |
statePtr->flags &= ~INPUT_SAW_CR;
}
}
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.
|
| ︙ | ︙ | |||
8330 8331 8332 8333 8334 8335 8336 |
}
} else {
*dPtr = *sPtr;
}
}
break;
case TCL_TRANSLATE_AUTO:
| | | | 8329 8330 8331 8332 8333 8334 8335 8336 8337 8338 8339 8340 8341 8342 8343 8344 8345 |
}
} 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.
*/
|
| ︙ | ︙ |
Changes to generic/tclIOCmd.c.
1 2 3 4 5 6 7 8 9 10 | /* * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /* * 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. * * RCS: @(#) $Id: tclIOCmd.c,v 1.15.4.1 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" /* * Callback structure for accept callback in a TCP server. |
| ︙ | ︙ | |||
993 994 995 996 997 998 999 | case O_WRONLY: flags |= TCL_STDIN; break; case O_RDWR: flags |= (TCL_STDIN | TCL_STDOUT); break; default: | | | 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 |
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);
}
ckfree((char *) cmdArgv);
#endif
}
|
| ︙ | ︙ | |||
1099 1100 1101 1102 1103 1104 1105 |
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) {
| | | 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 |
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) {
Tcl_Panic("RegisterTcpServerCleanup: damaged accept record table");
}
Tcl_SetHashValue(hPtr, (ClientData) acceptCallbackPtr);
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
1382 1383 1384 1385 1386 1387 1388 |
(char *) NULL);
return TCL_ERROR;
}
script = Tcl_GetString(objv[a]);
break;
}
default: {
| | | 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 |
(char *) NULL);
return TCL_ERROR;
}
script = Tcl_GetString(objv[a]);
break;
}
default: {
Tcl_Panic("Tcl_SocketObjCmd: bad option index to SocketOptions");
}
}
}
if (server) {
host = myaddr; /* NULL implies INADDR_ANY */
if (myport != 0) {
Tcl_AppendResult(interp, "Option -myport is not valid for servers",
|
| ︙ | ︙ |
Changes to generic/tclIOUtil.c.
| ︙ | ︙ | |||
13 14 15 16 17 18 19 | * * 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. * | | | | | | | | > > > | | 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 | * * 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. * * RCS: @(#) $Id: tclIOUtil.c,v 1.81.2.5 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" #ifdef MAC_TCL #include "tclMacInt.h" #endif #ifdef __WIN32__ /* for tclWinProcs->useWide */ #include "tclWinInt.h" #endif #include "tclFileSystem.h" /* * Prototypes for procedures defined later in this file. */ static FilesystemRecord* FsGetFirstFilesystem _ANSI_ARGS_((void)); static void FsThrExitProc _ANSI_ARGS_((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 void FsUpdateCwd _ANSI_ARGS_((Tcl_Obj *cwdObj, ClientData clientData)); #ifdef TCL_THREADS 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 |
| ︙ | ︙ | |||
293 294 295 296 297 298 299 | * 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; | < < | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | * 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). */ 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; |
| ︙ | ︙ | |||
338 339 340 341 342 343 344 |
* 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),
| | | 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
* 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_2,
&TclNativePathInFilesystem,
&TclNativeDupInternalRep,
&NativeFreeInternalRep,
&TclpNativeToNormalized,
&NativeCreateNativeRep,
&TclpObjNormalizePath,
&TclpFilesystemPathType,
|
| ︙ | ︙ | |||
369 370 371 372 373 374 375 |
&TclpObjRemoveDirectory,
&TclpObjDeleteFile,
&TclpObjCopyFile,
&TclpObjRenameFile,
&TclpObjCopyDirectory,
&TclpObjLstat,
&TclpDlopen,
| > | | 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 |
&TclpObjRemoveDirectory,
&TclpObjDeleteFile,
&TclpObjCopyFile,
&TclpObjRenameFile,
&TclpObjCopyDirectory,
&TclpObjLstat,
&TclpDlopen,
/* 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
|
| ︙ | ︙ | |||
411 412 413 414 415 416 417 418 419 420 421 422 423 424 | TCL_DECLARE_MUTEX(filesystemMutex) /* * Used to implement Tcl_FSGetCwd in a file-system independent way. */ static Tcl_Obj* cwdPathPtr = NULL; static int cwdPathEpoch = 0; TCL_DECLARE_MUTEX(cwdMutex) Tcl_ThreadDataKey tclFsDataKey; /* * Declare fallback support function and * information for Tcl_FSLoadFile | > | 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 | 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) Tcl_ThreadDataKey tclFsDataKey; /* * Declare fallback support function and * information for Tcl_FSLoadFile |
| ︙ | ︙ | |||
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 |
ThreadSpecificData *tsdPtr = (ThreadSpecificData*)cd;
FilesystemRecord *fsRecPtr = NULL, *tmpFsRecPtr = NULL;
/* Trash the cwd copy */
if (tsdPtr->cwdPathPtr != NULL) {
Tcl_DecrRefCount(tsdPtr->cwdPathPtr);
}
/* Trash the filesystems cache */
fsRecPtr = tsdPtr->filesystemList;
while (fsRecPtr != NULL) {
tmpFsRecPtr = fsRecPtr->nextPtr;
if (--fsRecPtr->fileRefCount <= 0) {
ckfree((char *)fsRecPtr);
}
fsRecPtr = tmpFsRecPtr;
}
}
int
| > > > > > > > > > > > > > > > > > > > > > > > > | | | > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > | 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 |
ThreadSpecificData *tsdPtr = (ThreadSpecificData*)cd;
FilesystemRecord *fsRecPtr = NULL, *tmpFsRecPtr = NULL;
/* Trash the cwd copy */
if (tsdPtr->cwdPathPtr != NULL) {
Tcl_DecrRefCount(tsdPtr->cwdPathPtr);
}
if (tsdPtr->cwdClientData != NULL) {
NativeFreeInternalRep(tsdPtr->cwdClientData);
}
/* Trash the filesystems cache */
fsRecPtr = tsdPtr->filesystemList;
while (fsRecPtr != NULL) {
tmpFsRecPtr = fsRecPtr->nextPtr;
if (--fsRecPtr->fileRefCount <= 0) {
ckfree((char *)fsRecPtr);
}
fsRecPtr = tmpFsRecPtr;
}
}
/*
*----------------------------------------------------------------------
*
* 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(pathPtrPtr)
Tcl_Obj** pathPtrPtr;
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
Tcl_MutexLock(&cwdMutex);
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);
}
if (cwdClientData == NULL) {
tsdPtr->cwdClientData = NULL;
} else {
tsdPtr->cwdClientData = TclNativeDupInternalRep(cwdClientData);
}
tsdPtr->cwdPathEpoch = cwdPathEpoch;
}
Tcl_MutexUnlock(&cwdMutex);
if (tsdPtr->initialized == 0) {
Tcl_CreateThreadExitHandler(FsThrExitProc, (ClientData)tsdPtr);
tsdPtr->initialized = 1;
}
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
static void
FsRecacheFilesystemList(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
|
| ︙ | ︙ | |||
564 565 566 567 568 569 570 571 |
}
Tcl_MutexUnlock(&filesystemMutex);
fsRecPtr = tsdPtr->filesystemList;
#endif
return fsRecPtr;
}
static void
| > > > | > > > > > > > > > > > | 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 |
}
Tcl_MutexUnlock(&filesystemMutex);
fsRecPtr = tsdPtr->filesystemList;
#endif
return fsRecPtr;
}
/*
* If non-NULL, clientData is owned by us and must be freed later.
*/
static void
FsUpdateCwd(cwdObj, clientData)
Tcl_Obj *cwdObj;
ClientData clientData;
{
int len;
char *str = NULL;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
if (cwdObj != NULL) {
str = Tcl_GetStringFromObj(cwdObj, &len);
}
Tcl_MutexLock(&cwdMutex);
if (cwdPathPtr != NULL) {
Tcl_DecrRefCount(cwdPathPtr);
}
if (cwdClientData != NULL) {
NativeFreeInternalRep(cwdClientData);
}
if (cwdObj == NULL) {
cwdPathPtr = NULL;
cwdClientData = NULL;
} else {
/* 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);
}
if (tsdPtr->cwdClientData) {
NativeFreeInternalRep(tsdPtr->cwdClientData);
}
if (cwdObj == NULL) {
tsdPtr->cwdPathPtr = NULL;
tsdPtr->cwdClientData = NULL;
} else {
tsdPtr->cwdPathPtr = Tcl_NewStringObj(str, len);
tsdPtr->cwdClientData = clientData;
Tcl_IncrRefCount(tsdPtr->cwdPathPtr);
}
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
625 626 627 628 629 630 631 |
*
*----------------------------------------------------------------------
*/
void
TclFinalizeFilesystem()
{
| | > > > > | | 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 |
*
*----------------------------------------------------------------------
*/
void
TclFinalizeFilesystem()
{
FilesystemRecord *fsRecPtr;
/*
* 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;
}
if (cwdClientData != NULL) {
NativeFreeInternalRep(cwdClientData);
cwdClientData = NULL;
}
/*
* 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 */
if (fsRecPtr != &nativeFilesystemRecord) {
ckfree((char *)fsRecPtr);
}
}
fsRecPtr = tmpFsRecPtr;
|
| ︙ | ︙ | |||
918 919 920 921 922 923 924 |
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.
* May be NULL. In particular the directory
* flag is very important. */
{
| > > > > > > > > > > > > > | > > > > | 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 |
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.
* May be NULL. In particular the directory
* flag is very important. */
{
Tcl_Filesystem *fsPtr;
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;
}
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);
|
| ︙ | ︙ | |||
1020 1021 1022 1023 1024 1025 1026 | * Side effects: * None. * *---------------------------------------------------------------------- */ static Tcl_Obj* FsAddMountsToGlobResult(result, pathPtr, pattern, types) | | | | | > > | 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 |
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
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; /* 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;
|
| ︙ | ︙ | |||
1230 1231 1232 1233 1234 1235 1236 | * 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) | | | | | > > > | 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 |
* 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; /* 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;
/*
* Call each of the "normalise path" functions in succession. This is
|
| ︙ | ︙ | |||
1493 1494 1495 1496 1497 1498 1499 |
*/
int
Tcl_FSEvalFileEx(interp, pathPtr, encodingName)
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. */
| | > | 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 |
*/
int
Tcl_FSEvalFileEx(interp, pathPtr, encodingName)
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. */
{
int result;
Tcl_StatBuf statBuf;
Tcl_Obj *oldScriptFile;
Interp *iPtr;
Tcl_Channel chan;
Tcl_Obj *objPtr;
|
| ︙ | ︙ | |||
1536 1537 1538 1539 1540 1541 1542 |
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.
*/
| | | 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 |
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);
goto end;
}
}
if (Tcl_ReadChars(chan, objPtr, -1, 0) < 0) {
|
| ︙ | ︙ | |||
2304 2305 2306 2307 2308 2309 2310 |
* succeeded.
*/
fsRecPtr = FsGetFirstFilesystem();
while ((retVal == NULL) && (fsRecPtr != NULL)) {
Tcl_FSGetCwdProc *proc = fsRecPtr->fsPtr->getCwdProc;
if (proc != NULL) {
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 |
* succeeded.
*/
fsRecPtr = FsGetFirstFilesystem();
while ((retVal == NULL) && (fsRecPtr != NULL)) {
Tcl_FSGetCwdProc *proc = fsRecPtr->fsPtr->getCwdProc;
if (proc != NULL) {
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 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.
*/
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), (char *) 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.
|
| ︙ | ︙ | |||
2331 2332 2333 2334 2335 2336 2337 | * 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. */ | > | > | 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 |
* 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.
*/
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
|
| ︙ | ︙ | |||
2355 2356 2357 2358 2359 2360 2361 2362 |
* (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;
if (proc != NULL) {
| > | > > > > > > > > > > > > > > > > > > > > | > > > > > > > | > | > | 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 |
* (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;
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), (char *) 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.
*/
if (norm == NULL) {
/* Do nothing */
if (retCd != NULL) {
(*fsPtr->freeInternalRepProc)(retCd);
}
} 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 {
FsUpdateCwd(norm, retCd);
Tcl_DecrRefCount(norm);
}
Tcl_DecrRefCount(retVal);
} else {
/* The 'cwd' function returned an error; reset the cwd */
FsUpdateCwd(NULL, NULL);
}
}
}
}
cdDidNotChange:
if (tsdPtr->cwdPathPtr != NULL) {
Tcl_IncrRefCount(tsdPtr->cwdPathPtr);
}
return tsdPtr->cwdPathPtr;
}
|
| ︙ | ︙ | |||
2468 2469 2470 2471 2472 2473 2474 |
* will have been cached as a result of the
* Tcl_FSGetFileSystemForPath call above anyway).
*/
Tcl_Obj *normDirName = Tcl_FSGetNormalizedPath(NULL, pathPtr);
if (normDirName == NULL) {
return TCL_ERROR;
}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | | | | | | 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 |
* will have been cached as a result of the
* Tcl_FSGetFileSystemForPath call above anyway).
*/
Tcl_Obj *normDirName = Tcl_FSGetNormalizedPath(NULL, pathPtr);
if (normDirName == NULL) {
return TCL_ERROR;
}
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.
*/
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
ClientData cd;
/* Assumption we are using a filesystem version 2 */
TclFSGetCwdProc2 *proc2 = (TclFSGetCwdProc2*)fsPtr->getCwdProc;
cd = (*proc2)(tsdPtr->cwdClientData);
FsUpdateCwd(normDirName, TclNativeDupInternalRep(cd));
} else {
FsUpdateCwd(normDirName, NULL);
}
}
} else {
Tcl_SetErrno(ENOENT);
}
return (retVal);
}
/*
*----------------------------------------------------------------------
*
* 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 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.
*
|
| ︙ | ︙ | |||
2519 2520 2521 2522 2523 2524 2525 2526 2527 |
CONST char *sym1, *sym2; /* Names of two procedures to look up in
* the file's symbol table. */
Tcl_PackageInitProc **proc1Ptr, **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
* (*unloadProcPtr)() to unload the file. */
Tcl_FSUnloadFileProc **unloadProcPtr;
| | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > | < < > > | 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 |
CONST char *sym1, *sym2; /* Names of two procedures to look up in
* the file's symbol table. */
Tcl_PackageInitProc **proc1Ptr, **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
* (*unloadProcPtr)() to unload the file. */
Tcl_FSUnloadFileProc **unloadProcPtr;
/* Filled with address of Tcl_FSUnloadFileProc
* function which should be used for
* this file. */
{
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 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 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(interp, pathPtr, symc, symbols, procPtrs,
handlePtr, clientDataPtr, unloadProcPtr)
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 procedures 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. */
{
Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
if (fsPtr != NULL) {
Tcl_FSLoadFileProc *proc = fsPtr->loadFileProc;
if (proc != NULL) {
int i;
int retVal = (*proc)(interp, pathPtr, handlePtr, unloadProcPtr);
if (retVal != TCL_OK) {
return retVal;
}
if (*handlePtr == NULL) {
return TCL_ERROR;
}
for (i = 0;i < symc;i++) {
if (symbols[i] != NULL) {
*procPtrs[i] = TclpFindSymbol(interp, *handlePtr,
symbols[i]);
}
}
/* Copy this across, since both are equal for the native fs */
*clientDataPtr = (ClientData)*handlePtr;
return retVal;
} else {
Tcl_Filesystem *copyFsPtr;
Tcl_Obj *copyToPtr;
/* First check if it is readable -- and exists! */
if (Tcl_FSAccess(pathPtr, R_OK) != 0) {
|
| ︙ | ︙ | |||
2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 |
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
| > | 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 |
Tcl_DecrRefCount(copyToPtr);
return -1;
}
if (TclCrossFilesystemCopy(interp, pathPtr,
copyToPtr) == TCL_OK) {
Tcl_LoadHandle newLoadHandle = NULL;
ClientData newClientData = NULL;
Tcl_FSUnloadFileProc *newUnloadProcPtr = NULL;
FsDivertLoad *tvdlPtr;
int retVal;
#if !defined(__WIN32__) && !defined(MAC_TCL)
/*
* Do we need to set appropriate permissions
|
| ︙ | ︙ | |||
2608 2609 2610 2611 2612 2613 2614 | /* * 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); | | < | > | | 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 |
/*
* 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 = 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;
}
/*
|
| ︙ | ︙ | |||
2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 | * 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. | > | 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 | * 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; return TCL_OK; } /* * When we unload this file, we need to divert the * unloading so we can unload and cleanup the * temporary file correctly. |
| ︙ | ︙ | |||
2680 2681 2682 2683 2684 2685 2686 | */ tvdlPtr->divertedFile = NULL; tvdlPtr->divertedFilesystem = NULL; Tcl_DecrRefCount(copyToPtr); } copyToPtr = NULL; | | > | 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 |
*/
tvdlPtr->divertedFile = NULL;
tvdlPtr->divertedFilesystem = NULL;
Tcl_DecrRefCount(copyToPtr);
}
copyToPtr = NULL;
(*handlePtr) = newLoadHandle;
(*clientDataPtr) = (ClientData)tvdlPtr;
(*unloadProcPtr) = &FSUnloadTempFile;
return retVal;
} else {
/* Cross-platform copy failed */
Tcl_FSDeleteFile(copyToPtr);
Tcl_DecrRefCount(copyToPtr);
return TCL_ERROR;
|
| ︙ | ︙ | |||
2973 2974 2975 2976 2977 2978 2979 |
CONST char *pattern; /* Pattern to match against. */
{
FilesystemRecord *fsRecPtr;
Tcl_GlobTypeData mountsOnly = { TCL_GLOB_TYPE_MOUNT, 0, NULL, NULL };
Tcl_Obj *resultPtr = NULL;
/*
| | > | | | | 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 |
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 "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 != &nativeFilesystemRecord) {
Tcl_FSMatchInDirectoryProc *proc =
fsRecPtr->fsPtr->matchInDirectoryProc;
|
| ︙ | ︙ | |||
3139 3140 3141 3142 3143 3144 3145 | * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_PathType | | | | > > > | | | 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 |
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
Tcl_PathType
TclGetPathType(pathPtr, filesystemPtrPtr, driveNameLengthPtr, driveNameRef)
Tcl_Obj *pathPtr; /* Path to determine type for */
Tcl_Filesystem **filesystemPtrPtr; /* If absolute path and this is
* non-NULL, then set to the
* filesystem which claims this
* path */
int *driveNameLengthPtr;
Tcl_Obj **driveNameRef;
{
FilesystemRecord *fsRecPtr;
int pathLen;
char *path;
Tcl_PathType type = TCL_PATH_RELATIVE;
path = Tcl_GetStringFromObj(pathPtr, &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).
*/
|
| ︙ | ︙ | |||
3194 3195 3196 3197 3198 3199 3200 | /* * 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 | | | 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 |
/*
* 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) {
Tcl_Obj *vol;
int len;
char *strVol;
|
| ︙ | ︙ | |||
3235 3236 3237 3238 3239 3240 3241 |
}
}
}
fsRecPtr = fsRecPtr->nextPtr;
}
if (type != TCL_PATH_ABSOLUTE) {
| | | 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 |
}
}
}
fsRecPtr = fsRecPtr->nextPtr;
}
if (type != TCL_PATH_ABSOLUTE) {
type = TclpGetNativePathType(pathPtr, driveNameLengthPtr,
driveNameRef);
if ((type == TCL_PATH_ABSOLUTE) && (filesystemPtrPtr != NULL)) {
*filesystemPtrPtr = &tclNativeFilesystem;
}
}
return type;
}
|
| ︙ | ︙ | |||
3555 3556 3557 3558 3559 3560 3561 |
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]'
*/
| | > | 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 |
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);
}
}
|
| ︙ | ︙ | |||
3590 3591 3592 3593 3594 3595 3596 | * Side effects: * The object may be converted to a path type. * *--------------------------------------------------------------------------- */ Tcl_Filesystem* | | | | | | | | | | | | 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 |
* Side effects:
* The object may be converted to a path type.
*
*---------------------------------------------------------------------------
*/
Tcl_Filesystem*
Tcl_FSGetFileSystemForPath(pathPtr)
Tcl_Obj* pathPtr;
{
FilesystemRecord *fsRecPtr;
Tcl_Filesystem* retVal = NULL;
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 (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.
*/
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.
*/
fsRecPtr = FsGetFirstFilesystem();
while ((retVal == NULL) && (fsRecPtr != NULL)) {
Tcl_FSPathInFilesystemProc *proc = fsRecPtr->fsPtr->pathInFilesystemProc;
if (proc != NULL) {
ClientData clientData = NULL;
int ret = (*proc)(pathPtr, &clientData);
if (ret != -1) {
/*
* We assume the type of pathPtr hasn't been changed
* by the above call to the pathInFilesystemProc.
*/
TclFSSetPathDetails(pathPtr, fsRecPtr, clientData);
retVal = fsRecPtr->fsPtr;
}
}
fsRecPtr = fsRecPtr->nextPtr;
}
return retVal;
|
| ︙ | ︙ | |||
3681 3682 3683 3684 3685 3686 3687 | * Side effects: * See Tcl_FSGetInternalRep. * *--------------------------------------------------------------------------- */ CONST char * | | | | | | | > > > > > | | > | > | > > > > > > < > > > > > > > > > > > | 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 |
* Side effects:
* See Tcl_FSGetInternalRep.
*
*---------------------------------------------------------------------------
*/
CONST char *
Tcl_FSGetNativePath(pathPtr)
Tcl_Obj *pathPtr;
{
return (CONST char *)Tcl_FSGetInternalRep(pathPtr, &tclNativeFilesystem);
}
/*
*---------------------------------------------------------------------------
*
* NativeCreateNativeRep --
*
* Create a native representation for the given path.
*
* Results:
* None.
*
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
static ClientData
NativeCreateNativeRep(pathPtr)
Tcl_Obj* pathPtr;
{
char *nativePathPtr;
Tcl_DString ds;
Tcl_Obj* validPathPtr;
int len;
char *str;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
if (tsdPtr->cwdClientData != NULL) {
/* The cwd is native */
validPathPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
} else {
/* Make sure the normalized path is set */
validPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
Tcl_IncrRefCount(validPathPtr);
}
str = Tcl_GetStringFromObj(validPathPtr, &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
Tcl_DecrRefCount(validPathPtr);
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.
*
* 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 clientData;
{
Tcl_DString ds;
Tcl_Obj *objPtr;
int len;
#ifdef __WIN32__
char *copy;
char *p;
Tcl_WinTCharToUtf((CONST char*)clientData, -1, &ds);
#else
CONST char *copy;
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;
}
}
/*
* Ensure we are using forward slashes only.
*/
for (p = copy; *p != '\0'; p++) {
if (*p == '\\') {
*p = '/';
}
}
#endif
objPtr = Tcl_NewStringObj(copy,len);
Tcl_DStringFree(&ds);
return objPtr;
|
| ︙ | ︙ | |||
3812 3813 3814 3815 3816 3817 3818 |
*
*---------------------------------------------------------------------------
*/
ClientData
TclNativeDupInternalRep(clientData)
ClientData clientData;
{
| | | | | 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 |
*
*---------------------------------------------------------------------------
*/
ClientData
TclNativeDupInternalRep(clientData)
ClientData clientData;
{
char *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 = (char *) ckalloc(len);
memcpy((VOID*)copy, (VOID*)clientData, len);
return (ClientData)copy;
}
/*
*---------------------------------------------------------------------------
*
* NativeFreeInternalRep --
*
|
| ︙ | ︙ | |||
3878 3879 3880 3881 3882 3883 3884 | * * Side effects: * The object may be converted to a path type. * *--------------------------------------------------------------------------- */ Tcl_Obj* | | | | | | 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 |
*
* Side effects:
* The object may be converted to a path type.
*
*---------------------------------------------------------------------------
*/
Tcl_Obj*
Tcl_FSFileSystemInfo(pathPtr)
Tcl_Obj* pathPtr;
{
Tcl_Obj *resPtr;
Tcl_FSFilesystemPathTypeProc *proc;
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));
proc = fsPtr->filesystemPathTypeProc;
if (proc != NULL) {
Tcl_Obj *typePtr = (*proc)(pathPtr);
if (typePtr != NULL) {
Tcl_ListObjAppendElement(NULL, resPtr, typePtr);
}
}
return resPtr;
}
|
| ︙ | ︙ | |||
3924 3925 3926 3927 3928 3929 3930 | * * Side effects: * The path object may be converted to a path type. * *--------------------------------------------------------------------------- */ Tcl_Obj* | | | | | | 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 |
*
* Side effects:
* The path object may be converted to a path type.
*
*---------------------------------------------------------------------------
*/
Tcl_Obj*
Tcl_FSPathSeparator(pathPtr)
Tcl_Obj* pathPtr;
{
Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
if (fsPtr == NULL) {
return NULL;
}
if (fsPtr->filesystemSeparatorProc != NULL) {
return (*fsPtr->filesystemSeparatorProc)(pathPtr);
}
return NULL;
}
/*
*---------------------------------------------------------------------------
|
| ︙ | ︙ | |||
3956 3957 3958 3959 3960 3961 3962 | * * Side effects: * None. * *--------------------------------------------------------------------------- */ static Tcl_Obj* | | | | 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 |
*
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
static Tcl_Obj*
NativeFilesystemSeparator(pathPtr)
Tcl_Obj* pathPtr;
{
char *separator = NULL; /* lint */
switch (tclPlatform) {
case TCL_PLATFORM_UNIX:
separator = "/";
break;
case TCL_PLATFORM_WINDOWS:
|
| ︙ | ︙ |
Changes to generic/tclIndexObj.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* * 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. * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* * 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. * * 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. * * RCS: @(#) $Id: tclIndexObj.c,v 1.16.4.1 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" /* * Prototypes for procedures defined later in this file: |
| ︙ | ︙ | |||
267 268 269 270 271 272 273 |
error:
if (interp != NULL) {
/*
* Produce a fancy error message.
*/
int count;
| > > | | 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
error:
if (interp != NULL) {
/*
* Produce a fancy error message.
*/
int count;
TclNewObj(resultPtr);
Tcl_SetObjResult(interp, resultPtr);
Tcl_AppendStringsToObj(resultPtr,
(numAbbrev > 1) ? "ambiguous " : "bad ", msg, " \"",
key, "\": must be ", STRING_AT(tablePtr,offset,0), (char*)NULL);
for (entryPtr = NEXT_ENTRY(tablePtr, offset), count = 0;
*entryPtr != NULL;
entryPtr = NEXT_ENTRY(entryPtr, offset), count++) {
if (*NEXT_ENTRY(entryPtr, offset) == NULL) {
|
| ︙ | ︙ | |||
446 447 448 449 450 451 452 |
* leading objects in objv. The
* message may be NULL. */
{
Tcl_Obj *objPtr;
int i;
register IndexRep *indexRep;
| > | | 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 |
* leading objects in objv. The
* message may be NULL. */
{
Tcl_Obj *objPtr;
int i;
register IndexRep *indexRep;
TclNewObj(objPtr);
Tcl_SetObjResult(interp, objPtr);
Tcl_AppendToObj(objPtr, "wrong # args: should be \"", -1);
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.
*/
|
| ︙ | ︙ |
Changes to generic/tclInt.decls.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | # # Copyright (c) 1998-1999 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. # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # # Copyright (c) 1998-1999 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. # # RCS: @(#) $Id: tclInt.decls,v 1.61.2.3 2004/02/07 05:48:01 dgp Exp $ library tcl # Define the unsupported generic interfaces. interface tclInt |
| ︙ | ︙ | |||
71 72 73 74 75 76 77 |
}
declare 11 generic {
void TclDeleteCompiledLocalVars(Interp *iPtr, CallFrame *framePtr)
}
declare 12 generic {
void TclDeleteVars(Interp *iPtr, Tcl_HashTable *tablePtr)
}
| > | | | < > | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
}
declare 11 generic {
void TclDeleteCompiledLocalVars(Interp *iPtr, CallFrame *framePtr)
}
declare 12 generic {
void TclDeleteVars(Interp *iPtr, Tcl_HashTable *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)
}
# Removed in 8.1:
# declare 15 generic {
# void TclExpandParseValue(ParseValue *pvPtr, int needed)
# }
|
| ︙ | ︙ | |||
136 137 138 139 140 141 142 |
# int localIndex, Tcl_Obj *elemPtr, int flags)
#}
# Replaced by char *TclGetEnv(CONST char *name, Tcl_DString *valuePtr) in 8.1:
# declare 30 generic {
# char *TclGetEnv(CONST char *name)
# }
declare 31 generic {
| | | 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# int localIndex, Tcl_Obj *elemPtr, int flags)
#}
# Replaced by char *TclGetEnv(CONST char *name, Tcl_DString *valuePtr) in 8.1:
# declare 30 generic {
# char *TclGetEnv(CONST char *name)
# }
declare 31 generic {
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)
|
| ︙ | ︙ | |||
523 524 525 526 527 528 529 |
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)
}
| | | < > | 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 |
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)
#}
# Added in 8.1:
#declare 137 generic {
# int TclpChdir(CONST char *dirName)
#}
declare 138 generic {
|
| ︙ | ︙ | |||
721 722 723 724 725 726 727 728 729 730 731 732 733 734 |
declare 178 generic {
void Tcl_SetStartupScript(Tcl_Obj *pathPtr, CONST char* encodingName)
}
declare 179 generic {
Tcl_Obj *Tcl_GetStartupScript(CONST char **encodingNamePtr)
}
##############################################################################
# Define the platform specific internal Tcl interface. These functions are
# only available on the designated platform.
interface tclIntPlat
| > > > > > > > > > | 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 |
declare 178 generic {
void Tcl_SetStartupScript(Tcl_Obj *pathPtr, CONST char* encodingName)
}
declare 179 generic {
Tcl_Obj *Tcl_GetStartupScript(CONST char **encodingNamePtr)
}
# 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.
interface tclIntPlat
|
| ︙ | ︙ |
Changes to generic/tclInt.h.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | * Copyright (c) 1994-1998 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 2001, 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. * | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | * Copyright (c) 1994-1998 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 2001, 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. * * RCS: @(#) $Id: tclInt.h,v 1.127.2.6 2004/02/07 05:48:01 dgp Exp $ */ #ifndef _TCLINT #define _TCLINT /* * Common include files needed by most of the Tcl source files are |
| ︙ | ︙ | |||
1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 |
typedef struct List {
int maxElemCount; /* Total number of element array slots. */
int elemCount; /* Current number of list elements. */
Tcl_Obj **elements; /* Array of pointers to element objects. */
} List;
/*
* 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.
| > > > > > > > > > > > > > > > > | 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 |
typedef struct List {
int maxElemCount; /* Total number of element array slots. */
int elemCount; /* Current number of list elements. */
Tcl_Obj **elements; /* Array of pointers to element objects. */
} List;
/*
*----------------------------------------------------------------
* 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) _ANSI_ARGS_((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.
|
| ︙ | ︙ | |||
1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 | * 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 /* *---------------------------------------------------------------- * Data structures related to obsolete filesystem hooks *---------------------------------------------------------------- */ | > > > > > > > | 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 |
* 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
typedef enum Tcl_PathPart {
TCL_PATH_DIRNAME,
TCL_PATH_TAIL,
TCL_PATH_EXTENSION,
TCL_PATH_ROOT
} Tcl_PathPart;
/*
*----------------------------------------------------------------
* Data structures related to obsolete filesystem hooks
*----------------------------------------------------------------
*/
|
| ︙ | ︙ | |||
1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 |
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 TclParseExpr _ANSI_ARGS_((Tcl_Interp *interp,
CONST char *string, int numBytes,
int useInternalTokens, Tcl_Parse *parsePtr));
EXTERN int TclParseHex _ANSI_ARGS_((CONST char *src, int numBytes,
Tcl_UniChar *resultPtr));
EXTERN int TclParseInteger _ANSI_ARGS_((CONST char *string,
int numBytes));
Tcl_Token * TclParseScript _ANSI_ARGS_((CONST char *script,
int numBytes, int flags,
Tcl_Token **lastTokenPtrPtr, CONST char **termPtr));
EXTERN int TclParseWhiteSpace _ANSI_ARGS_((CONST char *src,
int numBytes, Tcl_Parse *parsePtr, char *typePtr));
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,
| > > > > > > > > > > > > > | 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 |
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 int TclLoadFile _ANSI_ARGS_((Tcl_Interp* interp,
Tcl_Obj *pathPtr, int symc,
CONST char *symbols[],
Tcl_PackageInitProc **procPtrs[],
Tcl_LoadHandle *handlePtr,
ClientData *clientDataPtr,
Tcl_FSUnloadFileProc **unloadProcPtr));
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 TclMergeReturnOptions _ANSI_ARGS_((Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[],
Tcl_Obj **optionsPtrPtr, int *codePtr,
int *levelPtr));
EXTERN int TclParseBackslash _ANSI_ARGS_((CONST char *src,
int numBytes, int *readPtr, char *dst));
EXTERN int TclParseExpr _ANSI_ARGS_((Tcl_Interp *interp,
CONST char *string, int numBytes,
int useInternalTokens, Tcl_Parse *parsePtr));
EXTERN int TclParseHex _ANSI_ARGS_((CONST char *src, int numBytes,
Tcl_UniChar *resultPtr));
EXTERN int TclParseInteger _ANSI_ARGS_((CONST char *string,
int numBytes));
Tcl_Token * TclParseScript _ANSI_ARGS_((CONST char *script,
int numBytes, int flags,
Tcl_Token **lastTokenPtrPtr, CONST char **termPtr));
EXTERN int TclParseWhiteSpace _ANSI_ARGS_((CONST char *src,
int numBytes, Tcl_Parse *parsePtr, char *typePtr));
EXTERN int TclProcessReturn _ANSI_ARGS_((Tcl_Interp *interp,
int code, int level, Tcl_Obj *returnOpts));
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,
|
| ︙ | ︙ | |||
1832 1833 1834 1835 1836 1837 1838 | 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)); | | | > | | | > | 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 | 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 *pathPtr, 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 ClientData TclpGetNativeCwd _ANSI_ARGS_((ClientData clientData)); 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* TclPathPart _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *pathPtr, Tcl_PathPart portion)); 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 TclpCutFileChannel _ANSI_ARGS_((Tcl_Channel chan)); EXTERN void TclpCutSockChannel _ANSI_ARGS_((Tcl_Channel chan)); EXTERN void TclpSpliceFileChannel _ANSI_ARGS_((Tcl_Channel chan)); EXTERN void TclpSpliceSockChannel _ANSI_ARGS_((Tcl_Channel chan)); |
| ︙ | ︙ | |||
1890 1891 1892 1893 1894 1895 1896 |
Tcl_Token *tokenPtr, int count,
int *tokensLeftPtr, int flags));
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
| | | 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 |
Tcl_Token *tokenPtr, int count,
int *tokensLeftPtr, int flags));
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* pathPtr));
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,
|
| ︙ | ︙ | |||
1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 | 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[])); | > > | 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 | 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_LassignObjCmd _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[])); |
| ︙ | ︙ | |||
2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 | 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, | > > | 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 | 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 TclCompileLassignCmd _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, |
| ︙ | ︙ | |||
2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 |
# define TclNewObj(objPtr) \
TclDbNewObj(objPtr, __FILE__, __LINE__);
# define TclDecrRefCount(objPtr) \
Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__)
#elif 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
*/
# define TclAllocObjStorage(objPtr) \
| > > > | | 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 |
# define TclNewObj(objPtr) \
TclDbNewObj(objPtr, __FILE__, __LINE__);
# define TclDecrRefCount(objPtr) \
Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__)
# define TclNewListObjDirect(objc, objv) \
TclDbNewListObjDirect(objc, objv, __FILE__, __LINE__)
#elif 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
*/
# define TclAllocObjStorage(objPtr) \
(objPtr) = (Tcl_Obj *) Tcl_Alloc(sizeof(Tcl_Obj))
# define TclFreeObjStorage(objPtr) \
ckfree((char *) (objPtr))
#elif defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
/*
|
| ︙ | ︙ |
Changes to generic/tclIntDecls.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* * tclIntDecls.h -- * * This file contains the declarations for all unsupported * functions that are exported by the Tcl library. These * interfaces are not guaranteed to remain the same between * versions. Use at your own risk. * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* * tclIntDecls.h -- * * This file contains the declarations for all unsupported * functions that are exported by the Tcl library. These * interfaces are not guaranteed to remain the same between * versions. Use at your own risk. * * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclIntDecls.h,v 1.50.2.5 2004/02/07 05:48:01 dgp Exp $ */ #ifndef _TCLINTDECLS #define _TCLINTDECLS /* * WARNING: This file is automatically generated by the tools/genStubs.tcl |
| ︙ | ︙ | |||
120 121 122 123 124 125 126 | #endif #ifndef TclDeleteVars_TCL_DECLARED #define TclDeleteVars_TCL_DECLARED /* 12 */ EXTERN void TclDeleteVars _ANSI_ARGS_((Interp * iPtr, Tcl_HashTable * tablePtr)); #endif | < < | < < < < | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | #endif #ifndef TclDeleteVars_TCL_DECLARED #define TclDeleteVars_TCL_DECLARED /* 12 */ EXTERN void TclDeleteVars _ANSI_ARGS_((Interp * iPtr, Tcl_HashTable * tablePtr)); #endif /* Slot 13 is reserved */ #ifndef TclDumpMemoryInfo_TCL_DECLARED #define TclDumpMemoryInfo_TCL_DECLARED /* 14 */ EXTERN void TclDumpMemoryInfo _ANSI_ARGS_((FILE * outFile)); #endif /* Slot 15 is reserved */ #ifndef TclExprFloatError_TCL_DECLARED |
| ︙ | ︙ | |||
186 187 188 189 190 191 192 | EXTERN Tcl_Channel TclpGetDefaultStdChannel _ANSI_ARGS_((int type)); #endif /* Slot 29 is reserved */ /* Slot 30 is reserved */ #ifndef TclGetExtension_TCL_DECLARED #define TclGetExtension_TCL_DECLARED /* 31 */ | | | 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | EXTERN Tcl_Channel TclpGetDefaultStdChannel _ANSI_ARGS_((int type)); #endif /* Slot 29 is reserved */ /* Slot 30 is reserved */ #ifndef TclGetExtension_TCL_DECLARED #define TclGetExtension_TCL_DECLARED /* 31 */ EXTERN CONST char * TclGetExtension _ANSI_ARGS_((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)); #endif |
| ︙ | ︙ | |||
702 703 704 705 706 707 708 | #ifndef TclpStrftime_TCL_DECLARED #define TclpStrftime_TCL_DECLARED /* 134 */ EXTERN size_t TclpStrftime _ANSI_ARGS_((char * s, size_t maxsize, CONST char * format, CONST struct tm * t, int useGMT)); #endif | < < | < < | 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 | #ifndef TclpStrftime_TCL_DECLARED #define TclpStrftime_TCL_DECLARED /* 134 */ EXTERN size_t TclpStrftime _ANSI_ARGS_((char * s, size_t maxsize, CONST char * format, CONST struct tm * t, int useGMT)); #endif /* 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)); |
| ︙ | ︙ | |||
945 946 947 948 949 950 951 952 953 954 955 956 957 958 |
#endif
#ifndef Tcl_GetStartupScript_TCL_DECLARED
#define Tcl_GetStartupScript_TCL_DECLARED
/* 179 */
EXTERN Tcl_Obj * Tcl_GetStartupScript _ANSI_ARGS_((
CONST char ** encodingNamePtr));
#endif
typedef struct TclIntStubs {
int magic;
struct TclIntStubHooks *hooks;
void *reserved0;
int (*tclAccessDeleteProc) _ANSI_ARGS_((TclAccessProc_ * proc)); /* 1 */
| > > > > > > > > > > > > | 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 |
#endif
#ifndef Tcl_GetStartupScript_TCL_DECLARED
#define Tcl_GetStartupScript_TCL_DECLARED
/* 179 */
EXTERN Tcl_Obj * Tcl_GetStartupScript _ANSI_ARGS_((
CONST char ** encodingNamePtr));
#endif
#ifndef TclNewListObjDirect_TCL_DECLARED
#define TclNewListObjDirect_TCL_DECLARED
/* 180 */
EXTERN Tcl_Obj * TclNewListObjDirect _ANSI_ARGS_((int objc,
Tcl_Obj ** objv));
#endif
#ifndef TclDbNewListObjDirect_TCL_DECLARED
#define TclDbNewListObjDirect_TCL_DECLARED
/* 181 */
EXTERN Tcl_Obj * TclDbNewListObjDirect _ANSI_ARGS_((int objc,
Tcl_Obj ** objv, CONST char * file, int line));
#endif
typedef struct TclIntStubs {
int magic;
struct TclIntStubHooks *hooks;
void *reserved0;
int (*tclAccessDeleteProc) _ANSI_ARGS_((TclAccessProc_ * proc)); /* 1 */
|
| ︙ | ︙ | |||
979 980 981 982 983 984 985 |
#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 */
| | | | 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 |
#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 */
void *reserved13;
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, unsigned long now, long zone, unsigned long * timePtr)); /* 27 */
Tcl_Channel (*tclpGetDefaultStdChannel) _ANSI_ARGS_((int type)); /* 28 */
void *reserved29;
void *reserved30;
CONST char * (*tclGetExtension) _ANSI_ARGS_((CONST 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 */
|
| ︙ | ︙ | |||
1109 1110 1111 1112 1113 1114 1115 |
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 */
| | | 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 |
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 */
void *reserved135;
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 */
|
| ︙ | ︙ | |||
1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 |
int (*tclUniCharMatch) _ANSI_ARGS_((CONST Tcl_UniChar * string, int strLen, CONST Tcl_UniChar * pattern, int ptnLen, int nocase)); /* 173 */
Tcl_Obj * (*tclIncrWideVar2) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, Tcl_WideInt wideIncrAmount, int part1NotParsed)); /* 174 */
int (*tclCallVarTraces) _ANSI_ARGS_((Interp * iPtr, Var * arrayPtr, Var * varPtr, CONST char * part1, CONST char * part2, int flags, int leaveErrMsg)); /* 175 */
void (*tclCleanupVar) _ANSI_ARGS_((Var * varPtr, Var * arrayPtr)); /* 176 */
void (*tclVarErrMsg) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * part1, CONST char * part2, CONST char * operation, CONST char * reason)); /* 177 */
void (*tcl_SetStartupScript) _ANSI_ARGS_((Tcl_Obj * pathPtr, CONST char* encodingName)); /* 178 */
Tcl_Obj * (*tcl_GetStartupScript) _ANSI_ARGS_((CONST char ** encodingNamePtr)); /* 179 */
} TclIntStubs;
#ifdef __cplusplus
extern "C" {
#endif
extern TclIntStubs *tclIntStubsPtr;
#ifdef __cplusplus
| > > | 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 |
int (*tclUniCharMatch) _ANSI_ARGS_((CONST Tcl_UniChar * string, int strLen, CONST Tcl_UniChar * pattern, int ptnLen, int nocase)); /* 173 */
Tcl_Obj * (*tclIncrWideVar2) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, Tcl_WideInt wideIncrAmount, int part1NotParsed)); /* 174 */
int (*tclCallVarTraces) _ANSI_ARGS_((Interp * iPtr, Var * arrayPtr, Var * varPtr, CONST char * part1, CONST char * part2, int flags, int leaveErrMsg)); /* 175 */
void (*tclCleanupVar) _ANSI_ARGS_((Var * varPtr, Var * arrayPtr)); /* 176 */
void (*tclVarErrMsg) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * part1, CONST char * part2, CONST char * operation, CONST char * reason)); /* 177 */
void (*tcl_SetStartupScript) _ANSI_ARGS_((Tcl_Obj * pathPtr, CONST char* encodingName)); /* 178 */
Tcl_Obj * (*tcl_GetStartupScript) _ANSI_ARGS_((CONST char ** encodingNamePtr)); /* 179 */
Tcl_Obj * (*tclNewListObjDirect) _ANSI_ARGS_((int objc, Tcl_Obj ** objv)); /* 180 */
Tcl_Obj * (*tclDbNewListObjDirect) _ANSI_ARGS_((int objc, Tcl_Obj ** objv, CONST char * file, int line)); /* 181 */
} TclIntStubs;
#ifdef __cplusplus
extern "C" {
#endif
extern TclIntStubs *tclIntStubsPtr;
#ifdef __cplusplus
|
| ︙ | ︙ | |||
1232 1233 1234 1235 1236 1237 1238 | #define TclDeleteCompiledLocalVars \ (tclIntStubsPtr->tclDeleteCompiledLocalVars) /* 11 */ #endif #ifndef TclDeleteVars #define TclDeleteVars \ (tclIntStubsPtr->tclDeleteVars) /* 12 */ #endif | | < < < | 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 | #define TclDeleteCompiledLocalVars \ (tclIntStubsPtr->tclDeleteCompiledLocalVars) /* 11 */ #endif #ifndef TclDeleteVars #define TclDeleteVars \ (tclIntStubsPtr->tclDeleteVars) /* 12 */ #endif /* Slot 13 is reserved */ #ifndef TclDumpMemoryInfo #define TclDumpMemoryInfo \ (tclIntStubsPtr->tclDumpMemoryInfo) /* 14 */ #endif /* Slot 15 is reserved */ #ifndef TclExprFloatError #define TclExprFloatError \ |
| ︙ | ︙ | |||
1626 1627 1628 1629 1630 1631 1632 | #define TclpGetDate \ (tclIntStubsPtr->tclpGetDate) /* 133 */ #endif #ifndef TclpStrftime #define TclpStrftime \ (tclIntStubsPtr->tclpStrftime) /* 134 */ #endif | < < | < | 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 | #define TclpGetDate \ (tclIntStubsPtr->tclpGetDate) /* 133 */ #endif #ifndef TclpStrftime #define TclpStrftime \ (tclIntStubsPtr->tclpStrftime) /* 134 */ #endif /* Slot 135 is reserved */ /* Slot 136 is reserved */ /* Slot 137 is reserved */ #ifndef TclGetEnv #define TclGetEnv \ (tclIntStubsPtr->tclGetEnv) /* 138 */ #endif /* Slot 139 is reserved */ |
| ︙ | ︙ | |||
1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 | #define Tcl_SetStartupScript \ (tclIntStubsPtr->tcl_SetStartupScript) /* 178 */ #endif #ifndef Tcl_GetStartupScript #define Tcl_GetStartupScript \ (tclIntStubsPtr->tcl_GetStartupScript) /* 179 */ #endif #endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */ /* !END!: Do not edit above this line. */ #endif /* _TCLINTDECLS */ | > > > > > > > > | 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 | #define Tcl_SetStartupScript \ (tclIntStubsPtr->tcl_SetStartupScript) /* 178 */ #endif #ifndef Tcl_GetStartupScript #define Tcl_GetStartupScript \ (tclIntStubsPtr->tcl_GetStartupScript) /* 179 */ #endif #ifndef TclNewListObjDirect #define TclNewListObjDirect \ (tclIntStubsPtr->tclNewListObjDirect) /* 180 */ #endif #ifndef TclDbNewListObjDirect #define TclDbNewListObjDirect \ (tclIntStubsPtr->tclDbNewListObjDirect) /* 181 */ #endif #endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */ /* !END!: Do not edit above this line. */ #endif /* _TCLINTDECLS */ |
Changes to generic/tclInterp.c.
1 2 3 4 5 6 7 8 9 10 11 | /* * tclInterp.c -- * * 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. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * tclInterp.c -- * * 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. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclInterp.c,v 1.22.2.2 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" #include <stdio.h> /* |
| ︙ | ︙ | |||
281 282 283 284 285 286 287 |
/*
* There shouldn't be any commands left.
*/
masterPtr = &interpInfoPtr->master;
if (masterPtr->slaveTable.numEntries != 0) {
| | | 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
/*
* There shouldn't be any commands left.
*/
masterPtr = &interpInfoPtr->master;
if (masterPtr->slaveTable.numEntries != 0) {
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.
|
| ︙ | ︙ | |||
319 320 321 322 323 324 325 |
}
/*
* There shouldn't be any aliases left.
*/
if (slavePtr->aliasTable.numEntries != 0) {
| | | 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
}
/*
* There shouldn't be any aliases left.
*/
if (slavePtr->aliasTable.numEntries != 0) {
Tcl_Panic("InterpInfoDeleteProc: still exist aliases");
}
Tcl_DeleteHashTable(&slavePtr->aliasTable);
ckfree((char *) interpInfoPtr);
}
/*
|
| ︙ | ︙ | |||
1883 1884 1885 1886 1887 1888 1889 |
OPT_ALIAS, OPT_ALIASES, OPT_EVAL, OPT_EXPOSE,
OPT_HIDE, OPT_HIDDEN, OPT_ISSAFE, OPT_INVOKEHIDDEN,
OPT_MARKTRUSTED, OPT_RECLIMIT
};
slaveInterp = (Tcl_Interp *) clientData;
if (slaveInterp == NULL) {
| | | 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 |
OPT_ALIAS, OPT_ALIASES, OPT_EVAL, OPT_EXPOSE,
OPT_HIDE, OPT_HIDDEN, OPT_ISSAFE, OPT_INVOKEHIDDEN,
OPT_MARKTRUSTED, OPT_RECLIMIT
};
slaveInterp = (Tcl_Interp *) clientData;
if (slaveInterp == NULL) {
Tcl_Panic("SlaveObjCmd: interpreter has been deleted");
}
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "cmd ?arg ...?");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0,
|
| ︙ | ︙ |
Changes to generic/tclListObj.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* * tclListObj.c -- * * This file contains procedures 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* * tclListObj.c -- * * This file contains procedures 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. * * RCS: @(#) $Id: tclListObj.c,v 1.13.6.2 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" /* * Prototypes for procedures defined later in this file: */ |
| ︙ | ︙ | |||
40 41 42 43 44 45 46 |
* it is occasionally used as working storage to avoid an auxiliary
* stack.
*/
Tcl_ObjType tclListType = {
"list", /* name */
FreeListInternalRep, /* freeIntRepProc */
| | | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
* 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 */
};
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
93 94 95 96 97 98 99 |
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;
| | | | | | | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
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;
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;
}
return listPtr;
}
#endif /* if TCL_MEM_DEBUG */
|
| ︙ | ︙ | |||
163 164 165 166 167 168 169 |
int line; /* Line number in the source file; used
* for debugging. */
{
register Tcl_Obj *listPtr;
register Tcl_Obj **elemPtrs;
register List *listRepPtr;
int i;
| | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
int line; /* Line number in the source file; used
* for debugging. */
{
register Tcl_Obj *listPtr;
register Tcl_Obj **elemPtrs;
register List *listRepPtr;
int i;
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;
}
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. */
{
return Tcl_NewListObj(objc, objv);
}
#endif /* TCL_MEM_DEBUG */
/*
*----------------------------------------------------------------------
*
* TclNewListObjDirect, TclDbNewListObjDirect --
*
* Version of Tcl_NewListOb/Tcl_DbNewListObj that does not copy
* the array of Tcl_Objs. It still scans it though to update the
* reference counts.
*
* 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 (and "ownership" of the array of objects is
* not transferred.) 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
* resulting list now refers to them.
*
*----------------------------------------------------------------------
*/
#ifdef TCL_MEM_DEBUG
#undef TclNewListObjDirect
Tcl_Obj *
TclNewListObjDirect(objc, objv)
int objc; /* Count of objects referenced by objv. */
Tcl_Obj **objv; /* An array of pointers to Tcl objects. */
{
return TclDbNewListObjDirect(objc, objv, "unknown", 0);
}
#else /* !TCL_MEM_DEBUG */
Tcl_Obj *
TclNewListObjDirect(objc, objv)
int objc; /* Count of objects referenced by objv. */
Tcl_Obj **objv; /* An array of pointers to Tcl objects. */
{
register Tcl_Obj *listPtr;
TclNewObj(listPtr);
if (objc > 0) {
register List *listRepPtr;
int i;
Tcl_InvalidateStringRep(listPtr);
for (i=0 ; i<objc ; i++) {
Tcl_IncrRefCount(objv[i]);
}
listRepPtr = (List *) ckalloc(sizeof(List));
listRepPtr->maxElemCount = objc;
listRepPtr->elemCount = objc;
listRepPtr->elements = objv;
listPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
listPtr->internalRep.twoPtrValue.ptr2 = NULL;
listPtr->typePtr = &tclListType;
}
return listPtr;
}
#endif /* TCL_MEM_DEBUG */
#ifdef TCL_MEM_DEBUG
Tcl_Obj *
TclDbNewListObjDirect(objc, objv, file, line)
int objc; /* Count of objects referenced by objv. */
Tcl_Obj **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. */
{
register Tcl_Obj *listPtr;
TclDbNewObj(listPtr, file, line);
if (objc > 0) {
register List *listRepPtr;
int i;
Tcl_InvalidateStringRep(listPtr);
for (i=0 ; i<objc ; i++) {
Tcl_IncrRefCount(objv[i]);
}
listRepPtr = (List *) ckalloc(sizeof(List));
listRepPtr->maxElemCount = objc;
listRepPtr->elemCount = objc;
listRepPtr->elements = objv;
listPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
listPtr->internalRep.twoPtrValue.ptr2 = NULL;
listPtr->typePtr = &tclListType;
}
return listPtr;
}
#else /* !TCL_MEM_DEBUG */
Tcl_Obj *
TclDbNewListObjDirect(objc, objv, file, line)
int objc; /* Count of objects referenced by objv. */
Tcl_Obj **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. */
{
return TclNewListObjDirect(objc, objv);
}
#endif /* TCL_MEM_DEBUG */
/*
*----------------------------------------------------------------------
*
* Tcl_SetListObj --
*
|
| ︙ | ︙ | |||
237 238 239 240 241 242 243 |
{
register Tcl_Obj **elemPtrs;
register List *listRepPtr;
Tcl_ObjType *oldTypePtr = objPtr->typePtr;
int i;
if (Tcl_IsShared(objPtr)) {
| | | | | | | 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
{
register Tcl_Obj **elemPtrs;
register List *listRepPtr;
Tcl_ObjType *oldTypePtr = objPtr->typePtr;
int i;
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("Tcl_SetListObj called with shared object");
}
/*
* Free any old string rep and any internal rep for the old type.
*/
if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
oldTypePtr->freeIntRepProc(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.
*/
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;
} else {
objPtr->bytes = tclEmptyStringRep;
objPtr->length = 0;
}
|
| ︙ | ︙ | |||
315 316 317 318 319 320 321 |
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
* referenced by objv. */
| | | 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 |
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
* referenced by objv. */
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);
if (result != TCL_OK) {
|
| ︙ | ︙ | |||
369 370 371 372 373 374 375 |
Tcl_Obj *elemListPtr; /* List obj with elements to append. */
{
register List *listRepPtr;
int listLen, objc, result;
Tcl_Obj **objv;
if (Tcl_IsShared(listPtr)) {
| | | | 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 |
Tcl_Obj *elemListPtr; /* List obj with elements to append. */
{
register List *listRepPtr;
int listLen, objc, result;
Tcl_Obj **objv;
if (Tcl_IsShared(listPtr)) {
Tcl_Panic("Tcl_ListObjAppendList called with shared object");
}
if (listPtr->typePtr != &tclListType) {
result = SetListFromAny(interp, listPtr);
if (result != TCL_OK) {
return result;
}
}
listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
listLen = listRepPtr->elemCount;
result = Tcl_ListObjGetElements(interp, elemListPtr, &objc, &objv);
if (result != TCL_OK) {
return result;
}
/*
* Insert objc new elements starting after the lists's last element.
* Delete zero existing elements.
*/
return Tcl_ListObjReplace(interp, listPtr, listLen, 0, objc, objv);
}
/*
*----------------------------------------------------------------------
*
* Tcl_ListObjAppendElement --
|
| ︙ | ︙ | |||
429 430 431 432 433 434 435 |
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;
| | | | | | | | 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 |
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;
if (Tcl_IsShared(listPtr)) {
Tcl_Panic("Tcl_ListObjAppendElement called with shared object");
}
if (listPtr->typePtr != &tclListType) {
int result = SetListFromAny(interp, listPtr);
if (result != TCL_OK) {
return result;
}
}
listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
elemPtrs = listRepPtr->elements;
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 (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;
}
|
| ︙ | ︙ | |||
516 517 518 519 520 521 522 |
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. */
{
register List *listRepPtr;
| | | | 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 |
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. */
{
register List *listRepPtr;
if (listPtr->typePtr != &tclListType) {
int result = SetListFromAny(interp, listPtr);
if (result != TCL_OK) {
return result;
}
}
listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
if ((index < 0) || (index >= listRepPtr->elemCount)) {
*objPtrPtr = NULL;
} else {
*objPtrPtr = listRepPtr->elements[index];
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_ListObjLength --
|
| ︙ | ︙ | |||
563 564 565 566 567 568 569 |
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. */
{
register List *listRepPtr;
| | | 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 |
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. */
{
register List *listRepPtr;
if (listPtr->typePtr != &tclListType) {
int result = SetListFromAny(interp, listPtr);
if (result != TCL_OK) {
return result;
}
}
|
| ︙ | ︙ | |||
629 630 631 632 633 634 635 |
* to insert. */
{
List *listRepPtr;
register Tcl_Obj **elemPtrs, **newPtrs;
Tcl_Obj *victimPtr;
int numElems, numRequired, numAfterLast;
int start, shift, newMax, i, j, result;
| | | | | 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 |
* to insert. */
{
List *listRepPtr;
register Tcl_Obj **elemPtrs, **newPtrs;
Tcl_Obj *victimPtr;
int numElems, numRequired, numAfterLast;
int start, shift, newMax, i, j, result;
if (Tcl_IsShared(listPtr)) {
Tcl_Panic("Tcl_ListObjReplace called with shared object");
}
if (listPtr->typePtr != &tclListType) {
result = SetListFromAny(interp, listPtr);
if (result != TCL_OK) {
return result;
}
}
listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
elemPtrs = listRepPtr->elements;
numElems = listRepPtr->elemCount;
if (first < 0) {
first = 0;
}
if (first >= numElems) {
first = numElems; /* so we'll insert after last element */
}
if (count < 0) {
count = 0;
}
numRequired = (numElems - count + objc);
if (numRequired <= listRepPtr->maxElemCount) {
/*
* Enough room in the current array. First "delete" count
* elements starting at first.
*/
|
| ︙ | ︙ | |||
693 694 695 696 697 698 699 | } } /* * Insert the new elements into elemPtrs before "first". */ | | | | | | 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 |
}
}
/*
* Insert the new elements into elemPtrs before "first".
*/
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;
} else {
|
| ︙ | ︙ | |||
743 744 745 746 747 748 749 |
start = (first + count);
numAfterLast = (numElems - start);
if (numAfterLast > 0) {
memcpy((VOID *) &(newPtrs[first + objc]),
(VOID *) &(elemPtrs[start]),
(size_t) (numAfterLast * sizeof(Tcl_Obj *)));
}
| | | | 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 |
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, j = first; i < objc; i++, j++) {
newPtrs[j] = objv[i];
Tcl_IncrRefCount(objv[i]);
}
listRepPtr->elemCount = numRequired;
listRepPtr->maxElemCount = newMax;
listRepPtr->elements = newPtrs;
ckfree((char *) elemPtrs);
}
/*
* Invalidate and free any old string representation since it no longer
* reflects the list's internal representation.
*/
Tcl_InvalidateStringRep(listPtr);
return TCL_OK;
|
| ︙ | ︙ | |||
817 818 819 820 821 822 823 | * the 'ptr2' field of any Tcl_Obj that has been modified is set to * NULL. * *---------------------------------------------------------------------- */ Tcl_Obj* | | < < | | < | | | < | < | | | | | | 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 |
* the 'ptr2' field of any Tcl_Obj that has been modified is set to
* NULL.
*
*----------------------------------------------------------------------
*/
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' */
{
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;
/*
* 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 (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) {
/*
* indexArgPtr designates something that is neither an index nor a
* well formed list. Report the error via TclLsetFlat.
*/
return TclLsetFlat(interp, listPtr, 1, &indexArgPtr, valuePtr);
}
/*
* 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.
*/
if (indexCount == 0) {
Tcl_IncrRefCount(valuePtr);
return valuePtr;
}
/*
* Duplicate the list arg if necessary.
*/
if (Tcl_IsShared(listPtr)) {
duplicated = 1;
listPtr = Tcl_DuplicateObj(listPtr);
Tcl_IncrRefCount(listPtr);
} else {
duplicated = 0;
}
/*
* It would be tempting simply to go off to TclLsetFlat to finish the
* processing. Alas, it is also incorrect! The problem is that
|
| ︙ | ︙ | |||
912 913 914 915 916 917 918 |
retValuePtr = listPtr;
chainPtr = NULL;
/*
* Handle each index arg by diving into the appropriate sublist
*/
| < | | < | | | | | < | | | | | < | | | | | | < | < | | | < | | | | | | | | < | 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 |
retValuePtr = listPtr;
chainPtr = NULL;
/*
* Handle each index arg by diving into the appropriate sublist
*/
for (i=0 ; ; i++) {
/*
* Take the sublist apart.
*/
result = Tcl_ListObjGetElements(interp, listPtr, &elemCount, &elemPtrs);
if (result != TCL_OK) {
break;
}
listPtr->internalRep.twoPtrValue.ptr2 = (VOID *) chainPtr;
/*
* Reconstitute the index array
*/
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.
*/
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.
*/
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.
*/
break;
}
}
/*
* Chain the current sublist onto the linked list of Tcl_Obj's
* whose string reps must be spoilt.
*/
chainPtr = listPtr;
listPtr = subListPtr;
}
/*
* Store the new element into the correct slot in the innermost sublist.
*/
if (result == TCL_OK) {
result = TclListObjSetElement(interp, listPtr, index, valuePtr);
}
if (result == TCL_OK) {
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;
}
/* Return the new list if everything worked. */
if (!duplicated) {
Tcl_IncrRefCount(retValuePtr);
}
return retValuePtr;
}
/* Clean up the one dangling reference otherwise */
if (duplicated) {
Tcl_DecrRefCount(retValuePtr);
}
return NULL;
}
/*
*----------------------------------------------------------------------
*
* TclLsetFlat --
*
|
| ︙ | ︙ | |||
1086 1087 1088 1089 1090 1091 1092 | * the 'ptr2' field of any Tcl_Obj that has been modified is set to * NULL. * *---------------------------------------------------------------------- */ Tcl_Obj* | | < < < < < < < < | | | | | < | | < | | < | | | | | < | | | | | | < | < | | | < | | | | | | | | < | 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 |
* 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' */
{
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;
/*
* If there are no indices, then simply return the new value,
* counting the returned pointer as a reference
*/
if (indexCount == 0) {
Tcl_IncrRefCount(valuePtr);
return valuePtr;
}
/*
* If the list is shared, make a private copy.
*/
if (Tcl_IsShared(listPtr)) {
duplicated = 1;
listPtr = Tcl_DuplicateObj(listPtr);
Tcl_IncrRefCount(listPtr);
} else {
duplicated = 0;
}
/*
* Anchor the linked list of Tcl_Obj's whose string reps must be
* invalidated if the operation succeeds.
*/
retValuePtr = listPtr;
chainPtr = NULL;
/*
* Handle each index arg by diving into the appropriate sublist
*/
for (i=0 ; ; i++) {
/*
* Take the sublist apart.
*/
result = Tcl_ListObjGetElements(interp, listPtr, &elemCount, &elemPtrs);
if (result != TCL_OK) {
break;
}
listPtr->internalRep.twoPtrValue.ptr2 = (VOID *) chainPtr;
/*
* Determine the index of the requested element.
*/
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;
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.
*/
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;
}
}
/*
* Chain the current sublist onto the linked list of Tcl_Obj's
* whose string reps must be spoilt.
*/
chainPtr = listPtr;
listPtr = subListPtr;
}
/* Store the result in the list element */
if (result == TCL_OK) {
result = TclListObjSetElement(interp, listPtr, index, valuePtr);
}
if (result == TCL_OK) {
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;
}
/* Return the new list if everything worked. */
if (!duplicated) {
Tcl_IncrRefCount(retValuePtr);
}
return retValuePtr;
}
/* Clean up the one dangling reference otherwise */
if (duplicated) {
Tcl_DecrRefCount(retValuePtr);
}
return NULL;
}
/*
*----------------------------------------------------------------------
*
* TclListObjSetElement --
*
|
| ︙ | ︙ | |||
1279 1280 1281 1282 1283 1284 1285 | * 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: * | | | | | | | | | | | | | | | < | | | < | 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 |
* 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. 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.
*
*----------------------------------------------------------------------
*/
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 */
{
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 */
/* Ensure that the listPtr parameter designates an unshared list */
if (Tcl_IsShared(listPtr)) {
Tcl_Panic("Tcl_ListObjSetElement called with shared object");
}
if (listPtr->typePtr != &tclListType) {
result = SetListFromAny(interp, listPtr);
if (result != TCL_OK) {
return result;
}
}
listRepPtr = (List*) listPtr->internalRep.twoPtrValue.ptr1;
elemPtrs = listRepPtr->elements;
elemCount = listRepPtr->elemCount;
/* 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;
}
}
/* Add a reference to the new list element */
Tcl_IncrRefCount(valuePtr);
/* Remove a reference from the old list element */
Tcl_DecrRefCount(elemPtrs[index]);
/* Stash the new object in the list */
elemPtrs[index] = valuePtr;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* FreeListInternalRep --
*
|
| ︙ | ︙ | |||
1377 1378 1379 1380 1381 1382 1383 |
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;
| | | 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 |
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);
}
ckfree((char *) elemPtrs);
ckfree((char *) listRepPtr);
|
| ︙ | ︙ | |||
1429 1430 1431 1432 1433 1434 1435 |
int i;
/*
* Allocate a new List structure that points to "srcPtr"s element
* objects. Increment the ref counts for those (now shared) element
* objects.
*/
| | | | | 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 |
int i;
/*
* 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;
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
1531 1532 1533 1534 1535 1536 1537 |
ckfree((char *) elemPtrs);
return result;
}
if (elemStart >= limit) {
break;
}
if (i > estCount) {
| | | | | | | 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 |
ckfree((char *) elemPtrs);
return result;
}
if (elemStart >= limit) {
break;
}
if (i > estCount) {
Tcl_Panic("SetListFromAny: bad size estimate for list");
}
/*
* Allocate a Tcl object for the element and initialize it from the
* "elemSize" bytes starting at "elemStart".
*/
s = ckalloc((unsigned) elemSize + 1);
if (hasBrace) {
memcpy((VOID *) s, (VOID *) elemStart, (size_t) elemSize);
s[elemSize] = 0;
} else {
elemSize = TclCopyAndCollapse(elemSize, elemStart, s);
}
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;
|
| ︙ | ︙ | |||
1637 1638 1639 1640 1641 1642 1643 |
* Pass 2: copy into string rep buffer.
*/
listPtr->bytes = ckalloc((unsigned) listPtr->length);
dst = listPtr->bytes;
for (i = 0; i < numElems; i++) {
elem = Tcl_GetStringFromObj(listRepPtr->elements[i], &length);
| | | | 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 |
* Pass 2: copy into string rep buffer.
*/
listPtr->bytes = ckalloc((unsigned) listPtr->length);
dst = listPtr->bytes;
for (i = 0; i < numElems; i++) {
elem = Tcl_GetStringFromObj(listRepPtr->elements[i], &length);
dst += Tcl_ConvertCountedElement(elem, length, dst,
flagPtr[i] | (i==0 ? 0 : TCL_DONT_QUOTE_HASH));
*dst = ' ';
dst++;
}
if (flagPtr != localFlags) {
ckfree((char *) flagPtr);
}
if (dst == listPtr->bytes) {
|
| ︙ | ︙ |
Changes to generic/tclLiteral.c.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | * that appears in tclHash.c. * * 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. * | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | * that appears in tclHash.c. * * 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. * * RCS: @(#) $Id: tclLiteral.c,v 1.11.8.1 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" #include "tclCompile.h" #include "tclPort.h" /* * When there are this many entries per bucket, on average, rebuild |
| ︙ | ︙ | |||
59 60 61 62 63 64 65 |
void
TclInitLiteralTable(tablePtr)
register LiteralTable *tablePtr; /* Pointer to table structure, which
* is supplied by the caller. */
{
#if (TCL_SMALL_HASH_TABLE != 4)
| | | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
void
TclInitLiteralTable(tablePtr)
register LiteralTable *tablePtr; /* Pointer to table structure, which
* is supplied by the caller. */
{
#if (TCL_SMALL_HASH_TABLE != 4)
Tcl_Panic("TclInitLiteralTable: TCL_SMALL_HASH_TABLE is %d, not 4\n",
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;
|
| ︙ | ︙ | |||
238 239 240 241 242 243 244 |
if (onHeap) {
ckfree(bytes);
}
objIndex = AddLocalLiteralEntry(envPtr, globalPtr, localHash);
#ifdef TCL_COMPILE_DEBUG
if (globalPtr->refCount < 1) {
| | | 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
if (onHeap) {
ckfree(bytes);
}
objIndex = AddLocalLiteralEntry(envPtr, globalPtr, 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;
}
|
| ︙ | ︙ | |||
278 279 280 281 282 283 284 |
objPtr->typePtr = &tclIntType;
}
}
}
#ifdef TCL_COMPILE_DEBUG
if (TclLookupLiteralEntry((Tcl_Interp *) iPtr, objPtr) != NULL) {
| | | 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
objPtr->typePtr = &tclIntType;
}
}
}
#ifdef TCL_COMPILE_DEBUG
if (TclLookupLiteralEntry((Tcl_Interp *) iPtr, objPtr) != NULL) {
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;
|
| ︙ | ︙ | |||
317 318 319 320 321 322 323 |
if ((entryPtr == globalPtr)
&& (entryPtr->objPtr == objPtr)) {
found = 1;
}
}
}
if (!found) {
| | | 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 |
if ((entryPtr == globalPtr)
&& (entryPtr->objPtr == objPtr)) {
found = 1;
}
}
}
if (!found) {
Tcl_Panic("TclRegisterLiteral: literal \"%.*s\" wasn't global",
(length>60? 60 : length), bytes);
}
}
#endif /*TCL_COMPILE_DEBUG*/
#ifdef TCL_COMPILE_STATS
iPtr->stats.numLiteralsCreated++;
iPtr->stats.totalLitStringBytes += (double) (length + 1);
|
| ︙ | ︙ | |||
559 560 561 562 563 564 565 |
if (localPtr->objPtr == globalPtr->objPtr) {
found = 1;
}
}
}
if (!found) {
bytes = Tcl_GetStringFromObj(globalPtr->objPtr, &length);
| | | 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 |
if (localPtr->objPtr == globalPtr->objPtr) {
found = 1;
}
}
}
if (!found) {
bytes = Tcl_GetStringFromObj(globalPtr->objPtr, &length);
Tcl_Panic("AddLocalLiteralEntry: literal \"%.*s\" wasn't found locally",
(length>60? 60 : length), bytes);
}
}
#endif /*TCL_COMPILE_DEBUG*/
return objIndex;
}
|
| ︙ | ︙ | |||
955 956 957 958 959 960 961 | * * Check a CompileEnv's local literal table for consistency. * * Results: * None. * * Side effects: | | | 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 |
*
* Check a CompileEnv's local literal table for consistency.
*
* Results:
* None.
*
* Side effects:
* Tcl_Panic if problems are found.
*
*----------------------------------------------------------------------
*/
void
TclVerifyLocalLiteralTable(envPtr)
CompileEnv *envPtr; /* Points to CompileEnv whose literal
|
| ︙ | ︙ | |||
978 979 980 981 982 983 984 |
count = 0;
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);
| | | | | | | 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 |
count = 0;
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);
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);
Tcl_Panic("TclVerifyLocalLiteralTable: local literal \"%.*s\" is not global",
(length>60? 60 : length), bytes);
}
if (localPtr->objPtr->bytes == NULL) {
Tcl_Panic("TclVerifyLocalLiteralTable: literal has NULL string rep");
}
}
}
if (count != localTablePtr->numEntries) {
Tcl_Panic("TclVerifyLocalLiteralTable: local literal table had %d entries, should be %d",
count, localTablePtr->numEntries);
}
}
/*
*----------------------------------------------------------------------
*
* TclVerifyGlobalLiteralTable --
*
* Check an interpreter's global literal table literal for consistency.
*
* Results:
* None.
*
* Side effects:
* Tcl_Panic if problems are found.
*
*----------------------------------------------------------------------
*/
void
TclVerifyGlobalLiteralTable(iPtr)
Interp *iPtr; /* Points to interpreter whose global
|
| ︙ | ︙ | |||
1033 1034 1035 1036 1037 1038 1039 |
count = 0;
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);
| | | | | 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 |
count = 0;
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);
Tcl_Panic("TclVerifyGlobalLiteralTable: global literal \"%.*s\" had bad refCount %d",
(length>60? 60 : length), bytes,
globalPtr->refCount);
}
if (globalPtr->objPtr->bytes == NULL) {
Tcl_Panic("TclVerifyGlobalLiteralTable: literal has NULL string rep");
}
}
}
if (count != globalTablePtr->numEntries) {
Tcl_Panic("TclVerifyGlobalLiteralTable: global literal table had %d entries, should be %d",
count, globalTablePtr->numEntries);
}
}
#endif /*TCL_COMPILE_DEBUG*/
|
Changes to generic/tclNamesp.c.
| ︙ | ︙ | |||
17 18 19 20 21 22 23 | * 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. * | | | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | * 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. * * RCS: @(#) $Id: tclNamesp.c,v 1.31.4.3 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" /* * Flag passed to TclGetNamespaceForQualName to indicate that it should * search for a namespace rather than a command or variable inside a |
| ︙ | ︙ | |||
420 421 422 423 424 425 426 |
register Namespace *nsPtr;
if (namespacePtr == NULL) {
nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
} else {
nsPtr = (Namespace *) namespacePtr;
if (nsPtr->flags & NS_DEAD) {
| | | 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 |
register Namespace *nsPtr;
if (namespacePtr == NULL) {
nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
} else {
nsPtr = (Namespace *) namespacePtr;
if (nsPtr->flags & NS_DEAD) {
Tcl_Panic("Trying to push call frame for dead namespace");
/*NOTREACHED*/
}
}
nsPtr->activationCount++;
framePtr->nsPtr = nsPtr;
framePtr->isProcCallFrame = isProcCallFrame;
|
| ︙ | ︙ | |||
1687 1688 1689 1690 1691 1692 1693 |
ckfree((char *) refPtr);
ckfree((char *) dataPtr);
return;
}
prevPtr = refPtr;
}
| | | 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 |
ckfree((char *) refPtr);
ckfree((char *) dataPtr);
return;
}
prevPtr = refPtr;
}
Tcl_Panic("DeleteImportedCmd: did not find cmd in real cmd's list of import references");
}
/*
*----------------------------------------------------------------------
*
* TclGetNamespaceForQualName --
*
|
| ︙ | ︙ | |||
1951 1952 1953 1954 1955 1956 1957 |
(Tcl_Namespace *) nsPtr, /*isProcCallFrame*/ 0);
nsPtr = (Namespace *) Tcl_CreateNamespace(interp, nsName,
(ClientData) NULL, (Tcl_NamespaceDeleteProc *) NULL);
Tcl_PopCallFrame(interp);
if (nsPtr == NULL) {
| | | 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 |
(Tcl_Namespace *) nsPtr, /*isProcCallFrame*/ 0);
nsPtr = (Namespace *) Tcl_CreateNamespace(interp, nsName,
(ClientData) NULL, (Tcl_NamespaceDeleteProc *) NULL);
Tcl_PopCallFrame(interp);
if (nsPtr == NULL) {
Tcl_Panic("Could not create namespace '%s'", nsName);
}
} else { /* namespace not found and wasn't created */
nsPtr = NULL;
}
}
/*
|
| ︙ | ︙ | |||
4727 4728 4729 4730 4731 4732 4733 |
*/
ensemblePtr->nsPtr->exportLookupEpoch++;
return TCL_OK;
}
}
default:
| | | 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 |
*/
ensemblePtr->nsPtr->exportLookupEpoch++;
return TCL_OK;
}
}
default:
Tcl_Panic("unexpected ensemble command");
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
4890 4891 4892 4893 4894 4895 4896 |
/*
* The subcommand is not a prefix of anything, so bail out!
*/
goto unknownOrAmbiguousSubcommand;
}
hPtr = Tcl_FindHashEntry(&ensemblePtr->subcommandTable, fullName);
if (hPtr == NULL) {
| | | 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 |
/*
* 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_Obj *) Tcl_GetHashValue(hPtr);
/*
* Cache for later in the subcommand object.
*/
|
| ︙ | ︙ |
Changes to generic/tclObj.c.
|
| | | | | 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 | /* * tclObj.c -- * * This file contains Tcl object-related procedures 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. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclObj.c,v 1.46.2.5 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" #include "tclCompile.h" #include "tclPort.h" /* * Table of all object types. */ static Tcl_HashTable typeTable; static int typeTableInitialized = 0; /* 0 means not yet initialized. */ TCL_DECLARE_MUTEX(tableMutex) /* * Head of the list of free Tcl_Obj structs we maintain. */ Tcl_Obj *tclFreeObjList = NULL; |
| ︙ | ︙ | |||
112 113 114 115 116 117 118 |
* means of procedures that can be invoked by generic object code. See also
* tclStringObj.c, tclListObj.c, tclByteCode.c for other type manager
* implementations.
*/
Tcl_ObjType tclBooleanType = {
"boolean", /* name */
| | | | | | 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
* means of procedures that can be invoked by generic object code. See also
* tclStringObj.c, tclListObj.c, tclByteCode.c for other type manager
* implementations.
*/
Tcl_ObjType tclBooleanType = {
"boolean", /* name */
(Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
(Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */
UpdateStringOfBoolean, /* updateStringProc */
SetBooleanFromAny /* setFromAnyProc */
};
Tcl_ObjType tclDoubleType = {
"double", /* name */
(Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
(Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */
UpdateStringOfDouble, /* updateStringProc */
SetDoubleFromAny /* setFromAnyProc */
};
Tcl_ObjType tclIntType = {
"int", /* name */
(Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
(Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */
UpdateStringOfInt, /* updateStringProc */
SetIntFromAny /* setFromAnyProc */
};
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 */
UpdateStringOfWideInt, /* updateStringProc */
#endif /* TCL_WIDE_INT_IS_LONG */
SetWideIntFromAny /* setFromAnyProc */
|
| ︙ | ︙ | |||
224 225 226 227 228 229 230 | /* *------------------------------------------------------------------------- * * TclInitObjectSubsystem -- * * This procedure is invoked to perform once-only initialization of | | | | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
/*
*-------------------------------------------------------------------------
*
* TclInitObjectSubsystem --
*
* This procedure 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.
*
*-------------------------------------------------------------------------
*/
void
TclInitObjSubsystem()
{
|
| ︙ | ︙ | |||
269 270 271 272 273 274 275 |
#ifdef TCL_COMPILE_STATS
Tcl_MutexLock(&tclObjMutex);
tclObjsAlloced = 0;
tclObjsFreed = 0;
{
int i;
| | | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
#ifdef TCL_COMPILE_STATS
Tcl_MutexLock(&tclObjMutex);
tclObjsAlloced = 0;
tclObjsFreed = 0;
{
int i;
for (i=0 ; i<TCL_MAX_SHARED_OBJ_STATS ; i++) {
tclObjsShared[i] = 0;
}
}
Tcl_MutexUnlock(&tclObjMutex);
#endif
}
|
| ︙ | ︙ | |||
396 397 398 399 400 401 402 |
* name of each registered type is appended
* as a list element. */
{
register Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
Tcl_ObjType *typePtr;
int result;
| | | 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 |
* name of each registered type is appended
* as a list element. */
{
register Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
Tcl_ObjType *typePtr;
int result;
/*
* This code assumes that types names do not contain embedded NULLs.
*/
Tcl_MutexLock(&tableMutex);
for (hPtr = Tcl_FirstHashEntry(&typeTable, &search);
hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
|
| ︙ | ︙ | |||
521 522 523 524 525 526 527 |
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.
*/
| | < | | | 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 |
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 new;
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, &new);
if (!new) {
Tcl_Panic("expected to create new entry for object map");
}
Tcl_SetHashValue(hPtr, NULL);
}
# endif /* TCL_THREADS */
}
#endif /* TCL_MEM_DEBUG */
|
| ︙ | ︙ | |||
737 738 739 740 741 742 743 |
*/
void
TclFreeObj(objPtr)
register Tcl_Obj *objPtr; /* The object to be freed. */
{
register Tcl_ObjType *typePtr = objPtr->typePtr;
| | | | | | | 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 |
*/
void
TclFreeObj(objPtr)
register Tcl_Obj *objPtr; /* The object to be freed. */
{
register Tcl_ObjType *typePtr = objPtr->typePtr;
#ifdef TCL_MEM_DEBUG
if ((objPtr)->refCount < -1) {
Tcl_Panic("Reference count for %lx was negative", objPtr);
}
#endif /* TCL_MEM_DEBUG */
if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
typePtr->freeIntRepProc(objPtr);
}
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.
*/
#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 */
#ifdef TCL_COMPILE_STATS
|
| ︙ | ︙ | |||
793 794 795 796 797 798 799 | * 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. * * Side effects: | | | 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 | * 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. * * 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. * *---------------------------------------------------------------------- */ |
| ︙ | ︙ | |||
816 817 818 819 820 821 822 |
TclNewObj(dupPtr);
if (objPtr->bytes == NULL) {
dupPtr->bytes = NULL;
} else if (objPtr->bytes != tclEmptyStringRep) {
TclInitStringRep(dupPtr, objPtr->bytes, objPtr->length);
}
| | | 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 |
TclNewObj(dupPtr);
if (objPtr->bytes == NULL) {
dupPtr->bytes = NULL;
} else if (objPtr->bytes != tclEmptyStringRep) {
TclInitStringRep(dupPtr, objPtr->bytes, objPtr->length);
}
if (typePtr != NULL) {
if (typePtr->dupIntRepProc == NULL) {
dupPtr->internalRep = objPtr->internalRep;
dupPtr->typePtr = typePtr;
} else {
(*typePtr->dupIntRepProc)(objPtr, dupPtr);
}
|
| ︙ | ︙ | |||
859 860 861 862 863 864 865 |
* should be returned. */
{
if (objPtr->bytes != NULL) {
return objPtr->bytes;
}
if (objPtr->typePtr->updateStringProc == NULL) {
| | | 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 |
* should be returned. */
{
if (objPtr->bytes != NULL) {
return objPtr->bytes;
}
if (objPtr->typePtr->updateStringProc == NULL) {
Tcl_Panic("UpdateStringProc should not be invoked for type %s",
objPtr->typePtr->name);
}
(*objPtr->typePtr->updateStringProc)(objPtr);
return objPtr->bytes;
}
/*
|
| ︙ | ︙ | |||
899 900 901 902 903 904 905 |
* be returned. */
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) {
| | | | 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 |
* be returned. */
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) {
Tcl_Panic("UpdateStringProc should not be invoked for type %s",
objPtr->typePtr->name);
}
(*objPtr->typePtr->updateStringProc)(objPtr);
}
if (lengthPtr != NULL) {
*lengthPtr = objPtr->length;
}
return objPtr->bytes;
}
/*
*----------------------------------------------------------------------
*
* Tcl_InvalidateStringRep --
*
* This procedure 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.
|
| ︙ | ︙ | |||
985 986 987 988 989 990 991 |
Tcl_NewBooleanObj(boolValue)
register int boolValue; /* Boolean used to initialize new object. */
{
register Tcl_Obj *objPtr;
TclNewObj(objPtr);
objPtr->bytes = NULL;
| | | 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 |
Tcl_NewBooleanObj(boolValue)
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;
return objPtr;
}
#endif /* TCL_MEM_DEBUG */
/*
|
| ︙ | ︙ | |||
1032 1033 1034 1035 1036 1037 1038 |
int line; /* Line number in the source file; used
* for debugging. */
{
register Tcl_Obj *objPtr;
TclDbNewObj(objPtr, file, line);
objPtr->bytes = NULL;
| | | 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 |
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;
return objPtr;
}
#else /* if not TCL_MEM_DEBUG */
|
| ︙ | ︙ | |||
1078 1079 1080 1081 1082 1083 1084 |
Tcl_SetBooleanObj(objPtr, boolValue)
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)) {
| | | | | 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 |
Tcl_SetBooleanObj(objPtr, boolValue)
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)) {
Tcl_Panic("Tcl_SetBooleanObj called with shared object");
}
if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
oldTypePtr->freeIntRepProc(objPtr);
}
objPtr->internalRep.longValue = (boolValue? 1 : 0);
objPtr->typePtr = &tclBooleanType;
Tcl_InvalidateStringRep(objPtr);
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
1106 1107 1108 1109 1110 1111 1112 | * Results: * The return value is a standard Tcl object result. If an error occurs * during conversion, an error message is left in the interpreter's * result unless "interp" is NULL. * * Side effects: * If the object is not already a boolean, the conversion will free | | | 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 |
* Results:
* The return value is a standard Tcl object result. If an error occurs
* during conversion, an error message is left in the interpreter's
* result unless "interp" is NULL.
*
* Side effects:
* If the object is not already a boolean, the conversion will free
* any old internal representation.
*
*----------------------------------------------------------------------
*/
int
Tcl_GetBooleanFromObj(interp, objPtr, boolPtr)
Tcl_Interp *interp; /* Used for error reporting if not NULL. */
|
| ︙ | ︙ | |||
1159 1160 1161 1162 1163 1164 1165 |
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;
| | | | > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | < | < < > | > > > | < | < < > > > | > | > > > | > > > > > | | < < < < > | > | | | > > | < | | < | > > > > | > > > | | | < < < | | > > | > | | | | | | | | > | | | | > | | | > | | | 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 |
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[8];
int newBool, length;
register int i;
/*
* Get the string representation. Make it up-to-date if necessary.
*/
string = Tcl_GetStringFromObj(objPtr, &length);
/*
* Use the obvious shortcuts for numerical values; if objPtr is not
* of numerical type, parse its string rep.
*/
if (objPtr->typePtr == &tclIntType) {
newBool = (objPtr->internalRep.longValue != 0);
goto goodBoolean;
} else if (objPtr->typePtr == &tclDoubleType) {
newBool = (objPtr->internalRep.doubleValue != 0.0);
goto goodBoolean;
} else if (objPtr->typePtr == &tclWideIntType) {
#ifdef TCL_WIDE_INT_IS_LONG
newBool = (objPtr->internalRep.longValue != 0);
#else /* !TCL_WIDE_INT_IS_LONG */
newBool = (objPtr->internalRep.wideValue != Tcl_LongAsWide(0));
#endif /* TCL_WIDE_INT_IS_LONG */
goto goodBoolean;
}
/*
* Parse the string as a boolean. We use an implementation here
* that doesn't report errors in interp if interp is NULL.
*
* First we define a macro to factor out the to-lower-case code.
* The len parameter is the maximum number of characters to copy
* to allow the following comparisons to proceed correctly,
* including (properly) the trailing \0 character. This is done
* in multiple places so the number of copying steps is minimised
* and only performed when needed.
*/
#define SBFA_TOLOWER(len) \
for (i=0 ; i<(len) && i<length ; i++) { \
c = string[i]; \
if (c & 0x80) { \
goto badBoolean; \
} \
if (Tcl_UniCharIsUpper(UCHAR(c))) { \
c = (char) Tcl_UniCharToLower(UCHAR(c)); \
} \
lowerCase[i] = c; \
} \
lowerCase[i] = 0;
switch (string[0]) {
case 'y': case 'Y':
/*
* Copy the string converting its characters to lower case.
* This also weeds out international characters so we can
* safely operate on single bytes.
*/
SBFA_TOLOWER(4);
/*
* Checking the 'y' is redundant, but makes the code clearer.
*/
if (strncmp(lowerCase, "yes", (size_t) length) == 0) {
newBool = 1;
goto goodBoolean;
}
goto badBoolean;
case 'n': case 'N':
SBFA_TOLOWER(3);
if (strncmp(lowerCase, "no", (size_t) length) == 0) {
newBool = 0;
goto goodBoolean;
}
goto badBoolean;
case 't': case 'T':
SBFA_TOLOWER(5);
if (strncmp(lowerCase, "true", (size_t) length) == 0) {
newBool = 1;
goto goodBoolean;
}
goto badBoolean;
case 'f': case 'F':
SBFA_TOLOWER(6);
if (strncmp(lowerCase, "false", (size_t) length) == 0) {
newBool = 0;
goto goodBoolean;
}
goto badBoolean;
case 'o': case 'O':
if (length < 2) {
goto badBoolean;
}
SBFA_TOLOWER(4);
if (strncmp(lowerCase, "on", (size_t) length) == 0) {
newBool = 1;
goto goodBoolean;
} else if (strncmp(lowerCase, "off", (size_t) length) == 0) {
newBool = 0;
goto goodBoolean;
}
goto badBoolean;
#undef SBFA_TOLOWER
case '0':
if (string[1] == '\0') {
newBool = 0;
goto goodBoolean;
}
goto parseNumeric;
case '1':
if (string[1] == '\0') {
newBool = 1;
goto goodBoolean;
}
/* deliberate fall-through */
default:
parseNumeric:
{
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);
}
|
| ︙ | ︙ | |||
1335 1336 1337 1338 1339 1340 1341 | /* *---------------------------------------------------------------------- * * UpdateStringOfBoolean -- * * Update the string representation for a boolean object. * Note: This procedure does not free an existing old string rep | | | | 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 |
/*
*----------------------------------------------------------------------
*
* 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;
}
/*
|
| ︙ | ︙ | |||
1401 1402 1403 1404 1405 1406 1407 |
Tcl_NewDoubleObj(dblValue)
register double dblValue; /* Double used to initialize the object. */
{
register Tcl_Obj *objPtr;
TclNewObj(objPtr);
objPtr->bytes = NULL;
| | | 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 |
Tcl_NewDoubleObj(dblValue)
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;
return objPtr;
}
#endif /* if TCL_MEM_DEBUG */
/*
|
| ︙ | ︙ | |||
1448 1449 1450 1451 1452 1453 1454 |
int line; /* Line number in the source file; used
* for debugging. */
{
register Tcl_Obj *objPtr;
TclDbNewObj(objPtr, file, line);
objPtr->bytes = NULL;
| | | 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 |
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;
}
#else /* if not TCL_MEM_DEBUG */
|
| ︙ | ︙ | |||
1494 1495 1496 1497 1498 1499 1500 |
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. */
{
register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
if (Tcl_IsShared(objPtr)) {
| | | | 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 |
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. */
{
register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("Tcl_SetDoubleObj called with shared object");
}
if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
oldTypePtr->freeIntRepProc(objPtr);
}
objPtr->internalRep.doubleValue = dblValue;
objPtr->typePtr = &tclDoubleType;
Tcl_InvalidateStringRep(objPtr);
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
1534 1535 1536 1537 1538 1539 1540 |
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. */
{
register int result;
| | | 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 |
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. */
{
register int result;
if (objPtr->typePtr == &tclDoubleType) {
*dblPtr = objPtr->internalRep.doubleValue;
return TCL_OK;
}
result = SetDoubleFromAny(interp, objPtr);
if (result == TCL_OK) {
|
| ︙ | ︙ | |||
1612 1613 1614 1615 1616 1617 1618 |
}
return TCL_ERROR;
}
/*
* Make sure that the string has no garbage after the end of the double.
*/
| | | | | 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 |
}
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;
|
| ︙ | ︙ | |||
1664 1665 1666 1667 1668 1669 1670 |
static void
UpdateStringOfDouble(objPtr)
register Tcl_Obj *objPtr; /* Double obj with string rep to update. */
{
char buffer[TCL_DOUBLE_SPACE];
register int len;
| | | | | 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 |
static void
UpdateStringOfDouble(objPtr)
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);
len = strlen(buffer);
objPtr->bytes = (char *) ckalloc((unsigned) len + 1);
strcpy(objPtr->bytes, buffer);
objPtr->length = len;
}
/*
*----------------------------------------------------------------------
*
* Tcl_NewIntObj --
*
* 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.
*
* 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.
*
* 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.
*
|
| ︙ | ︙ | |||
1724 1725 1726 1727 1728 1729 1730 |
Tcl_NewIntObj(intValue)
register int intValue; /* Int used to initialize the new object. */
{
register Tcl_Obj *objPtr;
TclNewObj(objPtr);
objPtr->bytes = NULL;
| | | | | | | 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 |
Tcl_NewIntObj(intValue)
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;
return objPtr;
}
#endif /* if TCL_MEM_DEBUG */
/*
*----------------------------------------------------------------------
*
* Tcl_SetIntObj --
*
* Modify an object to be an integer and to have the specified integer
* value.
*
* Results:
* None.
*
* Side effects:
* 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. */
{
register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("Tcl_SetIntObj called with shared object");
}
if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
oldTypePtr->freeIntRepProc(objPtr);
}
objPtr->internalRep.longValue = (long) intValue;
objPtr->typePtr = &tclIntType;
Tcl_InvalidateStringRep(objPtr);
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
1803 1804 1805 1806 1807 1808 1809 |
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. */
{
register long l;
int result;
| | | 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 |
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. */
{
register long l;
int result;
if (objPtr->typePtr != &tclIntType) {
result = SetIntFromAny(interp, objPtr);
if (result != TCL_OK) {
return result;
}
}
l = objPtr->internalRep.longValue;
|
| ︙ | ︙ | |||
1838 1839 1840 1841 1842 1843 1844 | * 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 | | | 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 |
* 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
SetIntFromAny(interp, objPtr)
Tcl_Interp *interp; /* Used for error reporting if not NULL. */
|
| ︙ | ︙ | |||
1870 1871 1872 1873 1874 1875 1876 |
* 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
| | | 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 |
* 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
for (; isspace(UCHAR(*p)) ; p++) { /* INTL: ISO space. */
/* Empty loop body. */
}
if (*p == '-') {
p++;
newLong = -((long)strtoul(p, &end, 0));
} else if (*p == '+') {
p++;
|
| ︙ | ︙ | |||
1908 1909 1910 1911 1912 1913 1914 |
}
return TCL_ERROR;
}
/*
* Make sure that the string has no garbage after the end of the int.
*/
| | | 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 |
}
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;
}
|
| ︙ | ︙ | |||
1940 1941 1942 1943 1944 1945 1946 | /* *---------------------------------------------------------------------- * * UpdateStringOfInt -- * * Update the string representation for an integer object. * Note: This procedure does not free an existing old string rep | | | | | | 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 |
/*
*----------------------------------------------------------------------
*
* 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.
*
* Results:
* None.
*
* Side effects:
* 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. */
{
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;
}
/*
*----------------------------------------------------------------------
*
* 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.
*
* 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
* 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.
*
|
| ︙ | ︙ | |||
2018 2019 2020 2021 2022 2023 2024 |
register long longValue; /* Long integer used to initialize the
* new object. */
{
register Tcl_Obj *objPtr;
TclNewObj(objPtr);
objPtr->bytes = NULL;
| | | 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 |
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;
return objPtr;
}
#endif /* if TCL_MEM_DEBUG */
/*
|
| ︙ | ︙ | |||
2073 2074 2075 2076 2077 2078 2079 |
int line; /* Line number in the source file; used
* for debugging. */
{
register Tcl_Obj *objPtr;
TclDbNewObj(objPtr, file, line);
objPtr->bytes = NULL;
| | | 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 |
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;
}
#else /* if not TCL_MEM_DEBUG */
|
| ︙ | ︙ | |||
2107 2108 2109 2110 2111 2112 2113 | * long integer value. * * Results: * None. * * Side effects: * The object's old string rep, if any, is freed. Also, any old | | | | | 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 |
* long integer value.
*
* Results:
* None.
*
* Side effects:
* 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
* object's value. */
{
register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("Tcl_SetLongObj called with shared object");
}
if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
oldTypePtr->freeIntRepProc(objPtr);
}
objPtr->internalRep.longValue = longValue;
objPtr->typePtr = &tclIntType;
Tcl_InvalidateStringRep(objPtr);
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
2161 2162 2163 2164 2165 2166 2167 |
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. */
{
register int result;
| | | 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 |
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. */
{
register int result;
if (objPtr->typePtr == &tclIntType) {
*longPtr = objPtr->internalRep.longValue;
return TCL_OK;
}
result = SetIntFromAny(interp, objPtr);
if (result == TCL_OK) {
*longPtr = objPtr->internalRep.longValue;
|
| ︙ | ︙ | |||
2188 2189 2190 2191 2192 2193 2194 | * 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 | | | 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 |
* 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. */
|
| ︙ | ︙ | |||
2221 2222 2223 2224 2225 2226 2227 |
* 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
| | | 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 |
* 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++;
|
| ︙ | ︙ | |||
2259 2260 2261 2262 2263 2264 2265 |
}
return TCL_ERROR;
}
/*
* Make sure that the string has no garbage after the end of the int.
*/
| | | | | | 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 |
}
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;
}
#endif
objPtr->typePtr = &tclWideIntType;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* 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.
*
* Results:
* None.
*
* Side effects:
* The object's string is set to a valid string that results from
* the wideInt-to-string conversion.
|
| ︙ | ︙ | |||
2343 2344 2345 2346 2347 2348 2349 | * 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. * * 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 | | | 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 | * 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. * * 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. * * Results: * The newly created object is returned. This object will have an * invalid string representation. The returned object has ref count 0. * * Side effects: |
| ︙ | ︙ | |||
2378 2379 2380 2381 2382 2383 2384 |
register Tcl_WideInt wideValue; /* Wide integer used to initialize
* the new object. */
{
register Tcl_Obj *objPtr;
TclNewObj(objPtr);
objPtr->bytes = NULL;
| | | 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 |
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;
return objPtr;
}
#endif /* if TCL_MEM_DEBUG */
/*
|
| ︙ | ︙ | |||
2435 2436 2437 2438 2439 2440 2441 |
int line; /* Line number in the source file;
* used for debugging. */
{
register Tcl_Obj *objPtr;
TclDbNewObj(objPtr, file, line);
objPtr->bytes = NULL;
| | | 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 |
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;
return objPtr;
}
#else /* if not TCL_MEM_DEBUG */
|
| ︙ | ︙ | |||
2470 2471 2472 2473 2474 2475 2476 | * specified wide integer value. * * Results: * None. * * Side effects: * The object's old string rep, if any, is freed. Also, any old | | | | | 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 |
* 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.
*
*----------------------------------------------------------------------
*/
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. */
{
register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("Tcl_SetWideIntObj called with shared object");
}
if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
oldTypePtr->freeIntRepProc(objPtr);
}
objPtr->internalRep.wideValue = wideValue;
objPtr->typePtr = &tclWideIntType;
Tcl_InvalidateStringRep(objPtr);
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
2570 2571 2572 2573 2574 2575 2576 |
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);
| | | | | 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 |
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);
Tcl_Panic("Trying to increment 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;
|
| ︙ | ︙ | |||
2634 2635 2636 2637 2638 2639 2640 |
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);
| | | | | 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 |
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);
Tcl_Panic("Trying to decrement 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) {
Tcl_DeleteHashEntry(hPtr);
|
| ︙ | ︙ | |||
2704 2705 2706 2707 2708 2709 2710 |
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);
| | | | | 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 |
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);
Tcl_Panic("Trying to check 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
|
| ︙ | ︙ | |||
2845 2846 2847 2848 2849 2850 2851 |
* Don't use Tcl_GetStringFromObj as it would prevent l1 and l2 being
* in a register.
*/
p1 = Tcl_GetString (objPtr1);
l1 = objPtr1->length;
p2 = Tcl_GetString (objPtr2);
l2 = objPtr2->length;
| | | 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 |
* Don't use Tcl_GetStringFromObj as it would prevent l1 and l2 being
* in a register.
*/
p1 = Tcl_GetString (objPtr1);
l1 = objPtr1->length;
p2 = Tcl_GetString (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;
|
| ︙ | ︙ | |||
2920 2921 2922 2923 2924 2925 2926 |
register CONST char *string;
register int length;
register unsigned int result;
register int c;
string = Tcl_GetString (objPtr);
length = objPtr->length;
| | | 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 |
register CONST char *string;
register int length;
register unsigned int result;
register int c;
string = Tcl_GetString (objPtr);
length = objPtr->length;
/*
* 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:
*
|
| ︙ | ︙ | |||
2955 2956 2957 2958 2959 2960 2961 | } /* *---------------------------------------------------------------------- * * Tcl_GetCommandFromObj -- * | | | | | 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 | } /* *---------------------------------------------------------------------- * * Tcl_GetCommandFromObj -- * * 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. * * 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. * *---------------------------------------------------------------------- */ Tcl_Command Tcl_GetCommandFromObj(interp, objPtr) |
| ︙ | ︙ | |||
2989 2990 2991 2992 2993 2994 2995 |
Namespace *currNsPtr;
int result;
CallFrame *savedFramePtr;
char *name;
/*
* If the variable name is fully qualified, do as if the lookup were
| | | | | | 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 |
Namespace *currNsPtr;
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.
*/
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;
}
/*
* 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) {
|
| ︙ | ︙ | |||
3099 3100 3101 3102 3103 3104 3105 |
register ResolvedCmdName *resPtr;
Tcl_ObjType *oldTypePtr = objPtr->typePtr;
register Namespace *currNsPtr;
if (oldTypePtr == &tclCmdNameType) {
return;
}
| | | | | | | 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 |
register ResolvedCmdName *resPtr;
Tcl_ObjType *oldTypePtr = objPtr->typePtr;
register Namespace *currNsPtr;
if (oldTypePtr == &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);
}
objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) resPtr;
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
objPtr->typePtr = &tclCmdNameType;
}
|
| ︙ | ︙ | |||
3140 3141 3142 3143 3144 3145 3146 | * representation. * * Results: * None. * * Side effects: * Decrements the ref count of any cached ResolvedCmdName structure | | | | | | | 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 |
* representation.
*
* Results:
* None.
*
* 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.
*
*----------------------------------------------------------------------
*/
static void
FreeCmdNameInternalRep(objPtr)
register Tcl_Obj *objPtr; /* CmdName object with internal
* representation to free. */
{
register ResolvedCmdName *resPtr =
(ResolvedCmdName *) objPtr->internalRep.twoPtrValue.ptr1;
if (resPtr != NULL) {
/*
* 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.
*/
Command *cmdPtr = resPtr->cmdPtr;
TclCleanupCommand(cmdPtr);
ckfree((char *) resPtr);
}
}
}
/*
*----------------------------------------------------------------------
*
* DupCmdNameInternalRep --
*
* 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
|
| ︙ | ︙ | |||
3270 3271 3272 3273 3274 3275 3276 |
cmd = Tcl_FindCommand(interp, name, (Tcl_Namespace *) NULL,
/*flags*/ 0);
cmdPtr = (Command *) cmd;
if (cmdPtr != NULL) {
/*
* Get the current namespace.
*/
| | | | | | | | | | | 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 |
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 */
}
/*
* 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.
*/
if ((objPtr->typePtr != NULL)
&& (objPtr->typePtr->freeIntRepProc != NULL)) {
objPtr->typePtr->freeIntRepProc(objPtr);
}
objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) resPtr;
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
objPtr->typePtr = &tclCmdNameType;
return TCL_OK;
}
|
Changes to generic/tclParse.c.
| ︙ | ︙ | |||
9 10 11 12 13 14 15 | * 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. * | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | * 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. * * RCS: @(#) $Id: tclParse.c,v 1.27.2.2 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" /* * The following table provides parsing information about each possible |
| ︙ | ︙ | |||
603 604 605 606 607 608 609 610 611 612 613 614 615 616 |
/*
* The following loop parses the words of the command, one word
* in each iteration through the loop.
*/
parsePtr->commandStart = src;
while (1) {
/*
* Create the token for the word.
*/
TclGrowParseTokenArray(parsePtr,1);
wordIndex = parsePtr->numTokens;
tokenPtr = &parsePtr->tokenPtr[wordIndex];
| > > | 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 |
/*
* 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.
*/
TclGrowParseTokenArray(parsePtr,1);
wordIndex = parsePtr->numTokens;
tokenPtr = &parsePtr->tokenPtr[wordIndex];
|
| ︙ | ︙ | |||
633 634 635 636 637 638 639 | break; } tokenPtr->start = src; parsePtr->numTokens++; parsePtr->numWords++; /* | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 |
break;
}
tokenPtr->start = src;
parsePtr->numTokens++;
parsePtr->numWords++;
/*
* 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 (ParseQuotedString(interp, src, numBytes,
parsePtr, flags | PARSE_APPEND, &termPtr) != TCL_OK) {
goto error;
}
src = termPtr; numBytes = parsePtr->end - src;
} else if (*src == '{') {
static char expPfx[] = "expand";
CONST size_t expPfxLen = sizeof(expPfx) - 1;
int expIdx = wordIndex + 1;
Tcl_Token *expPtr;
if (ParseBraces(interp, src, numBytes,
parsePtr, flags | PARSE_APPEND, &termPtr) != TCL_OK) {
goto error;
}
src = termPtr; numBytes = parsePtr->end - src;
/*
* Check whether the braces contained
* the word expansion prefix.
*/
expPtr = &parsePtr->tokenPtr[expIdx];
if ( (expPfxLen == (size_t) expPtr->size)
/* Same length as prefix */
&& (0 == expandWord)
/* Haven't seen prefix already */
&& (1 == parsePtr->numTokens - expIdx)
/* Only one token */
&& (0 == strncmp(expPfx,expPtr->start,expPfxLen))
/* Is the prefix */
&& (numBytes > 0)
&& (TclParseWhiteSpace(termPtr, numBytes, parsePtr, &type)
== 0)
&& (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.
*/
if (ParseTokens(src, numBytes, TYPE_SPACE|terminators,
|
| ︙ | ︙ | |||
676 677 678 679 680 681 682 683 684 685 686 687 688 689 |
tokenPtr = &parsePtr->tokenPtr[wordIndex];
tokenPtr->size = src - tokenPtr->start;
tokenPtr->numComponents = parsePtr->numTokens - (wordIndex + 1);
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.
*/
| > > > | 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 |
tokenPtr = &parsePtr->tokenPtr[wordIndex];
tokenPtr->size = src - tokenPtr->start;
tokenPtr->numComponents = parsePtr->numTokens - (wordIndex + 1);
if ((tokenPtr->numComponents == 1)
&& (tokenPtr[1].type == TCL_TOKEN_TEXT)) {
tokenPtr->type = TCL_TOKEN_SIMPLE_WORD;
}
if (expandWord) {
tokenPtr->type = TCL_TOKEN_EXPAND_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.
*/
|
| ︙ | ︙ | |||
1303 1304 1305 1306 1307 1308 1309 |
numBytes -= tokenPtr->size;
} else if (*src == 0) {
tokenPtr->type = TCL_TOKEN_TEXT;
tokenPtr->size = 1;
parsePtr->numTokens++;
src++; numBytes--;
} else {
| | | 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 |
numBytes -= tokenPtr->size;
} else if (*src == 0) {
tokenPtr->type = TCL_TOKEN_TEXT;
tokenPtr->size = 1;
parsePtr->numTokens++;
src++; numBytes--;
} else {
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.
|
| ︙ | ︙ | |||
2312 2313 2314 2315 2316 2317 2318 | } /* *---------------------------------------------------------------------- * * CommandComplete -- * | | | | | 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 | } /* *---------------------------------------------------------------------- * * CommandComplete -- * * This procedure 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. * * Side effects: |
| ︙ | ︙ |
Changes to generic/tclPathObj.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* * 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. * | | | | | | > > | 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 |
/*
* 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.
*
* RCS: @(#) $Id: tclPathObj.c,v 1.3.2.4 2004/02/07 05:48:01 dgp Exp $
*/
#include "tclInt.h"
#include "tclPort.h"
#ifdef MAC_TCL
#include "tclMacInt.h"
#endif
#include "tclFileSystem.h"
/*
* 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 *pathPtr));
static void UpdateStringOfFsPath _ANSI_ARGS_((Tcl_Obj *pathPtr));
static int SetFsPathFromAny _ANSI_ARGS_((Tcl_Interp *interp,
Tcl_Obj *pathPtr));
static int FindSplitPos _ANSI_ARGS_((CONST char *path, int separator));
static int IsSeparatorOrNull _ANSI_ARGS_((int ch));
static Tcl_Obj* GetExtension _ANSI_ARGS_((Tcl_Obj *pathPtr));
/*
* Define the 'path' object type, which Tcl uses to represent
* file paths internally.
*/
Tcl_ObjType tclFsPathType = {
|
| ︙ | ︙ | |||
49 50 51 52 53 54 55 | * 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. * | | | > > > > > > > > > > > > > > > > > | > > > > > > | | | < < > > > | > | < | | | > > > > < > | > > > | > | > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > | > > > > > > > > > > > > > > | > > | > > > | > > > > > > > > > | < | | > > > > > > > > > > > > > > > > > > > > | > > > > | < > > > > > > > | > > > > > > > > > > > > > > > | > > | > > > | > > > | > > | | > > > > > > > > > | > | < > | | > | > > > > | > > > > > > | > | < < | | | | | | | | | | | | | < | | | | | | | | | | < < < < < < < < < < < < < < < < < | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 |
* 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 some macros to give us convenient access to path-object
* specific fields.
*/
#define PATHOBJ(pathPtr) (pathPtr->internalRep.otherValuePtr)
#define PATHFLAGS(pathPtr) \
(((FsPath*)(pathPtr->internalRep.otherValuePtr))->flags)
/*
*---------------------------------------------------------------------------
*
* 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.
*
* 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(interp, pathPtr, clientDataPtr)
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 = Tcl_GetString(pathPtr);
if (tclPlatform == TCL_PLATFORM_WINDOWS) {
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 */
if (retVal == NULL) {
CONST char *path = Tcl_GetString(pathPtr);
retVal = Tcl_NewStringObj(path, dirSep - path);
Tcl_IncrRefCount(retVal);
}
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 = Tcl_GetString(pathPtr);
retVal = Tcl_NewStringObj(path, dirSep - path);
Tcl_IncrRefCount(retVal);
}
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)) {
Tcl_DecrRefCount(retVal);
retVal = Tcl_DuplicateObj(retVal);
Tcl_IncrRefCount(retVal);
}
/* We want the trailing slash */
Tcl_SetObjLength(retVal, curLen+1);
Tcl_AppendObjToObj(retVal, link);
Tcl_DecrRefCount(link);
linkStr = Tcl_GetStringFromObj(retVal, &curLen);
} else {
/* Absolute link */
Tcl_DecrRefCount(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 */
while (--curLen >= 0) {
if (IsSeparatorOrNull(linkStr[curLen])) {
Tcl_SetObjLength(retVal, curLen);
break;
}
}
}
dirSep += 3;
oldDirSep = dirSep;
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.
*/
Tcl_DecrRefCount(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)) {
Tcl_DecrRefCount(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). MacOS is case-insensitive.
*
* 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 */
return retVal;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
232 233 234 235 236 237 238 | * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_PathType | | | | | 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 |
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
Tcl_PathType
Tcl_FSGetPathType(pathPtr)
Tcl_Obj *pathPtr;
{
return TclFSGetPathType(pathPtr, NULL, NULL);
}
/*
*----------------------------------------------------------------------
*
* TclFSGetPathType --
*
|
| ︙ | ︙ | |||
263 264 265 266 267 268 269 | * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_PathType | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 |
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
Tcl_PathType
TclFSGetPathType(pathPtr, filesystemPtrPtr, driveNameLengthPtr)
Tcl_Obj *pathPtr;
Tcl_Filesystem **filesystemPtrPtr;
int *driveNameLengthPtr;
{
if (Tcl_FSConvertToPathType(NULL, pathPtr) != TCL_OK) {
return TclGetPathType(pathPtr, filesystemPtrPtr,
driveNameLengthPtr, NULL);
} else {
FsPath *fsPathPtr = (FsPath*) PATHOBJ(pathPtr);
if (fsPathPtr->cwdPtr != NULL) {
if (PATHFLAGS(pathPtr) == 0) {
return TCL_PATH_RELATIVE;
}
return TclFSGetPathType(fsPathPtr->cwdPtr, filesystemPtrPtr,
driveNameLengthPtr);
} else {
return TclGetPathType(pathPtr, filesystemPtrPtr,
driveNameLengthPtr, NULL);
}
}
}
/*
*---------------------------------------------------------------------------
*
* TclPathPart
*
* This procedure calculates the requested part of the 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(interp, pathPtr, portion)
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 = (FsPath*) PATHOBJ(pathPtr);
if (PATHFLAGS(pathPtr) != 0) {
switch (portion) {
case TCL_PATH_DIRNAME: {
Tcl_IncrRefCount(fsPathPtr->cwdPtr);
return fsPathPtr->cwdPtr;
}
case TCL_PATH_TAIL: {
Tcl_IncrRefCount(fsPathPtr->normPathPtr);
return fsPathPtr->normPathPtr;
}
case TCL_PATH_EXTENSION: {
return GetExtension(fsPathPtr->normPathPtr);
}
case TCL_PATH_ROOT: {
/* Unimplemented */
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 {
/*
* Duplicate the object we were given and
* then trim off the extension of the
* tail component of the path.
*/
Tcl_Obj *root;
FsPath *fsDupPtr;
root = Tcl_DuplicateObj(pathPtr);
Tcl_IncrRefCount(root);
fsDupPtr = (FsPath*) PATHOBJ(root);
if (Tcl_IsShared(fsDupPtr->normPathPtr)) {
Tcl_DecrRefCount(fsDupPtr->normPathPtr);
fsDupPtr->normPathPtr = Tcl_NewStringObj(fileName,
(int)(length - strlen(extension)));
Tcl_IncrRefCount(fsDupPtr->normPathPtr);
} else {
Tcl_SetObjLength(fsDupPtr->normPathPtr,
(int)(length - strlen(extension)));
}
return root;
}
}
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;
Tcl_Obj *resultPtr = NULL;
standardPath:
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) && (Tcl_GetString(pathPtr)[0] == '~')) {
Tcl_Obj *norm;
Tcl_DecrRefCount(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)) {
resultPtr = Tcl_NewStringObj(
((tclPlatform == TCL_PLATFORM_MAC) ? ":" : "."), 1);
} else {
Tcl_ListObjIndex(NULL, splitPtr, 0, &resultPtr);
}
}
Tcl_IncrRefCount(resultPtr);
Tcl_DecrRefCount(splitPtr);
return resultPtr;
}
}
/*
* Simple helper function
*/
static Tcl_Obj*
GetExtension(pathPtr)
Tcl_Obj *pathPtr;
{
CONST char *tail, *extension;
Tcl_Obj *ret;
tail = Tcl_GetString(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. If elements < 0,
* we use the entire list.
*
* 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.
*
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
Tcl_Obj*
Tcl_FSJoinPath(listObj, elements)
Tcl_Obj *listObj; /* Path elements to join, may have refCount 0 */
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) {
|
| ︙ | ︙ | |||
334 335 336 337 338 339 340 |
* waste our time joining null elements to the path
*/
if (elements > listTest) {
elements = listTest;
}
}
| | | 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 |
* 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;
int driveNameLength;
Tcl_PathType type;
char *strElt;
int strEltLen;
|
| ︙ | ︙ | |||
373 374 375 376 377 378 379 |
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!
*/
| | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > | | < | < | 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 |
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) 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))) {
if (res != NULL) Tcl_DecrRefCount(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) 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) {
if (res != NULL) Tcl_DecrRefCount(res);
return tail;
}
} else if (tclPlatform == TCL_PLATFORM_MAC) {
if (strchr(str, '/') == NULL) {
if (res != NULL) Tcl_DecrRefCount(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) Tcl_DecrRefCount(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);
Tcl_DecrRefCount(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;
}
/*
* 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 procedure.
*/
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.
*/
int equal = 1;
if (tclPlatform == TCL_PLATFORM_WINDOWS) {
if (strchr(strElt, '\\') != NULL) {
equal = 0;
}
}
if (equal && (tclPlatform != TCL_PLATFORM_MAC)) {
ptr = strElt;
while (*ptr != '\0') {
if (*ptr == '/' && (ptr[1] == '/' || ptr[1] == '\0')) {
equal = 0;
break;
}
ptr++;
}
}
if (equal && (tclPlatform == TCL_PLATFORM_MAC)) {
/*
* If it contains any colons, then it mustn't contain
* any duplicates. Otherwise, the path is in unix-form
* and is no good.
*/
if (strchr(strElt, ':') != NULL) {
ptr = strElt;
while (*ptr != '\0') {
if (*ptr == ':' && (ptr[1] == ':' || ptr[1] == '\0')) {
equal = 0;
break;
}
ptr++;
}
} else {
equal = 0;
}
}
if (equal) {
if (res != NULL) Tcl_DecrRefCount(res);
/*
* This element is just what we want to return already -
* no further manipulation is requred.
*/
return elt;
}
}
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.
|
| ︙ | ︙ | |||
517 518 519 520 521 522 523 | * * Side effects: * The old representation may be freed, and new memory allocated. * *--------------------------------------------------------------------------- */ int | | | | | | | | | | < | < < > | | | | | | | | < > | | > > > > > > > | | | | > > > > > | > > | > > > > > > > > > > > > | > | | | | | | | > | | > > | | | | | | | | < | > > > > > > > | | | | | | | | | | | | | | | | | | | | 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 |
*
* Side effects:
* The old representation may be freed, and new memory allocated.
*
*---------------------------------------------------------------------------
*/
int
Tcl_FSConvertToPathType(interp, pathPtr)
Tcl_Interp *interp; /* Interpreter in which to store error
* message (if necessary). */
Tcl_Obj *pathPtr; /* Object to convert to a valid, current
* path type. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
/*
* 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) {
FsPath *fsPathPtr = (FsPath*) PATHOBJ(pathPtr);
if (fsPathPtr->filesystemEpoch != tsdPtr->filesystemEpoch) {
if (pathPtr->bytes == NULL) {
UpdateStringOfFsPath(pathPtr);
}
FreeFsPathInternalRep(pathPtr);
pathPtr->typePtr = NULL;
return Tcl_ConvertToType(interp, pathPtr, &tclFsPathType);
}
return TCL_OK;
/*
* We used to have more complex code here:
*
* 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);
* pathPtr->typePtr = NULL;
* return Tcl_ConvertToType(interp, pathPtr, &tclFsPathType);
* }
* }
*
* But we no longer believe this is necessary.
*/
} else {
return Tcl_ConvertToType(interp, pathPtr, &tclFsPathType);
}
}
/*
* Helper function for normalization.
*/
static int
IsSeparatorOrNull(ch)
int ch;
{
if (ch == 0) {
return 1;
}
switch (tclPlatform) {
case TCL_PLATFORM_UNIX: {
return (ch == '/' ? 1 : 0);
}
case TCL_PLATFORM_MAC: {
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(path, separator)
CONST char *path;
int 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 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;
tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
pathPtr = 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(pathPtr) = (VOID *) fsPathPtr;
PATHFLAGS(pathPtr) = TCLPATH_APPENDED;
pathPtr->typePtr = &tclFsPathType;
pathPtr->bytes = NULL;
pathPtr->length = 0;
return pathPtr;
}
/*
*---------------------------------------------------------------------------
*
* 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(interp, pathPtr, cwdPtr)
Tcl_Interp *interp; /* Used for error reporting if not NULL. */
Tcl_Obj *pathPtr; /* The object 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 = (FsPath*) PATHOBJ(pathPtr);
if (PATHFLAGS(pathPtr) != 0
&& fsPathPtr->cwdPtr == cwdPtr) {
pathPtr = fsPathPtr->normPathPtr;
/* 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", (char *) NULL);
}
return NULL;
}
pathPtr->typePtr->updateStringProc(pathPtr);
}
if ((pathPtr->typePtr->freeIntRepProc) != NULL) {
(*pathPtr->typePtr->freeIntRepProc)(pathPtr);
}
}
fsPathPtr = (FsPath*)ckalloc((unsigned)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;
PATHOBJ(pathPtr) = (VOID *) 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.
|
| ︙ | ︙ | |||
771 772 773 774 775 776 777 |
break;
case TCL_PLATFORM_MAC:
if (tempStr[cwdLen-1] != ':') {
cwdLen++;
}
break;
}
| | | 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 |
break;
case TCL_PLATFORM_MAC:
if (tempStr[cwdLen-1] != ':') {
cwdLen++;
}
break;
}
tempStr = Tcl_GetStringFromObj(pathPtr, &len);
return Tcl_NewStringObj(tempStr + cwdLen, len - cwdLen);
}
/*
*---------------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
794 795 796 797 798 799 800 | * Side effects: * The old representation may be freed, and new memory allocated. * *--------------------------------------------------------------------------- */ int | | | | | | | | | | > | | | | | 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 |
* Side effects:
* The old representation may be freed, and new memory allocated.
*
*---------------------------------------------------------------------------
*/
int
TclFSMakePathFromNormalized(interp, pathPtr, nativeRep)
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", (char *) NULL);
}
return TCL_ERROR;
}
pathPtr->typePtr->updateStringProc(pathPtr);
}
if ((pathPtr->typePtr->freeIntRepProc) != NULL) {
(*pathPtr->typePtr->freeIntRepProc)(pathPtr);
}
}
fsPathPtr = (FsPath*)ckalloc((unsigned)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;
PATHOBJ(pathPtr) = (VOID *) fsPathPtr;
PATHFLAGS(pathPtr) = 0;
pathPtr->typePtr = &tclFsPathType;
return TCL_OK;
}
/*
*---------------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
872 873 874 875 876 877 878 |
*/
Tcl_Obj *
Tcl_FSNewNativePath(fromFilesystem, clientData)
Tcl_Filesystem* fromFilesystem;
ClientData clientData;
{
| | | | | | | | | | | | | | | | 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 |
*/
Tcl_Obj *
Tcl_FSNewNativePath(fromFilesystem, clientData)
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);
}
if ((pathPtr->typePtr->freeIntRepProc) != NULL) {
(*pathPtr->typePtr->freeIntRepProc)(pathPtr);
}
}
fsPathPtr = (FsPath*)ckalloc((unsigned)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;
PATHOBJ(pathPtr) = (VOID *) fsPathPtr;
PATHFLAGS(pathPtr) = 0;
pathPtr->typePtr = &tclFsPathType;
return pathPtr;
}
/*
*---------------------------------------------------------------------------
*
* Tcl_FSGetTranslatedPath --
*
|
| ︙ | ︙ | |||
952 953 954 955 956 957 958 |
if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {
return NULL;
}
srcFsPathPtr = (FsPath*) PATHOBJ(pathPtr);
if (srcFsPathPtr->translatedPathPtr == NULL) {
if (PATHFLAGS(pathPtr) != 0) {
| | | | | | | | | | > | 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 |
if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {
return NULL;
}
srcFsPathPtr = (FsPath*) PATHOBJ(pathPtr);
if (srcFsPathPtr->translatedPathPtr == NULL) {
if (PATHFLAGS(pathPtr) != 0) {
retObj = Tcl_FSGetNormalizedPath(interp, pathPtr);
} 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;
}
Tcl_IncrRefCount(retObj);
return retObj;
|
| ︙ | ︙ | |||
1029 1030 1031 1032 1033 1034 1035 | * New memory may be allocated. The Tcl 'errno' may be modified * in the process of trying to examine various path possibilities. * *--------------------------------------------------------------------------- */ Tcl_Obj* | | | | | | | | | 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 |
* 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, pathPtr)
Tcl_Interp *interp;
Tcl_Obj* pathPtr;
{
FsPath *fsPathPtr;
if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {
return NULL;
}
fsPathPtr = (FsPath*) 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;
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 (pathPtr->bytes == NULL) {
UpdateStringOfFsPath(pathPtr);
}
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);
|
| ︙ | ︙ | |||
1130 1131 1132 1133 1134 1135 1136 |
fsPathPtr->normPathPtr = copy;
/* That's our reference to copy used */
Tcl_DecrRefCount(dir);
}
if (clientData != NULL) {
fsPathPtr->nativePathPtr = clientData;
}
| | | | | | | | | | 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 |
fsPathPtr->normPathPtr = copy;
/* That's our reference to copy used */
Tcl_DecrRefCount(dir);
}
if (clientData != NULL) {
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);
pathPtr->typePtr = NULL;
if (Tcl_ConvertToType(interp, pathPtr,
&tclFsPathType) != TCL_OK) {
return NULL;
}
fsPathPtr = (FsPath*) PATHOBJ(pathPtr);
} else if (fsPathPtr->normPathPtr == NULL) {
int cwdLen;
Tcl_Obj *copy;
CONST char *cwdStr;
ClientData clientData = NULL;
copy = Tcl_DuplicateObj(fsPathPtr->cwdPtr);
|
| ︙ | ︙ | |||
1181 1182 1183 1184 1185 1186 1187 |
case TCL_PLATFORM_MAC:
if (cwdStr[cwdLen-1] != ':') {
Tcl_AppendToObj(copy, ":", 1);
cwdLen++;
}
break;
}
| | | 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 |
case TCL_PLATFORM_MAC:
if (cwdStr[cwdLen-1] != ':') {
Tcl_AppendToObj(copy, ":", 1);
cwdLen++;
}
break;
}
Tcl_AppendObjToObj(copy, pathPtr);
/*
* 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));
|
| ︙ | ︙ | |||
1212 1213 1214 1215 1216 1217 1218 |
/*
* 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') {
| | | 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 |
/*
* 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(pathPtr);
if (type == TCL_PATH_RELATIVE) {
useThisCwd = Tcl_FSGetCwd(interp);
if (useThisCwd == NULL) return NULL;
absolutePath = Tcl_FSJoinToPath(useThisCwd, 1, &absolutePath);
Tcl_IncrRefCount(absolutePath);
|
| ︙ | ︙ | |||
1255 1256 1257 1258 1259 1260 1261 |
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.
*/
| > | > | | | | < < < < > > > > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | > > | > > | 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 |
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.
*/
int cwdLen;
CONST char *drive = Tcl_GetStringFromObj(useThisCwd,
&cwdLen);
char drive_cur = path[0];
if (drive_cur >= 'a') {
drive_cur -= ('a' - 'A');
}
if (drive[0] == drive_cur) {
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);
if (drive[cwdLen-1] != '/') {
/* Only add a trailing '/' if needed */
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);
}
/*
* Check if path is pure normalized (this can only be the case
* if it is an absolute path).
*/
if (useThisCwd == NULL) {
if (!strcmp(Tcl_GetString(fsPathPtr->normPathPtr),
Tcl_GetString(pathPtr))) {
/*
* 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 = pathPtr;
}
} else {
/*
* 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.
*/
Tcl_DecrRefCount(absolutePath);
fsPathPtr->cwdPtr = useThisCwd;
}
}
return fsPathPtr->normPathPtr;
}
|
| ︙ | ︙ | |||
1328 1329 1330 1331 1332 1333 1334 | * Side effects: * An attempt may be made to convert the object. * *--------------------------------------------------------------------------- */ ClientData | | | | | | 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 |
* Side effects:
* An attempt may be made to convert the object.
*
*---------------------------------------------------------------------------
*/
ClientData
Tcl_FSGetInternalRep(pathPtr, fsPtr)
Tcl_Obj* pathPtr;
Tcl_Filesystem *fsPtr;
{
FsPath* srcFsPathPtr;
if (Tcl_FSConvertToPathType(NULL, pathPtr) != TCL_OK) {
return NULL;
}
srcFsPathPtr = (FsPath*) 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
|
| ︙ | ︙ | |||
1364 1365 1366 1367 1368 1369 1370 | * 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. */ | | | | | | | | | < < < | < | | | | | | | | | | < > > > > > > > | | 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 |
* 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 = (FsPath*) PATHOBJ(pathPtr);
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(pathPtr);
if (actualFs == fsPtr) {
return Tcl_FSGetInternalRep(pathPtr, fsPtr);
}
return NULL;
}
if (srcFsPathPtr->nativePathPtr == NULL) {
Tcl_FSCreateInternalRepProc *proc;
proc = srcFsPathPtr->fsRecPtr->fsPtr->createInternalRepProc;
if (proc == NULL) {
return NULL;
}
srcFsPathPtr->nativePathPtr = (*proc)(pathPtr);
}
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(pathPtr, fsPtrPtr)
Tcl_Obj* pathPtr;
Tcl_Filesystem **fsPtrPtr;
{
FsPath* srcFsPathPtr;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
if (pathPtr->typePtr != &tclFsPathType) {
return TCL_OK;
}
srcFsPathPtr = (FsPath*) PATHOBJ(pathPtr);
/*
* 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 (pathPtr->bytes == NULL) {
UpdateStringOfFsPath(pathPtr);
}
FreeFsPathInternalRep(pathPtr);
pathPtr->typePtr = NULL;
if (SetFsPathFromAny(NULL, pathPtr) != TCL_OK) {
return TCL_ERROR;
}
srcFsPathPtr = (FsPath*) PATHOBJ(pathPtr);
}
/* Check whether the object is already assigned to a fs */
if (srcFsPathPtr->fsRecPtr != NULL) {
*fsPtrPtr = srcFsPathPtr->fsRecPtr->fsPtr;
}
return TCL_OK;
}
void
TclFSSetPathDetails(pathPtr, fsRecPtr, clientData)
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 = (FsPath*) PATHOBJ(pathPtr);
srcFsPathPtr->fsRecPtr = fsRecPtr;
srcFsPathPtr->nativePathPtr = clientData;
srcFsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
fsRecPtr->fileRefCount++;
}
/*
|
| ︙ | ︙ | |||
1568 1569 1570 1571 1572 1573 1574 | * Side effects: * The old representation may be freed, and new memory allocated. * *--------------------------------------------------------------------------- */ static int | | | | | | | 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 |
* Side effects:
* The old representation may be freed, and new memory allocated.
*
*---------------------------------------------------------------------------
*/
static int
SetFsPathFromAny(interp, pathPtr)
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;
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, Win
* or MacOS (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='/';
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 '~' */
|
| ︙ | ︙ | |||
1668 1669 1670 1671 1672 1673 1674 | * 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; | | > | > > > > > > | > > | | 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 |
* 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++));
}
Tcl_DecrRefCount(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);
Tcl_DecrRefCount(transPtr);
transPtr = joined;
}
}
Tcl_DStringFree(&temp);
} else {
transPtr = Tcl_FSJoinToPath(pathPtr,0,NULL);
}
#if defined(__CYGWIN__) && defined(__WIN32__)
{
extern int cygwin_conv_to_win32_path
_ANSI_ARGS_((CONST char *, char *));
char winbuf[MAX_PATH+1];
|
| ︙ | ︙ | |||
1716 1717 1718 1719 1720 1721 1722 |
* forward slashes on Windows, and will not contain any ~user
* sequences.
*/
fsPathPtr = (FsPath*)ckalloc((unsigned)sizeof(FsPath));
fsPathPtr->translatedPathPtr = transPtr;
| > | > | | | | | | | | | | | 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 |
* forward slashes on Windows, and will not contain any ~user
* sequences.
*/
fsPathPtr = (FsPath*)ckalloc((unsigned)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.
*/
if (pathPtr->typePtr != NULL && pathPtr->typePtr->freeIntRepProc != NULL) {
(pathPtr->typePtr->freeIntRepProc)(pathPtr);
}
PATHOBJ(pathPtr) = (VOID *) fsPathPtr;
PATHFLAGS(pathPtr) = 0;
pathPtr->typePtr = &tclFsPathType;
return TCL_OK;
}
static void
FreeFsPathInternalRep(pathPtr)
Tcl_Obj *pathPtr; /* Path object with internal rep to free. */
{
FsPath* fsPathPtr = (FsPath*) PATHOBJ(pathPtr);
if (fsPathPtr->translatedPathPtr != NULL) {
if (fsPathPtr->translatedPathPtr != pathPtr) {
Tcl_DecrRefCount(fsPathPtr->translatedPathPtr);
}
}
if (fsPathPtr->normPathPtr != NULL) {
if (fsPathPtr->normPathPtr != pathPtr) {
Tcl_DecrRefCount(fsPathPtr->normPathPtr);
}
fsPathPtr->normPathPtr = NULL;
}
if (fsPathPtr->cwdPtr != NULL) {
Tcl_DecrRefCount(fsPathPtr->cwdPtr);
}
|
| ︙ | ︙ | |||
1776 1777 1778 1779 1780 1781 1782 |
ckfree((char *)fsPathPtr->fsRecPtr);
}
}
ckfree((char*) fsPathPtr);
}
| < | 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 |
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));
|
| ︙ | ︙ | |||
1854 1855 1856 1857 1858 1859 1860 | * Side effects: * Memory may be allocated. * *--------------------------------------------------------------------------- */ static void | | | | | | | 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 |
* Side effects:
* Memory may be allocated.
*
*---------------------------------------------------------------------------
*/
static void
UpdateStringOfFsPath(pathPtr)
register Tcl_Obj *pathPtr; /* path obj with string rep to update. */
{
FsPath* fsPathPtr = (FsPath*) PATHOBJ(pathPtr);
CONST char *cwdStr;
int cwdLen;
Tcl_Obj *copy;
if (PATHFLAGS(pathPtr) == 0 || fsPathPtr->cwdPtr == NULL) {
Tcl_Panic("Called UpdateStringOfFsPath with invalid object");
}
copy = Tcl_DuplicateObj(fsPathPtr->cwdPtr);
Tcl_IncrRefCount(copy);
cwdStr = Tcl_GetStringFromObj(copy, &cwdLen);
/*
|
| ︙ | ︙ | |||
1905 1906 1907 1908 1909 1910 1911 |
if (cwdStr[cwdLen-1] != ':') {
Tcl_AppendToObj(copy, ":", 1);
cwdLen++;
}
break;
}
Tcl_AppendObjToObj(copy, fsPathPtr->normPathPtr);
| | | | 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 |
if (cwdStr[cwdLen-1] != ':') {
Tcl_AppendToObj(copy, ":", 1);
cwdLen++;
}
break;
}
Tcl_AppendObjToObj(copy, fsPathPtr->normPathPtr);
pathPtr->bytes = Tcl_GetStringFromObj(copy, &cwdLen);
pathPtr->length = cwdLen;
copy->bytes = tclEmptyStringRep;
copy->length = 0;
Tcl_DecrRefCount(copy);
}
/*
*---------------------------------------------------------------------------
|
| ︙ | ︙ |
Changes to generic/tclPkg.c.
1 2 3 4 5 6 7 8 9 10 11 | /* * tclPkg.c -- * * This file implements package and version control for Tcl via * the "package" command and a few C APIs. * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * tclPkg.c -- * * This file implements package and version control for Tcl via * the "package" command and a few C APIs. * * 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. * * RCS: @(#) $Id: tclPkg.c,v 1.9.4.1 2004/02/07 05:48:01 dgp Exp $ */ #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 |
| ︙ | ︙ | |||
790 791 792 793 794 795 796 |
return TCL_ERROR;
}
ComparePkgVersions(argv2, argv3, &satisfies);
Tcl_SetIntObj(Tcl_GetObjResult(interp), satisfies);
break;
}
default: {
| | | 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 |
return TCL_ERROR;
}
ComparePkgVersions(argv2, argv3, &satisfies);
Tcl_SetIntObj(Tcl_GetObjResult(interp), satisfies);
break;
}
default: {
Tcl_Panic("Tcl_PackageObjCmd: bad option index to pkgOptions");
}
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ |
Changes to generic/tclPreserve.c.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | * * 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. * | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | * * 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. * * RCS: @(#) $Id: tclPreserve.c,v 1.3.36.2 2004/02/07 05:48:01 dgp Exp $ */ #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 |
| ︙ | ︙ | |||
247 248 249 250 251 252 253 |
}
Tcl_MutexUnlock(&preserveMutex);
/*
* Reference not found. This is a bug in the caller.
*/
| | | 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
}
Tcl_MutexUnlock(&preserveMutex);
/*
* Reference not found. This is a bug in the caller.
*/
Tcl_Panic("Tcl_Release couldn't find reference for 0x%x", clientData);
}
/*
*----------------------------------------------------------------------
*
* Tcl_EventuallyFree --
*
|
| ︙ | ︙ | |||
288 289 290 291 292 293 294 |
Tcl_MutexLock(&preserveMutex);
for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) {
if (refPtr->clientData != clientData) {
continue;
}
if (refPtr->mustFree) {
| | | 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
Tcl_MutexLock(&preserveMutex);
for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) {
if (refPtr->clientData != clientData) {
continue;
}
if (refPtr->mustFree) {
Tcl_Panic("Tcl_EventuallyFree called twice for 0x%x\n", clientData);
}
refPtr->mustFree = 1;
refPtr->freeProc = freeProc;
Tcl_MutexUnlock(&preserveMutex);
return;
}
Tcl_MutexUnlock(&preserveMutex);
|
| ︙ | ︙ | |||
383 384 385 386 387 388 389 |
* doubly dereferencing it will give NULL. */
{
HandleStruct *handlePtr;
handlePtr = (HandleStruct *) handle;
#ifdef TCL_MEM_DEBUG
if (handlePtr->refCount == 0x61616161) {
| | | | 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 |
* doubly dereferencing it will give NULL. */
{
HandleStruct *handlePtr;
handlePtr = (HandleStruct *) handle;
#ifdef TCL_MEM_DEBUG
if (handlePtr->refCount == 0x61616161) {
Tcl_Panic("using previously disposed TclHandle %x", handlePtr);
}
if (handlePtr->ptr2 != handlePtr->ptr) {
Tcl_Panic("someone has changed the block referenced by the handle %x\nfrom %x to %x",
handlePtr, handlePtr->ptr2, handlePtr->ptr);
}
#endif
handlePtr->ptr = NULL;
if (handlePtr->refCount == 0) {
ckfree((char *) handlePtr);
}
|
| ︙ | ︙ | |||
426 427 428 429 430 431 432 |
* memory referenced by this handle. */
{
HandleStruct *handlePtr;
handlePtr = (HandleStruct *) handle;
#ifdef TCL_MEM_DEBUG
if (handlePtr->refCount == 0x61616161) {
| | | | 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 |
* memory referenced by this handle. */
{
HandleStruct *handlePtr;
handlePtr = (HandleStruct *) handle;
#ifdef TCL_MEM_DEBUG
if (handlePtr->refCount == 0x61616161) {
Tcl_Panic("using previously disposed TclHandle %x", handlePtr);
}
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
handlePtr->refCount++;
return handle;
}
|
| ︙ | ︙ | |||
468 469 470 471 472 473 474 |
* memory referenced by this handle. */
{
HandleStruct *handlePtr;
handlePtr = (HandleStruct *) handle;
#ifdef TCL_MEM_DEBUG
if (handlePtr->refCount == 0x61616161) {
| | | | 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 |
* memory referenced by this handle. */
{
HandleStruct *handlePtr;
handlePtr = (HandleStruct *) handle;
#ifdef TCL_MEM_DEBUG
if (handlePtr->refCount == 0x61616161) {
Tcl_Panic("using previously disposed TclHandle %x", handlePtr);
}
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
handlePtr->refCount--;
if ((handlePtr->refCount == 0) && (handlePtr->ptr == NULL)) {
ckfree((char *) handlePtr);
}
}
|
Changes to generic/tclProc.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* * tclProc.c -- * * 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. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* * tclProc.c -- * * 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. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclProc.c,v 1.46.2.3 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" #include "tclCompile.h" /* * Prototypes for static functions in this file |
| ︙ | ︙ | |||
990 991 992 993 994 995 996 |
numArgs = procPtr->numArgs;
varPtr = framePtr->compiledLocals;
localPtr = procPtr->firstLocalPtr;
argCt = objc;
for (i = 1, argCt -= 1; i <= numArgs; i++, argCt--) {
if (!TclIsVarArgument(localPtr)) {
| | | | 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 |
numArgs = procPtr->numArgs;
varPtr = framePtr->compiledLocals;
localPtr = procPtr->firstLocalPtr;
argCt = objc;
for (i = 1, argCt -= 1; i <= numArgs; i++, argCt--) {
if (!TclIsVarArgument(localPtr)) {
Tcl_Panic("TclObjInterpProc: local variable %s is not argument but should be",
localPtr->name);
return TCL_ERROR;
}
if (TclIsVarTemporary(localPtr)) {
Tcl_Panic("TclObjInterpProc: local variable %d is temporary but should be an argument", i);
return TCL_ERROR;
}
/*
* Handle the special case of the last formal being "args". When
* it occurs, assign it a list consisting of all the remaining
* actual arguments.
|
| ︙ | ︙ | |||
1169 1170 1171 1172 1173 1174 1175 |
(*tclByteCodeType.freeIntRepProc)(bodyPtr);
bodyPtr->typePtr = (Tcl_ObjType *) NULL;
}
}
}
if (bodyPtr->typePtr != &tclByteCodeType) {
#ifdef TCL_COMPILE_DEBUG
| < < < | 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 |
(*tclByteCodeType.freeIntRepProc)(bodyPtr);
bodyPtr->typePtr = (Tcl_ObjType *) NULL;
}
}
}
if (bodyPtr->typePtr != &tclByteCodeType) {
#ifdef TCL_COMPILE_DEBUG
if (tclTraceCompile >= 1) {
/*
* Display a line summarizing the top level command we
* are about to compile.
*/
Tcl_Obj *message = Tcl_NewStringObj("Compiling ", -1);
Tcl_IncrRefCount(message);
|
| ︙ | ︙ | |||
1622 1623 1624 1625 1626 1627 1628 | /* *---------------------------------------------------------------------- * * ProcBodySetFromAny -- * * Tcl_ObjType's SetFromAny function for the proc body object. | | | | | | | | | 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 |
/*
*----------------------------------------------------------------------
*
* ProcBodySetFromAny --
*
* Tcl_ObjType's SetFromAny function for the proc body object.
* Calls Tcl_Panic.
*
* Results:
* Theoretically returns a TCL result code.
*
* Side effects:
* Calls Tcl_Panic, since we can't set the value of the object from a
* string representation (or any other internal ones).
*
*----------------------------------------------------------------------
*/
static int
ProcBodySetFromAny(interp, objPtr)
Tcl_Interp *interp; /* current interpreter */
Tcl_Obj *objPtr; /* object pointer */
{
Tcl_Panic("called ProcBodySetFromAny");
/*
* this to keep compilers happy.
*/
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* ProcBodyUpdateString --
*
* Tcl_ObjType's UpdateString function for the proc body object.
* Calls Tcl_Panic.
*
* Results:
* None.
*
* Side effects:
* Calls Tcl_Panic, since we this type has no string representation.
*
*----------------------------------------------------------------------
*/
static void
ProcBodyUpdateString(objPtr)
Tcl_Obj *objPtr; /* the object to update */
{
Tcl_Panic("called ProcBodyUpdateString");
}
/*
*----------------------------------------------------------------------
*
* TclCompileNoOp --
|
| ︙ | ︙ |
Changes to generic/tclStringObj.c.
| ︙ | ︙ | |||
29 30 31 32 33 34 35 | * * 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. * | | | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | * * 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. * * RCS: @(#) $Id: tclStringObj.c,v 1.32.4.2 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" /* * Prototypes for procedures defined later in this file: */ |
| ︙ | ︙ | |||
703 704 705 706 707 708 709 |
/*
* Free any old string rep, then set the string rep to a copy of
* the length bytes starting at "bytes".
*/
if (Tcl_IsShared(objPtr)) {
| | | 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 |
/*
* Free any old string rep, then set the string rep to a copy of
* the length bytes starting at "bytes".
*/
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("Tcl_SetStringObj called with shared object");
}
/*
* Set the type to NULL and free any internal rep for the old type.
*/
if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
|
| ︙ | ︙ | |||
757 758 759 760 761 762 763 |
register int length; /* Number of bytes desired for string
* representation of object, not including
* terminating null byte. */
{
String *stringPtr;
if (Tcl_IsShared(objPtr)) {
| | | 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 |
register int length; /* Number of bytes desired for string
* representation of object, not including
* terminating null byte. */
{
String *stringPtr;
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("Tcl_SetObjLength called with shared object");
}
SetStringFromAny(NULL, objPtr);
stringPtr = GET_STRING(objPtr);
/* Check that we're not extending a pure unicode string */
|
| ︙ | ︙ | |||
852 853 854 855 856 857 858 |
register int length; /* Number of bytes desired for string
* representation of object, not including
* terminating null byte. */
{
String *stringPtr;
if (Tcl_IsShared(objPtr)) {
| | | 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 |
register int length; /* Number of bytes desired for string
* representation of object, not including
* terminating null byte. */
{
String *stringPtr;
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("Tcl_AttemptSetObjLength called with shared object");
}
SetStringFromAny(NULL, objPtr);
stringPtr = GET_STRING(objPtr);
/* Check that we're not extending a pure unicode string */
|
| ︙ | ︙ | |||
1020 1021 1022 1023 1024 1025 1026 |
* the object to indicate not all available
* bytes at "bytes" were appended. */
{
String *stringPtr;
int toCopy = 0;
if (Tcl_IsShared(objPtr)) {
| | | 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 |
* the object to indicate not all available
* bytes at "bytes" were appended. */
{
String *stringPtr;
int toCopy = 0;
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("TclAppendLimitedToObj called with shared object");
}
SetStringFromAny(NULL, objPtr);
if (length < 0) {
length = (bytes ? strlen(bytes) : 0);
}
|
| ︙ | ︙ | |||
1123 1124 1125 1126 1127 1128 1129 |
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)) {
| | | 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 |
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)) {
Tcl_Panic("Tcl_AppendUnicodeToObj called with shared object");
}
if (length == 0) {
return;
}
SetStringFromAny(NULL, objPtr);
|
| ︙ | ︙ | |||
1500 1501 1502 1503 1504 1505 1506 |
register char *string, *dst;
char *static_list[STATIC_LIST_SIZE];
char **args = static_list;
int nargs_space = STATIC_LIST_SIZE;
int nargs, i;
if (Tcl_IsShared(objPtr)) {
| | | 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 |
register char *string, *dst;
char *static_list[STATIC_LIST_SIZE];
char **args = static_list;
int nargs_space = STATIC_LIST_SIZE;
int nargs, i;
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("Tcl_AppendStringsToObj called with shared object");
}
SetStringFromAny(NULL, objPtr);
/*
* Figure out how much space is needed for all the strings, and
* expand the string representation if it isn't big enough. If no
|
| ︙ | ︙ |
Changes to generic/tclStubInit.c.
1 2 3 4 5 6 7 8 9 10 | /* * tclStubInit.c -- * * This file contains the initializers for the Tcl stub vectors. * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /* * tclStubInit.c -- * * This file contains the initializers for the Tcl stub vectors. * * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclStubInit.c,v 1.84.2.8 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" /* * Remove macros that will interfere with the definitions below. |
| ︙ | ︙ | |||
95 96 97 98 99 100 101 |
#endif /* __WIN32__ */
#ifdef MAC_TCL
NULL, /* 9 */
#endif /* MAC_TCL */
TclCreateProc, /* 10 */
TclDeleteCompiledLocalVars, /* 11 */
TclDeleteVars, /* 12 */
| | | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
#endif /* __WIN32__ */
#ifdef MAC_TCL
NULL, /* 9 */
#endif /* MAC_TCL */
TclCreateProc, /* 10 */
TclDeleteCompiledLocalVars, /* 11 */
TclDeleteVars, /* 12 */
NULL, /* 13 */
TclDumpMemoryInfo, /* 14 */
NULL, /* 15 */
TclExprFloatError, /* 16 */
NULL, /* 17 */
NULL, /* 18 */
NULL, /* 19 */
NULL, /* 20 */
|
| ︙ | ︙ | |||
225 226 227 228 229 230 231 |
Tcl_PopCallFrame, /* 128 */
Tcl_PushCallFrame, /* 129 */
Tcl_RemoveInterpResolvers, /* 130 */
Tcl_SetNamespaceResolvers, /* 131 */
TclpHasSockets, /* 132 */
TclpGetDate, /* 133 */
TclpStrftime, /* 134 */
| | | 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
Tcl_PopCallFrame, /* 128 */
Tcl_PushCallFrame, /* 129 */
Tcl_RemoveInterpResolvers, /* 130 */
Tcl_SetNamespaceResolvers, /* 131 */
TclpHasSockets, /* 132 */
TclpGetDate, /* 133 */
TclpStrftime, /* 134 */
NULL, /* 135 */
NULL, /* 136 */
NULL, /* 137 */
TclGetEnv, /* 138 */
NULL, /* 139 */
TclLooksLikeInt, /* 140 */
TclpGetCwd, /* 141 */
TclSetByteCodeFromAny, /* 142 */
|
| ︙ | ︙ | |||
270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
TclUniCharMatch, /* 173 */
TclIncrWideVar2, /* 174 */
TclCallVarTraces, /* 175 */
TclCleanupVar, /* 176 */
TclVarErrMsg, /* 177 */
Tcl_SetStartupScript, /* 178 */
Tcl_GetStartupScript, /* 179 */
};
TclIntPlatStubs tclIntPlatStubs = {
TCL_STUB_MAGIC,
NULL,
#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
TclGetAndDetachPids, /* 0 */
| > > | 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
TclUniCharMatch, /* 173 */
TclIncrWideVar2, /* 174 */
TclCallVarTraces, /* 175 */
TclCleanupVar, /* 176 */
TclVarErrMsg, /* 177 */
Tcl_SetStartupScript, /* 178 */
Tcl_GetStartupScript, /* 179 */
TclNewListObjDirect, /* 180 */
TclDbNewListObjDirect, /* 181 */
};
TclIntPlatStubs tclIntPlatStubs = {
TCL_STUB_MAGIC,
NULL,
#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
TclGetAndDetachPids, /* 0 */
|
| ︙ | ︙ |
Changes to generic/tclTest.c.
| ︙ | ︙ | |||
10 11 12 13 14 15 16 | * 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. * | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | * 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. * * RCS: @(#) $Id: tclTest.c,v 1.67.2.2 2004/02/07 05:48:01 dgp Exp $ */ #define TCL_TEST #include "tclInt.h" #include "tclPort.h" /* |
| ︙ | ︙ | |||
125 126 127 128 129 130 131 132 133 134 135 136 137 138 | /* * 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, | > > > | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | /* * 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)); #ifdef TCL_THREADS static Tcl_ThreadCreateType AsyncThreadProc _ANSI_ARGS_((ClientData)); #endif 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, |
| ︙ | ︙ | |||
358 359 360 361 362 363 364 | 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_ (( | | | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 | 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* pathPtr)); 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_ (( Tcl_Interp *interp, Tcl_Obj *fileName, |
| ︙ | ︙ | |||
415 416 417 418 419 420 421 | 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)); | | > > > > > > > | 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 |
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* SimpleRedirect _ANSI_ARGS_ ((Tcl_Obj *pathPtr));
static int SimpleMatchInDirectory _ANSI_ARGS_ ((
Tcl_Interp *interp, Tcl_Obj *resultPtr,
Tcl_Obj *dirPtr, CONST char *pattern,
Tcl_GlobTypeData *types));
static int TestNumUtfCharsCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *CONST objv[]));
static int TestHashSystemHashCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *CONST objv[]));
static Tcl_Filesystem testReportingFilesystem = {
"reporting",
sizeof(Tcl_Filesystem),
TCL_FILESYSTEM_VERSION_1,
&TestReportInFilesystem, /* path in */
|
| ︙ | ︙ | |||
475 476 477 478 479 480 481 |
* one representation */
NULL,
NULL,
NULL,
&SimpleStat,
&SimpleAccess,
&SimpleOpenFileChannel,
| < > | 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 |
* one representation */
NULL,
NULL,
NULL,
&SimpleStat,
&SimpleAccess,
&SimpleOpenFileChannel,
&SimpleMatchInDirectory,
NULL,
/* We choose not to support symbolic links inside our vfs's */
NULL,
&SimpleListVolumes,
NULL,
NULL,
NULL,
|
| ︙ | ︙ | |||
616 617 618 619 620 621 622 623 624 625 626 627 628 629 |
(ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateCommand(interp, "testfevent", TestfeventCmd, (ClientData) 0,
(Tcl_CmdDeleteProc *) NULL);
Tcl_CreateObjCommand(interp, "testfilelink", TestfilelinkCmd,
(ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateObjCommand(interp, "testfile", TestfileCmd,
(ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateCommand(interp, "testgetassocdata", TestgetassocdataCmd,
(ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateCommand(interp, "testgetplatform", TestgetplatformCmd,
(ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateObjCommand(interp, "testgetvarfullname",
TestgetvarfullnameCmd, (ClientData) 0,
(Tcl_CmdDeleteProc *) NULL);
| > > > | 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 |
(ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateCommand(interp, "testfevent", TestfeventCmd, (ClientData) 0,
(Tcl_CmdDeleteProc *) NULL);
Tcl_CreateObjCommand(interp, "testfilelink", TestfilelinkCmd,
(ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateObjCommand(interp, "testfile", TestfileCmd,
(ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateObjCommand(interp, "testhashsystemhash",
TestHashSystemHashCmd, (ClientData) 0,
(Tcl_CmdDeleteProc *) NULL);
Tcl_CreateCommand(interp, "testgetassocdata", TestgetassocdataCmd,
(ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateCommand(interp, "testgetplatform", TestgetplatformCmd,
(ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateObjCommand(interp, "testgetvarfullname",
TestgetvarfullnameCmd, (ClientData) 0,
(Tcl_CmdDeleteProc *) NULL);
|
| ︙ | ︙ | |||
830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 |
if (asyncPtr->id == id) {
Tcl_AsyncMark(asyncPtr->handler);
break;
}
}
Tcl_SetResult(interp, (char *)argv[3], TCL_VOLATILE);
return code;
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
"\": must be create, delete, int, or mark",
(char *) NULL);
return TCL_ERROR;
}
return TCL_OK;
}
static int
AsyncHandlerProc(clientData, interp, code)
ClientData clientData; /* Pointer to TestAsyncHandler structure. */
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 |
if (asyncPtr->id == id) {
Tcl_AsyncMark(asyncPtr->handler);
break;
}
}
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",
(char *) NULL);
return TCL_ERROR;
#else /* !TCL_THREADS */
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
"\": must be create, delete, int, or mark",
(char *) NULL);
return TCL_ERROR;
#endif
}
return TCL_OK;
}
static int
AsyncHandlerProc(clientData, interp, code)
ClientData clientData; /* Pointer to TestAsyncHandler structure. */
|
| ︙ | ︙ | |||
869 870 871 872 873 874 875 876 877 878 879 880 881 882 |
* checking is needed here.
*/
}
ckfree((char *)cmd);
return code;
}
/*
*----------------------------------------------------------------------
*
* TestcmdinfoCmd --
*
* This procedure implements the "testcmdinfo" command. It is used
* to test Tcl_GetCommandInfo, Tcl_SetCommandInfo, and command creation
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 |
* checking is needed here.
*/
}
ckfree((char *)cmd);
return 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 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
|
| ︙ | ︙ | |||
3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 |
Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,
Tcl_NewStringObj(parsePtr->commandStart, parsePtr->commandSize));
Tcl_ListObjAppendElement((Tcl_Interp *) 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:
| > > > | 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 |
Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,
Tcl_NewStringObj(parsePtr->commandStart, parsePtr->commandSize));
Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,
Tcl_NewIntObj(parsePtr->numWords));
for (i = 0; i < parsePtr->numTokens; i++) {
tokenPtr = &parsePtr->tokenPtr[i];
switch (tokenPtr->type) {
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:
|
| ︙ | ︙ | |||
3936 3937 3938 3939 3940 3941 3942 |
/*
* Put the arguments into a var args structure
* Append all of the arguments together separated by spaces
*/
argString = Tcl_Merge(argc-1, argv+1);
| | | 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 |
/*
* Put the arguments into a var args structure
* Append all of the arguments together separated by spaces
*/
argString = Tcl_Merge(argc-1, argv+1);
Tcl_Panic(argString);
ckfree((char *)argString);
return TCL_OK;
}
/*
*---------------------------------------------------------------------------
|
| ︙ | ︙ | |||
5693 5694 5695 5696 5697 5698 5699 |
for (prevEsPtr = statePtr->scriptRecordPtr;
(prevEsPtr != (EventScriptRecord *) NULL) &&
(prevEsPtr->nextPtr != esPtr);
prevEsPtr = prevEsPtr->nextPtr) {
/* Empty loop body. */
}
if (prevEsPtr == (EventScriptRecord *) NULL) {
| | | 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 |
for (prevEsPtr = statePtr->scriptRecordPtr;
(prevEsPtr != (EventScriptRecord *) NULL) &&
(prevEsPtr->nextPtr != esPtr);
prevEsPtr = prevEsPtr->nextPtr) {
/* Empty loop body. */
}
if (prevEsPtr == (EventScriptRecord *) 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);
|
| ︙ | ︙ | |||
5980 5981 5982 5983 5984 5985 5986 | } /* * Simple helper function to extract the native vfs representation of a * path object, or NULL if no such representation exists. */ static Tcl_Obj* | | | | 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 |
}
/*
* 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* pathPtr) {
return (Tcl_Obj*) Tcl_FSGetInternalRep(pathPtr, &testReportingFilesystem);
}
static void
TestReportFreeInternalRep(ClientData clientData) {
Tcl_Obj *nativeRep = (Tcl_Obj*)clientData;
if (nativeRep != NULL) {
/* Free the path */
|
| ︙ | ︙ | |||
6246 6247 6248 6249 6250 6251 6252 |
if (strncmp(str,"simplefs:/",10)) {
return -1;
}
return TCL_OK;
}
/*
| < < < < < < < < < | | | | > | | < | | < | | < < | 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 |
if (strncmp(str,"simplefs:/",10)) {
return -1;
}
return TCL_OK;
}
/*
* 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[];
|
| ︙ | ︙ | |||
6295 6296 6297 6298 6299 6300 6301 |
}
if (Tcl_GetBooleanFromObj(interp, objv[1], &boolVal) != TCL_OK) {
return TCL_ERROR;
}
if (boolVal) {
res = Tcl_FSRegister((ClientData)interp, &simpleFilesystem);
msg = (res == TCL_OK) ? "registered" : "failed";
| < < < < < < < | | < | | | > > > > > > > > | | | > | > > > > > > > > > > > > > > > > > > > > | > | > > > > > > > > > > | < < | < | | | < < | 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 |
}
if (Tcl_GetBooleanFromObj(interp, objv[1], &boolVal) != TCL_OK) {
return TCL_ERROR;
}
if (boolVal) {
res = Tcl_FSRegister((ClientData)interp, &simpleFilesystem);
msg = (res == TCL_OK) ? "registered" : "failed";
} else {
res = Tcl_FSUnregister(&simpleFilesystem);
msg = (res == TCL_OK) ? "unregistered" : "failed";
}
Tcl_SetResult(interp, msg, TCL_VOLATILE);
return res;
}
/*
* Treats a file name 'simplefs:/foo' by using the file 'foo'
* in the current (native) directory.
*/
static Tcl_Obj*
SimpleRedirect(pathPtr)
Tcl_Obj *pathPtr; /* Name of file to copy. */
{
int len;
CONST char *str;
Tcl_Obj *origPtr;
/*
* We assume the same name in the current directory is ok.
*/
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;
}
static int
SimpleMatchInDirectory(interp, resultPtr, dirPtr, pattern, types)
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;
/* We only provide a new volume, therefore no mounts at all */
if (types != NULL && types->type & TCL_GLOB_TYPE_MOUNT) {
return TCL_OK;
}
/*
* We assume the same name in the current directory is ok.
*/
resPtr = Tcl_NewObj();
Tcl_IncrRefCount(resPtr);
origPtr = SimpleRedirect(dirPtr);
Tcl_IncrRefCount(origPtr);
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. */
|
| ︙ | ︙ | |||
6364 6365 6366 6367 6368 6369 6370 |
if ((mode != 0) && !(mode & O_RDONLY)) {
Tcl_AppendResult(interp, "read-only",
(char *) NULL);
return NULL;
}
| | < < < < < < | < < < < < < < | > > > | > | < < < < | < | | < | 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 |
if ((mode != 0) && !(mode & O_RDONLY)) {
Tcl_AppendResult(interp, "read-only",
(char *) NULL);
return NULL;
}
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. */
{
int res;
Tcl_Obj *tempPtr = SimpleRedirect(pathPtr);
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. */
{
int res;
Tcl_Obj *tempPtr = SimpleRedirect(pathPtr);
res = Tcl_FSStat(tempPtr, bufPtr);
Tcl_DecrRefCount(tempPtr);
return res;
}
static Tcl_Obj*
SimpleListVolumes(void)
{
/* Add one new volume */
Tcl_Obj *retVal;
|
| ︙ | ︙ | |||
6442 6443 6444 6445 6446 6447 6448 |
(void) Tcl_GetStringFromObj(objv[1], &len);
}
len = Tcl_NumUtfChars(Tcl_GetString(objv[1]), len);
Tcl_SetObjResult(interp, Tcl_NewIntObj(len));
}
return TCL_OK;
}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 |
(void) Tcl_GetStringFromObj(objv[1], &len);
}
len = Tcl_NumUtfChars(Tcl_GetString(objv[1]), len);
Tcl_SetObjResult(interp, Tcl_NewIntObj(len));
}
return TCL_OK;
}
/*
* Used to do basic checks of the TCL_HASH_KEY_SYSTEM_HASH flag
*/
static int
TestHashSystemHashCmd(clientData, interp, objc, objv)
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 *)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) (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 *)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 ((int)(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;
}
|
Changes to generic/tclThreadAlloc.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* * 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. * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* * 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. * * 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. * * RCS: @(#) $Id: tclThreadAlloc.c,v 1.6.2.1 2004/02/07 05:48:01 dgp Exp $ */ #if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) #include "tclInt.h" #ifdef WIN32 |
| ︙ | ︙ | |||
113 114 115 116 117 118 119 | /* * The following array specifies various per-bucket * limits and locks. The values are statically initialized * to avoid calculating them repeatedly. */ | | | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
/*
* The following array specifies various per-bucket
* limits and locks. The values are statically initialized
* to avoid calculating them repeatedly.
*/
static struct {
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] = {
{ 16, 1024, 512, NULL},
{ 32, 512, 256, NULL},
|
| ︙ | ︙ | |||
205 206 207 208 209 210 211 |
* Get this thread's cache, allocating if necessary.
*/
cachePtr = TclpGetAllocCache();
if (cachePtr == NULL) {
cachePtr = calloc(1, sizeof(Cache));
if (cachePtr == NULL) {
| | | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
* Get this thread's cache, allocating if necessary.
*/
cachePtr = TclpGetAllocCache();
if (cachePtr == NULL) {
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);
|
| ︙ | ︙ | |||
531 532 533 534 535 536 537 |
MoveObjs(sharedPtr, cachePtr, nmove);
}
Tcl_MutexUnlock(objLockPtr);
if (cachePtr->nobjs == 0) {
cachePtr->nobjs = nmove = NOBJALLOC;
newObjsPtr = malloc(sizeof(Tcl_Obj) * nmove);
if (newObjsPtr == NULL) {
| | | 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 |
MoveObjs(sharedPtr, cachePtr, nmove);
}
Tcl_MutexUnlock(objLockPtr);
if (cachePtr->nobjs == 0) {
cachePtr->nobjs = nmove = NOBJALLOC;
newObjsPtr = malloc(sizeof(Tcl_Obj) * nmove);
if (newObjsPtr == NULL) {
Tcl_Panic("alloc: could not allocate %d new objects", nmove);
}
while (--nmove >= 0) {
objPtr = &newObjsPtr[nmove];
objPtr->internalRep.otherValuePtr = cachePtr->firstObjPtr;
cachePtr->firstObjPtr = objPtr;
}
}
|
| ︙ | ︙ | |||
738 739 740 741 742 743 744 |
blockPtr = (((Block *) ptr) - 1);
if (blockPtr->b_magic1 != MAGIC
#if RCHECK
|| ((unsigned char *) ptr)[blockPtr->b_reqsize] != MAGIC
#endif
|| blockPtr->b_magic2 != MAGIC) {
| | | 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 |
blockPtr = (((Block *) ptr) - 1);
if (blockPtr->b_magic1 != MAGIC
#if RCHECK
|| ((unsigned char *) ptr)[blockPtr->b_reqsize] != MAGIC
#endif
|| blockPtr->b_magic2 != MAGIC) {
Tcl_Panic("alloc: invalid block: %p: %x %x %x\n",
blockPtr, blockPtr->b_magic1, blockPtr->b_magic2,
((unsigned char *) ptr)[blockPtr->b_reqsize]);
}
return blockPtr;
}
|
| ︙ | ︙ |
Changes to generic/tclTimer.c.
1 2 3 4 5 6 7 8 9 10 11 | /* * tclTimer.c -- * * This file provides timer event management facilities for Tcl, * including the "after" command. * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * tclTimer.c -- * * This file provides timer event management facilities for Tcl, * including the "after" command. * * 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. * * RCS: @(#) $Id: tclTimer.c,v 1.6.4.2 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" /* * For each timer callback that's pending there is one record of the following |
| ︙ | ︙ | |||
932 933 934 935 936 937 938 |
Tcl_ListObjAppendElement(interp, resultListPtr, afterPtr->commandPtr);
Tcl_ListObjAppendElement(interp, resultListPtr, Tcl_NewStringObj(
(afterPtr->token == NULL) ? "idle" : "timer", -1));
Tcl_SetObjResult(interp, resultListPtr);
break;
}
default: {
| | | 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 |
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;
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ |
Changes to generic/tclTrace.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* * 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. * * RCS: @(#) $Id: tclTrace.c,v 1.2.2.5 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" /* * Structure used to hold information about variable traces: */ |
| ︙ | ︙ | |||
1806 1807 1808 1809 1810 1811 1812 |
/* Append trace operation */
if (flags & TCL_TRACE_EXEC_DIRECT) {
Tcl_DStringAppendElement(&cmd, "leave");
} else {
Tcl_DStringAppendElement(&cmd, "leavestep");
}
} else {
| | | 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 |
/* 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. Save the interp's result used for
* the command, including the value of iPtr->returnOpts which
* may be modified when Tcl_Eval is invoked. We discard any
* object result the command returns.
|
| ︙ | ︙ | |||
2981 2982 2983 2984 2985 2986 2987 |
"trace", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
if (varPtr == NULL) {
return TCL_ERROR;
}
/*
* Check for a nonsense flag combination. Note that this is a
| | | | 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 |
"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 ((flags&TCL_TRACE_RESULT_DYNAMIC) && (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 |
|
| ︙ | ︙ |
Changes to generic/tclVar.c.
| ︙ | ︙ | |||
11 12 13 14 15 16 17 | * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 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. * | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 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. * * RCS: @(#) $Id: tclVar.c,v 1.73.2.3 2004/02/07 05:48:01 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" /* * The strings below are used to indicate what went wrong when a |
| ︙ | ︙ | |||
599 600 601 602 603 604 605 606 | /* * 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 */ | > > > > | | 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 | /* * 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 /* *---------------------------------------------------------------------- * * TclLookupSimpleVar -- * * This procedure is used by to locate a simple variable (i.e., not |
| ︙ | ︙ | |||
3337 3338 3339 3340 3341 3342 3343 |
}
if (otherPtr == NULL) {
return TCL_ERROR;
}
if (index >= 0) {
if (!varFramePtr->isProcCallFrame) {
| | | 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 |
}
if (otherPtr == NULL) {
return TCL_ERROR;
}
if (index >= 0) {
if (!varFramePtr->isProcCallFrame) {
Tcl_Panic("ObjMakeUpvar called with an index outside from a proc.\n");
}
varPtr = &(varFramePtr->compiledLocals[index]);
} 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
|
| ︙ | ︙ | |||
4678 4679 4680 4681 4682 4683 4684 |
int len1, len2, totalLen;
if (arrayPtr == NULL) {
/*
* This is a parsed scalar name: what is it
* doing here?
*/
| | | 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 |
int len1, len2, totalLen;
if (arrayPtr == NULL) {
/*
* This is a parsed scalar name: what is it
* doing here?
*/
Tcl_Panic("ERROR: scalar parsedVarName without a string rep.\n");
}
part1 = Tcl_GetStringFromObj(arrayPtr, &len1);
len2 = strlen(part2);
totalLen = len1 + len2 + 2;
p = ckalloc((unsigned int) totalLen + 1);
objPtr->bytes = p;
|
| ︙ | ︙ |
Changes to library/auto.tcl.
1 2 3 4 5 | # auto.tcl -- # # utility procs formerly in init.tcl dealing with auto execution # of commands and can be auto loaded themselves. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 | # auto.tcl -- # # utility procs formerly in init.tcl dealing with auto execution # of commands and can be auto loaded themselves. # # RCS: @(#) $Id: auto.tcl,v 1.13.2.1 2004/02/07 05:48:01 dgp Exp $ # # Copyright (c) 1991-1993 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. # |
| ︙ | ︙ | |||
174 175 176 177 178 179 180 |
append index "# Tcl autoload index file, version 2.0\n"
append index "# This file is generated by the \"auto_mkindex\" command\n"
append index "# and sourced to set up indexing information for one or\n"
append index "# more commands. Typically each line is a command that\n"
append index "# sets an element in the auto_index array, where the\n"
append index "# element name is the name of a command and the value is\n"
append index "# a script that loads the command.\n\n"
| | | | 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
append index "# Tcl autoload index file, version 2.0\n"
append index "# This file is generated by the \"auto_mkindex\" command\n"
append index "# and sourced to set up indexing information for one or\n"
append index "# more commands. Typically each line is a command that\n"
append index "# sets an element in the auto_index array, where the\n"
append index "# element name is the name of a command and the value is\n"
append index "# a script that loads the command.\n\n"
if {[llength $args] == 0} {
set args *.tcl
}
auto_mkindex_parser::init
foreach file [glob {expand}$args] {
if {[catch {auto_mkindex_parser::mkindex $file} msg] == 0} {
append index $msg
} else {
set code $errorCode
set info $errorInfo
cd $oldDir
error $msg $info $code
|
| ︙ | ︙ | |||
212 213 214 215 216 217 218 |
append index "# Tcl autoload index file, version 2.0\n"
append index "# This file is generated by the \"auto_mkindex\" command\n"
append index "# and sourced to set up indexing information for one or\n"
append index "# more commands. Typically each line is a command that\n"
append index "# sets an element in the auto_index array, where the\n"
append index "# element name is the name of a command and the value is\n"
append index "# a script that loads the command.\n\n"
| | | | 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
append index "# Tcl autoload index file, version 2.0\n"
append index "# This file is generated by the \"auto_mkindex\" command\n"
append index "# and sourced to set up indexing information for one or\n"
append index "# more commands. Typically each line is a command that\n"
append index "# sets an element in the auto_index array, where the\n"
append index "# element name is the name of a command and the value is\n"
append index "# a script that loads the command.\n\n"
if {[llength $args] == 0} {
set args *.tcl
}
foreach file [glob {expand}$args] {
set f ""
set error [catch {
set f [open $file]
while {[gets $f line] >= 0} {
if {[regexp {^proc[ ]+([^ ]*)} $line match procName]} {
set procName [lindex [auto_qualify $procName "::"] 0]
append index "set [list auto_index($procName)]"
|
| ︙ | ︙ |
Changes to library/dde/pkgIndex.tcl.
1 2 |
if {![package vsatisfies [package provide Tcl] 8]} {return}
if {[info exists ::tcl_platform(debug)]} {
| > | | | 1 2 3 4 5 6 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.3 [list load [file join $dir tcldde13g.dll] dde]
} else {
package ifneeded dde 1.3 [list load [file join $dir tcldde13.dll] dde]
}
|
Changes to library/init.tcl.
1 2 3 4 5 | # init.tcl -- # # Default system startup file for Tcl-based applications. Defines # "unknown" procedure and auto-load facilities. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 | # init.tcl -- # # Default system startup file for Tcl-based applications. Defines # "unknown" procedure and auto-load facilities. # # RCS: @(#) $Id: init.tcl,v 1.56.2.2 2004/02/07 05:48:01 dgp Exp $ # # Copyright (c) 1991-1993 The Regents of the University of California. # Copyright (c) 1994-1996 Sun Microsystems, Inc. # Copyright (c) 1998-1999 Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
| ︙ | ︙ | |||
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 |
# Arguments:
# action - "renaming" or "copying"
# src - source directory
# dest - destination directory
proc tcl::CopyDirectory {action src dest} {
set nsrc [file normalize $src]
set ndest [file normalize $dest]
if {[string equal $action "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} {
return -code error "error $action \"$src\" to\
\"$dest\": trying to rename a volume or move a directory\
into itself"
}
}
if {[file exists $dest]} {
if {$nsrc == $ndest} {
return -code error "error $action \"$src\" to\
\"$dest\": trying to rename a volume or move a directory\
into itself"
}
if {[string equal $action "copying"]} {
| > > > > > > > | | | 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 |
# Arguments:
# action - "renaming" or "copying"
# src - source directory
# dest - destination directory
proc tcl::CopyDirectory {action src dest} {
set nsrc [file normalize $src]
set ndest [file normalize $dest]
if {[string equal $action "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} {
return -code error "error $action \"$src\" to\
\"$dest\": trying to rename a volume or move a directory\
into itself"
}
}
if {[file exists $dest]} {
if {$nsrc == $ndest} {
return -code error "error $action \"$src\" to\
\"$dest\": trying to rename a volume or move a directory\
into itself"
}
if {[string equal $action "copying"]} {
# 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 [list lappend existing] \
|
| ︙ | ︙ | |||
717 718 719 720 721 722 723 |
# We will also be more generous to the file system and not
# assume the hidden and non-hidden lists are non-overlapping.
#
# On Unix 'hidden' files begin with '.'. On other platforms
# or filesystems hidden files may have other interpretations.
set filelist [concat [glob -nocomplain -directory $src *] \
[glob -nocomplain -directory $src -types hidden *]]
| | | | 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 |
# We will also be more generous to the file system and not
# assume the hidden and non-hidden lists are non-overlapping.
#
# On Unix 'hidden' files begin with '.'. On other platforms
# 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] != ".") && ([file tail $s] != "..")} {
file copy -force $s [file join $dest [file tail $s]]
}
}
return
}
|
Changes to library/msgcat/msgcat.tcl.
1 2 3 4 5 6 7 8 9 10 11 12 | # msgcat.tcl -- # # This file defines various procedures which implement a # message catalog facility for Tcl programs. It should be # loaded with the command "package require msgcat". # # Copyright (c) 1998-2000 by Ajuba Solutions. # Copyright (c) 1998 by Mark Harrison. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # | | | | 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 |
# msgcat.tcl --
#
# This file defines various procedures which implement a
# message catalog facility for Tcl programs. It should be
# loaded with the command "package require msgcat".
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
# Copyright (c) 1998 by Mark Harrison.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: msgcat.tcl,v 1.17.4.2 2004/02/07 05:48:02 dgp Exp $
package require Tcl 8.2
# When the version number changes, be sure to update the pkgIndex.tcl file,
# and the installation directory in the Makefiles.
package provide msgcat 1.4
namespace eval msgcat {
namespace export mc mcload mclocale mcmax mcmset mcpreferences mcset \
mcunknown
# Records the current locale as passed to mclocale
variable Locale ""
|
| ︙ | ︙ | |||
230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
set Locale [string tolower [lindex $args 0]]
set Loclist {}
set word ""
foreach part [split $Locale _] {
set word [string trimleft "${word}_${part}" _]
set Loclist [linsert $Loclist 0 $word]
}
}
return $Locale
}
# msgcat::mcpreferences --
#
# Fetch the list of locales used to look up strings, ordered from
| > | 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
set Locale [string tolower [lindex $args 0]]
set Loclist {}
set word ""
foreach part [split $Locale _] {
set word [string trimleft "${word}_${part}" _]
set Loclist [linsert $Loclist 0 $word]
}
lappend Loclist {}
}
return $Locale
}
# msgcat::mcpreferences --
#
# Fetch the list of locales used to look up strings, ordered from
|
| ︙ | ︙ | |||
264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
#
# Results:
# Returns the number of message catalogs that were loaded.
proc msgcat::mcload {langdir} {
set x 0
foreach p [mcpreferences] {
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
| > > > | 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
#
# Results:
# Returns the number of message catalogs that were loaded.
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
|
| ︙ | ︙ |
Changes to library/msgcat/pkgIndex.tcl.
1 |
if {![package vsatisfies [package provide Tcl] 8.2]} {return}
| | | 1 2 |
if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded msgcat 1.4 [list source [file join $dir msgcat.tcl]]
|
Changes to library/package.tcl.
1 2 3 4 5 | # package.tcl -- # # utility procs formerly in init.tcl which can be loaded on demand # for package management. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 | # package.tcl -- # # utility procs formerly in init.tcl which can be loaded on demand # for package management. # # RCS: @(#) $Id: package.tcl,v 1.23.4.3 2004/02/07 05:48:02 dgp Exp $ # # Copyright (c) 1991-1993 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. # |
| ︙ | ︙ | |||
136 137 138 139 140 141 142 |
if {[llength $patternList] == 0} {
set patternList [list "*.tcl" "*[info sharedlibextension]"]
}
set oldDir [pwd]
cd $dir
| | | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
if {[llength $patternList] == 0} {
set patternList [list "*.tcl" "*[info sharedlibextension]"]
}
set oldDir [pwd]
cd $dir
if {[catch {glob {expand}$patternList} fileList]} {
global errorCode errorInfo
cd $oldDir
return -code error -errorcode $errorCode -errorinfo $errorInfo $fileList
}
foreach file $fileList {
# For each file, figure out what commands and packages it provides.
# To do this, create a child interpreter, load the file into the
|
| ︙ | ︙ | |||
202 203 204 205 206 207 208 |
# Stub out the package command so packages can
# require other packages.
rename package __package_orig
proc package {what args} {
switch -- $what {
require { return ; # ignore transitive requires }
| | | 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
# Stub out the package command so packages can
# require other packages.
rename package __package_orig
proc package {what args} {
switch -- $what {
require { return ; # ignore transitive requires }
default { __package_orig $what {expand}$args }
}
}
proc tclPkgUnknown args {}
package unknown tclPkgUnknown
# Stub out the unknown command so package can call
# into each other during their initialilzation.
|
| ︙ | ︙ | |||
257 258 259 260 261 262 263 |
# we need to track command defined by each package even in
# the -direct case, because they are needed internally by
# the "partial pkgIndex.tcl" step above.
proc ::tcl::GetAllNamespaces {{root ::}} {
set list $root
foreach ns [namespace children $root] {
| | | 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
# we need to track command defined by each package even in
# the -direct case, because they are needed internally by
# the "partial pkgIndex.tcl" step above.
proc ::tcl::GetAllNamespaces {{root ::}} {
set list $root
foreach ns [namespace children $root] {
lappend list {expand}[::tcl::GetAllNamespaces $ns]
}
return $list
}
# init the list of existing namespaces, packages, commands
foreach ::tcl::x [::tcl::GetAllNamespaces] {
|
| ︙ | ︙ |
Changes to library/reg/pkgIndex.tcl.
1 2 |
if {![package vsatisfies [package provide Tcl] 8]} {return}
if {[info exists ::tcl_platform(debug)]} {
| > | | | 1 2 3 4 5 6 7 8 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.3 \
[list load [file join $dir tclreg11g.dll] registry]
} else {
package ifneeded registry 1.1.3 \
[list load [file join $dir tclreg11.dll] registry]
}
|
Changes to library/safe.tcl.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | # See the safe.n man page for details. # # 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. # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # See the safe.n man page for details. # # 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. # # RCS: @(#) $Id: safe.tcl,v 1.10.2.2 2004/02/07 05:48:02 dgp Exp $ # # The implementation is based on namespaces. These naming conventions # are followed: # Private procs starts with uppercase. # Public procs are exported and starts with lowercase # |
| ︙ | ︙ | |||
521 522 523 524 525 526 527 |
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
| | | 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 |
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 {{expand}$hook $slave} err]} {
Log $slave "Delete hook error ($err)"
}
}
}
# Discard the global array of state associated with the slave, and
# delete the interpreter.
|
| ︙ | ︙ | |||
632 633 634 635 636 637 638 |
}
# Run some code at the namespace toplevel
proc Toplevel {args} {
namespace eval [namespace current] $args
}
# set/get values
proc Set {args} {
| | | | | 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 |
}
# Run some code at the namespace toplevel
proc Toplevel {args} {
namespace eval [namespace current] $args
}
# set/get values
proc Set {args} {
Toplevel set {expand}$args
}
# lappend on toplevel vars
proc Lappend {args} {
Toplevel lappend {expand}$args
}
# unset a var/token (currently just an global level eval)
proc Unset {args} {
Toplevel unset {expand}$args
}
# test existance
proc Exists {varname} {
Toplevel info exists $varname
}
# short cut for access path getting
proc GetAccessPath {slave} {
|
| ︙ | ︙ | |||
687 688 689 690 691 692 693 |
# 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]} {
| | | 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 |
# 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]} {
{expand}$Log "$type for slave $slave : $msg"
}
}
# file name control (limit access to files/ressources that should be
# a valid tcl source file)
proc CheckFileName {slave file} {
|
| ︙ | ︙ | |||
852 853 854 855 856 857 858 |
# This procedure enables access from a safe interpreter to only a subset of
# the subcommands of a command:
proc Subset {slave command okpat args} {
set subcommand [lindex $args 0]
if {[regexp $okpat $subcommand]} {
| | | 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 |
# This procedure enables access from a safe interpreter to only a subset of
# the subcommands of a command:
proc Subset {slave command okpat args} {
set subcommand [lindex $args 0]
if {[regexp $okpat $subcommand]} {
return [$command $subcommand {expand}[lrange $args 1 end]]
}
set msg "not allowed to invoke subcommand $subcommand of $command"
Log $slave $msg
error $msg
}
# This procedure installs an alias in a slave that invokes "safesubset"
|
| ︙ | ︙ | |||
887 888 889 890 891 892 893 |
set argc [llength $args]
set okpat "^(name.*|convert.*)\$"
set subcommand [lindex $args 0]
if {[regexp $okpat $subcommand]} {
| | | | 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 |
set argc [llength $args]
set okpat "^(name.*|convert.*)\$"
set subcommand [lindex $args 0]
if {[regexp $okpat $subcommand]} {
return [::interp invokehidden $slave encoding $subcommand \
{expand}[lrange $args 1 end]]
}
if {[string match $subcommand system]} {
if {$argc == 1} {
# passed all the tests , lets source it:
if {[catch {::interp invokehidden \
$slave encoding system} msg]} {
|
| ︙ | ︙ |
Changes to library/tcltest/pkgIndex.tcl.
1 2 3 4 5 6 7 8 9 10 11 |
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex -direct" 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.3]} {return}
| | | 1 2 3 4 5 6 7 8 9 10 11 12 |
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex -direct" 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.3]} {return}
package ifneeded tcltest 2.2.5 [list source [file join $dir tcltest.tcl]]
|
Changes to library/tcltest/tcltest.tcl.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 | # # Copyright (c) 1994-1997 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # Copyright (c) 2000 by Ajuba Solutions # Contributions from Don Porter, NIST, 2002. (not subject to US copyright) # All rights reserved. # | | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2000 by Ajuba Solutions
# Contributions from Don Porter, NIST, 2002. (not subject to US copyright)
# All rights reserved.
#
# RCS: @(#) $Id: tcltest.tcl,v 1.82.2.2 2004/02/07 05:48:02 dgp Exp $
package require Tcl 8.3 ;# uses [glob -directory]
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.5
# Compatibility support for dumb variables defined in tcltest 1
# Do not use these. Call [package provide Tcl] and [info patchlevel]
# yourself. You don't need tcltest to wrap it for you.
variable version [package provide Tcl]
variable patchLevel [info patchlevel]
|
| ︙ | ︙ | |||
1415 1416 1417 1418 1419 1420 1421 |
exit 1
}
if {[llength $flagArray] == 0} {
RemoveAutoConfigureTraces
} else {
set args $flagArray
| | | 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 |
exit 1
}
if {[llength $flagArray] == 0} {
RemoveAutoConfigureTraces
} else {
set args $flagArray
while {[llength $args]>1 && [catch {eval configure $args} msg]} {
# Something went wrong parsing $args for tcltest options
# Check whether the problem is "unknown option"
if {[regexp {^unknown option (\S+):} $msg -> option]} {
# Could be this is an option the Hook knows about
set moreOptions [processCmdLineArgsAddFlagsHook]
if {[lsearch -exact $moreOptions $option] == -1} {
|
| ︙ | ︙ | |||
1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 |
# To recover, find that unknown option and remove up to it.
# then retry
while {![string equal [lindex $args 0] $option]} {
set args [lrange $args 2 end]
}
set args [lrange $args 2 end]
}
}
# Call the hook
array set flag $flagArray
processCmdLineArgsHook [array get flag]
return
| > > > > > | 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 |
# To recover, find that unknown option and remove up to it.
# then retry
while {![string equal [lindex $args 0] $option]} {
set args [lrange $args 2 end]
}
set args [lrange $args 2 end]
}
if {[llength $args] == 1} {
puts [errorChannel] \
"missing value for option [lindex $args 0]"
exit 1
}
}
# Call the hook
array set flag $flagArray
processCmdLineArgsHook [array get flag]
return
|
| ︙ | ︙ | |||
2470 2471 2472 2473 2474 2475 2476 |
}
if {[file exists [file join [workingDirectory] core]]} {
if {[preserveCore] > 1} {
puts "rename core file (> 1)"
puts [outputChannel] "produced core file! \
Moving file to: \
| | | | 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 |
}
if {[file exists [file join [workingDirectory] core]]} {
if {[preserveCore] > 1} {
puts "rename core file (> 1)"
puts [outputChannel] "produced core file! \
Moving file to: \
[file join [temporaryDirectory] core-$testFileName]"
catch {file rename -force \
[file join [workingDirectory] core] \
[file join [temporaryDirectory] core-$testFileName]
} msg
if {[string length $msg] > 0} {
PrintError "Problem renaming file: $msg"
}
} else {
# Print a message if there is a core file and (1) there
# previously wasn't one or (2) the new one is different
|
| ︙ | ︙ |
Changes to mac/tclMacChan.c.
1 2 3 4 5 6 7 8 9 10 11 | /* * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * 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. * * RCS: @(#) $Id: tclMacChan.c,v 1.21.4.1 2004/02/07 05:48:02 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" #include "tclMacInt.h" #include <Aliases.h> #include <Errors.h> |
| ︙ | ︙ | |||
430 431 432 433 434 435 436 |
if (fd == 0) {
tsdPtr->stdinChannel = NULL;
} else if (fd == 1) {
tsdPtr->stdoutChannel = NULL;
} else if (fd == 2) {
tsdPtr->stderrChannel = NULL;
} else {
| | | 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 |
if (fd == 0) {
tsdPtr->stdinChannel = NULL;
} else if (fd == 1) {
tsdPtr->stdoutChannel = NULL;
} else if (fd == 2) {
tsdPtr->stderrChannel = NULL;
} else {
Tcl_Panic("recieved invalid std file");
}
if (close(fd) < 0) {
errorCode = errno;
}
}
return errorCode;
|
| ︙ | ︙ | |||
692 693 694 695 696 697 698 | break; case TCL_STDERR: fd = 2; channelPermissions = TCL_WRITABLE; bufMode = "none"; break; default: | | | 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 |
break;
case TCL_STDERR:
fd = 2;
channelPermissions = TCL_WRITABLE;
bufMode = "none";
break;
default:
Tcl_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);
|
| ︙ | ︙ | |||
983 984 985 986 987 988 989 |
int errorCode = 0;
OSErr err;
err = FSClose(fileState->fileRef);
FlushVol(NULL, fileState->volumeRef);
if (err != noErr) {
errorCode = errno = TclMacOSErrorToPosixError(err);
| | | 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 |
int errorCode = 0;
OSErr err;
err = FSClose(fileState->fileRef);
FlushVol(NULL, fileState->volumeRef);
if (err != noErr) {
errorCode = errno = TclMacOSErrorToPosixError(err);
Tcl_Panic("error during file close");
}
ckfree((char *) fileState);
Tcl_SetErrno(errorCode);
return errorCode;
}
|
| ︙ | ︙ | |||
1254 1255 1256 1257 1258 1259 1260 |
/*
* 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.
*/
| | | | | 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 |
/*
* 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) {
Tcl_Panic("file info ptr not on thread channel list");
}
}
/*
*----------------------------------------------------------------------
*
* TclpSpliceFileChannel --
*
|
| ︙ | ︙ |
Changes to mac/tclMacFile.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* * 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. * * RCS: @(#) $Id: tclMacFile.c,v 1.27.4.2 2004/02/07 05:48:02 dgp Exp $ */ /* * 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. */ |
| ︙ | ︙ | |||
151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
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) {
| > > > > > | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
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;
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 (types != NULL) {
|
| ︙ | ︙ | |||
578 579 580 581 582 583 584 585 586 |
}
return -1;
}
return 0;
}
/*
*----------------------------------------------------------------------
| > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > < < < < < < < < < < < < < < < | 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 |
}
return -1;
}
return 0;
}
/*
*---------------------------------------------------------------------------
*
* TclpGetNativeCwd --
*
* This function replaces the library version of getcwd().
*
* Results:
* 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.
*
*----------------------------------------------------------------------
*/
ClientData
TclpGetNativeCwd(clientData)
ClientData clientData;
{
FSSpec theSpec;
int length;
Handle pathHandle = NULL;
OSErr err;
err = FSpGetDefaultDir(&theSpec);
if (err != noErr) {
errno = TclMacOSErrorToPosixError(err);
return NULL;
}
err = FSpPathFromLocation(&theSpec, &length, &pathHandle);
if (err != noErr) {
errno = TclMacOSErrorToPosixError(err);
return NULL;
}
if ((clientData != NULL)
&& strcmp((CONST char*)(*pathHandle), (CONST char*)clientData) == 0) {
/* No change to pwd */
DisposeHandle(pathHandle);
return clientData;
} else {
char *newCd;
HLock(pathHandle);
newCd = (char *) ckalloc((unsigned)
(strlen((CONST char*)(*pathHandle)) + 1));
strcpy(newCd, (CONST char*)(*pathHandle));
HUnlock(pathHandle);
DisposeHandle(pathHandle);
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.
*
*----------------------------------------------------------------------
*/
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;
|
| ︙ | ︙ | |||
1238 1239 1240 1241 1242 1243 1244 | * * Side effects: * None. * *--------------------------------------------------------------------------- */ Tcl_Obj* | | | | 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 |
*
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
Tcl_Obj*
TclpFilesystemPathType(pathPtr)
Tcl_Obj* pathPtr;
{
/* All native paths are of the same type */
return NULL;
}
/*
*---------------------------------------------------------------------------
|
| ︙ | ︙ |
Changes to mac/tclMacOSA.c.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | * * 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. * | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | * * 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. * * RCS: @(#) $Id: tclMacOSA.c,v 1.10.4.1 2004/02/07 05:48:02 dgp Exp $ */ #define MAC_TCL #include <Aliases.h> #include <string.h> #include <AppleEvents.h> |
| ︙ | ︙ | |||
218 219 220 221 222 223 224 |
* 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) {
| | | 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
* 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) {
Tcl_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) {
|
| ︙ | ︙ | |||
296 297 298 299 300 301 302 |
/*
* Create the Component Assoc Data & put it in the interpreter.
*/
ComponentTable = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
if (ComponentTable == NULL) {
| | | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
/*
* Create the Component Assoc Data & put it in the interpreter.
*/
ComponentTable = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
if (ComponentTable == NULL) {
Tcl_Panic("Memory Error Allocating Hash Table");
}
Tcl_SetAssocData(interp, "OSAScript_CompTable", NULL, ComponentTable);
Tcl_InitHashTable(ComponentTable, TCL_STRING_KEYS);
/*
|
| ︙ | ︙ | |||
1856 1857 1858 1859 1860 1861 1862 |
CloseComponent(theComponent->theComponent);
ComponentTable = (Tcl_HashTable *)
Tcl_GetAssocData(theComponent->theInterp,
"OSAScript_CompTable", (Tcl_InterpDeleteProc **) NULL);
if (ComponentTable == NULL) {
| | | 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 |
CloseComponent(theComponent->theComponent);
ComponentTable = (Tcl_HashTable *)
Tcl_GetAssocData(theComponent->theInterp,
"OSAScript_CompTable", (Tcl_InterpDeleteProc **) NULL);
if (ComponentTable == NULL) {
Tcl_Panic("Error, could not get the Component Table from the Associated data.");
}
hashEntry = Tcl_FindHashEntry(ComponentTable, theComponent->theName);
if (hashEntry != NULL) {
Tcl_DeleteHashEntry(hashEntry);
}
|
| ︙ | ︙ |
Changes to mac/tclMacResource.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* * 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. * * RCS: @(#) $Id: tclMacResource.c,v 1.15.2.3 2004/02/07 05:48:02 dgp Exp $ */ #include <Errors.h> #include <FSpCompat.h> #include <Processes.h> #include <Resources.h> #include <Sound.h> |
| ︙ | ︙ | |||
474 475 476 477 478 479 480 |
if (theName[0] != 0) {
objPtr = Tcl_NewStringObj((char *) theName + 1,
theName[0]);
} else {
objPtr = Tcl_NewIntObj(id);
}
| > > > > > > | > | 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 |
if (theName[0] != 0) {
objPtr = Tcl_NewStringObj((char *) theName + 1,
theName[0]);
} else {
objPtr = Tcl_NewIntObj(id);
}
/*
* 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.
*/
if (*resource == NULL) {
ReleaseResource(resource);
}
result = Tcl_ListObjAppendElement(interp, resultPtr,
objPtr);
if (result != TCL_OK) {
Tcl_DecrRefCount(objPtr);
break;
}
}
|
| ︙ | ︙ | |||
536 537 538 539 540 541 542 | macPermision = fsRdPerm; break; case O_WRONLY: case O_RDWR: macPermision = fsRdWrShPerm; break; default: | | | 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 |
macPermision = fsRdPerm;
break;
case O_WRONLY:
case O_RDWR:
macPermision = fsRdWrShPerm;
break;
default:
Tcl_Panic("Tcl_ResourceObjCmd: invalid mode value");
break;
}
} else {
macPermision = fsRdPerm;
}
/*
|
| ︙ | ︙ | |||
780 781 782 783 784 785 786 |
* resource of this type & id, or the id was not specified.
*/
resource = NewHandle(length);
if (resource == NULL) {
resource = NewHandleSys(length);
if (resource == NULL) {
| | | 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 |
* resource of this type & id, or the id was not specified.
*/
resource = NewHandle(length);
if (resource == NULL) {
resource = NewHandleSys(length);
if (resource == NULL) {
Tcl_Panic("could not allocate memory to write resource");
}
}
HLock(resource);
memcpy(*resource, stringPtr, length);
HUnlock(resource);
AddResource(resource, rezType, (short) rsrcId,
(StringPtr) resourceId);
|
| ︙ | ︙ | |||
851 852 853 854 855 856 857 |
" to overwrite it", (char *) NULL);
goto writeDone;
}
}
SetHandleSize(resource, length);
if ( MemError() != noErr ) {
| | | 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 |
" to overwrite it", (char *) NULL);
goto writeDone;
}
}
SetHandleSize(resource, length);
if ( MemError() != noErr ) {
Tcl_Panic("could not allocate memory to write resource");
}
HLock(resource);
memcpy(*resource, stringPtr, length);
HUnlock(resource);
ChangedResource(resource);
|
| ︙ | ︙ | |||
905 906 907 908 909 910 911 |
if (limitSearch) {
UseResFile(saveRef);
}
return result;
default:
| | | 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 |
if (limitSearch) {
UseResFile(saveRef);
}
return result;
default:
Tcl_Panic("Tcl_GetIndexFromObj returned unrecognized option");
return TCL_ERROR; /* Should never be reached. */
}
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
2031 2032 2033 2034 2035 2036 2037 |
}
Tcl_SetHashValue(resourceHashPtr, resourceId);
newId++;
nameHashPtr = Tcl_CreateHashEntry(&nameTable, resourceId, &new);
if (!new) {
| | | 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 |
}
Tcl_SetHashValue(resourceHashPtr, resourceId);
newId++;
nameHashPtr = Tcl_CreateHashEntry(&nameTable, resourceId, &new);
if (!new) {
Tcl_Panic("resource id has repeated itself");
}
resourceRef = (OpenResourceFork *) ckalloc(sizeof(OpenResourceFork));
resourceRef->fileRef = fileRef;
resourceRef->flags = flags;
Tcl_SetHashValue(nameHashPtr, (ClientData) resourceRef);
|
| ︙ | ︙ | |||
2134 2135 2136 2137 2138 2139 2140 |
}
if (match) {
index = i;
break;
}
}
if (!match) {
| | | | 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 |
}
if (match) {
index = i;
break;
}
}
if (!match) {
Tcl_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) {
Tcl_Panic("Resource & Name tables are out of synch in resource command.");
}
ckfree(Tcl_GetHashValue(resourceHashPtr));
Tcl_DeleteHashEntry(resourceHashPtr);
return fileRef;
}
|
| ︙ | ︙ |
Changes to mac/tclMacSock.c.
1 2 3 4 5 6 7 8 9 10 | /* * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /* * 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. * * RCS: @(#) $Id: tclMacSock.c,v 1.15.2.1 2004/02/07 05:48:02 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" #include "tclMacInt.h" #include <AddressXlation.h> #include <Aliases.h> |
| ︙ | ︙ | |||
733 734 735 736 737 738 739 |
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;
| | | | 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 |
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;
/* Tcl_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) {
Tcl_Panic("error releasing server socket");
}
/*
* Free the buffer space used by the socket and the
* actual socket state data structure.
*/
afterRelease:
|
| ︙ | ︙ | |||
2835 2836 2837 2838 2839 2840 2841 |
/*
* 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)
| | | 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 |
/*
* 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)
Tcl_Panic("file info ptr not on thread channel list");
return;
}
/*
*----------------------------------------------------------------------
*
* TclpSpliceSockChannel --
|
| ︙ | ︙ |
Changes to mac/tclMacThrd.c.
| ︙ | ︙ | |||
706 707 708 709 710 711 712 |
* has passed us a key without getting the value from
* TclpInitDataKey.
*/
if ((int) keyVal <= 0) {
return NULL;
} else if ((int) keyVal > keyCounter) {
| | | 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 |
* has passed us a key without getting the value from
* TclpInitDataKey.
*/
if ((int) keyVal <= 0) {
return NULL;
} else if ((int) keyVal > keyCounter) {
Tcl_Panic("illegal data key value");
}
GetCurrentThread(&curThread);
for (dataPtr = tclMacDataKeyArray[(int) keyVal - 1]; dataPtr != NULL;
dataPtr = dataPtr->next) {
if (dataPtr->threadID == curThread) {
|
| ︙ | ︙ | |||
751 752 753 754 755 756 757 |
ThreadID curThread;
TclMacThrdData *dataPtr, *prevPtr;
if ((int) keyVal <= 0) {
return NULL;
} else if ((int) keyVal > keyCounter) {
| | | 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 |
ThreadID curThread;
TclMacThrdData *dataPtr, *prevPtr;
if ((int) keyVal <= 0) {
return NULL;
} else if ((int) keyVal > keyCounter) {
Tcl_Panic("illegal data key value");
}
GetCurrentThread(&curThread);
for (dataPtr = tclMacDataKeyArray[(int) keyVal - 1], prevPtr = NULL;
dataPtr != NULL;
prevPtr = dataPtr, dataPtr = dataPtr->next) {
|
| ︙ | ︙ |
Changes to macosx/Makefile.
1 2 3 4 5 | ######################################################################################################## # # Makefile to build Tcl on Mac OS X packaged as a Framework # uses standard unix build system in tcl/unix # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 | ######################################################################################################## # # Makefile to build Tcl on Mac OS X packaged as a Framework # uses standard unix build system in tcl/unix # # RCS: @(#) $Id: Makefile,v 1.5.4.3 2004/02/07 05:48:02 dgp Exp $ # ######################################################################################################## #------------------------------------------------------------------------------------------------------- # customizable settings DESTDIR ?= |
| ︙ | ︙ | |||
31 32 33 34 35 36 37 | TCL_PACKAGE_PATH ?= "~/Library/Tcl /Library/Tcl /Network/Library/Tcl /System/Library/Tcl \ ~/Library/Frameworks /Library/Frameworks /Network/Library/Frameworks \ /System/Library/Frameworks" #------------------------------------------------------------------------------------------------------- # meta targets | | | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
TCL_PACKAGE_PATH ?= "~/Library/Tcl /Library/Tcl /Network/Library/Tcl /System/Library/Tcl \
~/Library/Frameworks /Library/Frameworks /Network/Library/Frameworks \
/System/Library/Frameworks"
#-------------------------------------------------------------------------------------------------------
# meta targets
meta := all install embedded install-embedded clean distclean test
styles := develop deploy
all := ${styles}
all : ${all}
install := ${styles:%=install-%}
|
| ︙ | ︙ | |||
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
clean := ${styles:%=clean-%}
clean : ${clean}
clean-%: action := clean-
distclean := ${styles:%=distclean-%}
distclean : ${distclean}
distclean-%: action := distclean-
targets := $(foreach v,${meta},${$v})
#-------------------------------------------------------------------------------------------------------
# build styles
develop_make_args := BUILD_STYLE=Development CONFIGURE_ARGS=--enable-symbols
deploy_make_args := BUILD_STYLE=Deployment \
MAKE_ARGS=INSTALL_PROGRAM="'$$\$${INSTALL} $$\$${INSTALL_STRIP_PROGRAM}'" \
| > > > > | > | 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 |
clean := ${styles:%=clean-%}
clean : ${clean}
clean-%: action := clean-
distclean := ${styles:%=distclean-%}
distclean : ${distclean}
distclean-%: action := distclean-
test := ${styles:%=test-%}
test : ${test}
test-%: action := test-
targets := $(foreach v,${meta},${$v})
#-------------------------------------------------------------------------------------------------------
# build styles
develop_make_args := BUILD_STYLE=Development CONFIGURE_ARGS=--enable-symbols
deploy_make_args := BUILD_STYLE=Deployment \
MAKE_ARGS=INSTALL_PROGRAM="'$$\$${INSTALL} $$\$${INSTALL_STRIP_PROGRAM}'" \
MAKE_ARGS+=INSTALL_LIBRARY="'$$\$${INSTALL} $$\$${INSTALL_STRIP_LIBRARY}'" \
MAKE_ARGS+=MEM_DEBUG_FLAGS="-DNDEBUG"
embedded_make_args := EMBEDDED_BUILD=1
install_make_args := INSTALL_BUILD=1
$(targets):
${MAKE} ${action}${PROJECT} \
$(foreach s,${styles} embedded install,$(if $(findstring $s,$@),${${s}_make_args}))
|
| ︙ | ︙ | |||
139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
clean-${PROJECT}:
${MAKE} -C ${OBJ_DIR} clean ${EXTRA_MAKE_ARGS}
distclean-${PROJECT}:
${MAKE} -C ${OBJ_DIR} distclean ${EXTRA_MAKE_ARGS}
rm -rf ${OBJ_DIR} ${PRODUCT_NAME}.framework tclsh${PRODUCT_VERSION} tcltest
install-${PROJECT}: build-${PROJECT}
# install to ${INSTALL_ROOT} with optional stripping
${MAKE} -C ${OBJ_DIR} install-binaries install-libraries \
SCRIPT_INSTALL_DIR=${INSTALL_ROOT}${SCRIPTDIR} ${MAKE_ARGS_V} ${MAKE_ARGS} ${EXTRA_MAKE_ARGS}
mkdir -p ${INSTALL_ROOT}${PRIVATEINCLUDEDIR} && \
cd ${GENERIC_DIR} && ${CPPROG} ${PRIVATE_HEADERS} ${INSTALL_ROOT}${PRIVATEINCLUDEDIR}
ifeq (${BUILD_STYLE},Development)
| > > > | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
clean-${PROJECT}:
${MAKE} -C ${OBJ_DIR} clean ${EXTRA_MAKE_ARGS}
distclean-${PROJECT}:
${MAKE} -C ${OBJ_DIR} distclean ${EXTRA_MAKE_ARGS}
rm -rf ${OBJ_DIR} ${PRODUCT_NAME}.framework tclsh${PRODUCT_VERSION} tcltest
test-${PROJECT}: build-${PROJECT}
${MAKE} -C ${OBJ_DIR} test ${EXTRA_MAKE_ARGS}
install-${PROJECT}: build-${PROJECT}
# install to ${INSTALL_ROOT} with optional stripping
${MAKE} -C ${OBJ_DIR} install-binaries install-libraries \
SCRIPT_INSTALL_DIR=${INSTALL_ROOT}${SCRIPTDIR} ${MAKE_ARGS_V} ${MAKE_ARGS} ${EXTRA_MAKE_ARGS}
mkdir -p ${INSTALL_ROOT}${PRIVATEINCLUDEDIR} && \
cd ${GENERIC_DIR} && ${CPPROG} ${PRIVATE_HEADERS} ${INSTALL_ROOT}${PRIVATEINCLUDEDIR}
ifeq (${BUILD_STYLE},Development)
|
| ︙ | ︙ |
Changes to tests/async.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # Commands covered: none # # This file contains a collection of tests for Tcl_AsyncCreate and related # library procedures. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 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. # | | > > > > | 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 |
# Commands covered: none
#
# This file contains a collection of tests for Tcl_AsyncCreate and related
# library procedures. Sourcing this file into Tcl runs the tests and
# generates output for errors. No output means no errors were found.
#
# Copyright (c) 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.
#
# RCS: @(#) $Id: async.test,v 1.5.26.2 2004/02/07 05:48:02 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
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
}
tcltest::testConstraint threaded [expr {
[info exists ::tcl_platform(threaded)] && $::tcl_platform(threaded)
}]
proc async1 {result code} {
global aresult acode
set aresult $result
set acode $code
return "new result"
}
|
| ︙ | ︙ | |||
141 142 143 144 145 146 147 148 |
set hm3 [testasync create mult2]
set hm4 [testasync create del2]
test async-3.1 {deleting handlers} {
set x {}
list [catch {testasync mark $hm2 "foobar" 5} msg] $msg $x
} {3 del2 {0 0 0 del1 del2}}
| > | > > > > | < | | | | | > | > > > > > > > > | > > > > > > > > > > > > > > > > | > > > > > > > > | > > > > > > > > | > > > > > > > | 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
set hm3 [testasync create mult2]
set hm4 [testasync create del2]
test async-3.1 {deleting handlers} {
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 {
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 {
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 {
threaded
} -setup {
set hm [testasync create async3]
} -body {
hang3 $hm
} -result {test pattern} -cleanup {
testasync delete $hm
}
# cleanup
testasync delete
::tcltest::cleanupTests
return
# Local Variables:
# mode: tcl
# End:
|
Changes to tests/basic.test.
| ︙ | ︙ | |||
11 12 13 14 15 16 17 | # # 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. # | | > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#
# 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.
#
# RCS: @(#) $Id: basic.test,v 1.27.2.3 2004/02/07 05:48:02 dgp Exp $
#
package require tcltest 2
namespace import -force ::tcltest::*
testConstraint testevalex [llength [info commands testevalex]]
testConstraint testcmdtoken [llength [info commands testcmdtoken]]
testConstraint testcreatecommand [llength [info commands testcreatecommand]]
testConstraint exec [llength [info commands exec]]
catch {namespace delete test_ns_basic}
catch {interp delete test_interp}
catch {rename p ""}
|
| ︙ | ︙ | |||
197 198 199 200 201 202 203 |
[cmd] \
[rename cmd ""] \
[interp expose {} cmd] \
[p]
} {42 {} {} Hello {} {} 42}
test basic-14.1 {Tcl_CreateCommand, new cmd goes into a namespace specified in its name, if any} {testcreatecommand} {
| | | | | | | | | | 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
[cmd] \
[rename cmd ""] \
[interp expose {} cmd] \
[p]
} {42 {} {} Hello {} {} 42}
test basic-14.1 {Tcl_CreateCommand, new cmd goes into a namespace specified in its name, if any} {testcreatecommand} {
catch {namespace delete {expand}[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 {namespace delete {expand}[namespace children :: test_ns_*]}
catch {rename value:at: ""}
list [testcreatecommand create2] \
[value:at:] \
[testcreatecommand delete2]
} {{} {CreatedCommandProc2 in ::} {}}
test basic-15.1 {Tcl_CreateObjCommand, new cmd goes into a namespace specified in its name, if any} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_basic {}
proc test_ns_basic::cmd {} { ;# proc requires that ns already exist
return [namespace current]
}
list [test_ns_basic::cmd] \
[namespace delete test_ns_basic]
} {::test_ns_basic {}}
test basic-16.1 {TclInvokeStringCommand} {emptyTest} {
} {}
test basic-17.1 {TclInvokeObjCommand} {emptyTest} {
} {}
test basic-18.1 {TclRenameCommand, name of existing cmd can have namespace qualifiers} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
catch {rename cmd ""}
namespace eval test_ns_basic {
proc p {} {
return "p in [namespace current]"
}
}
list [test_ns_basic::p] \
[rename test_ns_basic::p test_ns_basic::q] \
[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 {namespace delete {expand}[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 {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_basic {
proc p {} {
return "p in [namespace current]"
}
}
list [info commands test_ns_basic::*] \
[rename test_ns_basic::p ""] \
[info commands test_ns_basic::*]
} {::test_ns_basic::p {} {}}
test basic-18.4 {TclRenameCommand, bad new name} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_basic {
proc p {} {
return "p in [namespace current]"
}
}
rename test_ns_basic::p :::george::martha
} {}
test basic-18.5 {TclRenameCommand, new name must not already exist} {
namespace eval test_ns_basic {
proc q {} {
return 42
}
}
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 {namespace delete {expand}[namespace children :: test_ns_*]}
catch {rename p ""}
catch {rename q ""}
proc p {} {
return "p in [namespace current]"
}
proc q {} {
return "q in [namespace current]"
|
| ︙ | ︙ | |||
294 295 296 297 298 299 300 |
[test_ns_basic::callP]
} {{p in ::} {} {q in ::test_ns_basic}}
test basic-19.1 {Tcl_SetCommandInfo} {emptyTest} {
} {}
test basic-20.1 {Tcl_GetCommandInfo, names for commands created inside namespaces} {testcmdtoken} {
| | | | | 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
[test_ns_basic::callP]
} {{p in ::} {} {q in ::test_ns_basic}}
test basic-19.1 {Tcl_SetCommandInfo} {emptyTest} {
} {}
test basic-20.1 {Tcl_GetCommandInfo, names for commands created inside namespaces} {testcmdtoken} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
catch {rename p ""}
catch {rename q ""}
catch {unset x}
set x [namespace eval test_ns_basic::test_ns_basic2 {
# the following creates a cmd in the global namespace
testcmdtoken create p
}]
list [testcmdtoken name $x] \
[rename ::p q] \
[testcmdtoken name $x]
} {{p ::p} {} {q ::q}}
test basic-20.2 {Tcl_GetCommandInfo, names for commands created outside namespaces} {testcmdtoken} {
catch {rename q ""}
set x [testcmdtoken create test_ns_basic::test_ns_basic2::p]
list [testcmdtoken name $x] \
[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 {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_basic1 {
namespace export cmd*
proc cmd1 {} {}
proc cmd2 {} {}
}
namespace eval test_ns_basic2 {
namespace export *
|
| ︙ | ︙ | |||
369 370 371 372 373 374 375 |
}
}
list $x \
[interp eval test_interp {useSet}] \
[interp delete test_interp]
} {123 {set called with a 123} {}}
test basic-24.2 {Tcl_DeleteCommandFromToken, deleting commands changes command epoch} {
| | | | 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 |
}
}
list $x \
[interp eval test_interp {useSet}] \
[interp delete test_interp]
} {123 {set called with a 123} {}}
test basic-24.2 {Tcl_DeleteCommandFromToken, deleting commands changes command epoch} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
catch {rename p ""}
proc p {} {
return "global p"
}
namespace eval test_ns_basic {
proc p {} {
return "namespace p"
}
proc callP {} {
p
}
}
list [test_ns_basic::callP] \
[rename test_ns_basic::p ""] \
[test_ns_basic::callP]
} {{namespace p} {} {global p}}
test basic-24.3 {Tcl_DeleteCommandFromToken, delete imported cmds that refer to a deleted cmd} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
catch {rename p ""}
namespace eval test_ns_basic {
namespace export p
proc p {} {return 42}
}
namespace eval test_ns_basic2 {
namespace import ::test_ns_basic::*
|
| ︙ | ︙ | |||
455 456 457 458 459 460 461 |
test basic-34.1 {TclGlobalInvoke} {emptyTest} {
} {}
test basic-35.1 {TclObjInvokeGlobal} {emptyTest} {
} {}
test basic-36.1 {TclObjInvoke, lookup of "unknown" command} {
| | | 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 |
test basic-34.1 {TclGlobalInvoke} {emptyTest} {
} {}
test basic-35.1 {TclObjInvokeGlobal} {emptyTest} {
} {}
test basic-36.1 {TclObjInvoke, lookup of "unknown" command} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
catch {interp delete test_interp}
interp create test_interp
interp eval test_interp {
proc unknown {args} {
return "global unknown"
}
namespace eval test_ns_basic {
|
| ︙ | ︙ | |||
583 584 585 586 587 588 589 |
"return -code return"
(file "BREAKtest" line 2)}}
test basic-47.1 {Tcl_EvalEx: check for missing close-bracket} -body {
subst {a[set b [format cd]}
} -returnCodes error -result {missing close-bracket}
| > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 |
"return -code return"
(file "BREAKtest" line 2)}}
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 {{expand}\{}
} -constraints $constraints -returnCodes error -result {unmatched open brace in list}
test basic-47.3.$noComp {Tcl_EvalEx, error during substitution} -body {
run {{expand}[error foo]}
} -constraints $constraints -returnCodes error -result foo
test basic-47.4.$noComp {Tcl_EvalEx: no expansion} $constraints {
run {list {expand} {expand} {expand}}
} {expand expand expand}
test basic-47.5.$noComp {Tcl_EvalEx: expansion} $constraints {
run {list {expand}{} {expand} {expand}x {expand}"y z"}
} {expand x y z}
test basic-47.6.$noComp {Tcl_EvalEx: expansion to zero args} $constraints {
run {list {expand}{}}
} {}
test basic-47.7.$noComp {Tcl_EvalEx: expansion to one arg} $constraints {
run {list {expand}x}
} x
test basic-47.8.$noComp {Tcl_EvalEx: expansion to many args} $constraints {
run {list {expand}"y z"}
} {y z}
test basic-47.9.$noComp {Tcl_EvalEx: expansion and subst order} $constraints {
set x 0
run {list [incr x] {expand}[incr x] [incr x] \
{expand}[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 {expand}{} 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 {expand}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 {expand}{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 {expand}{} {expand}{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 {expand}{} 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 {expand}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 {expand}{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 {expand}{} {expand}{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 {expand}$::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 {expand}$::l1 $::l2 {expand}[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 {{expand}$::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 {expand}$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 {expand}$::l1$::l2}
} {a {b b} c de f {g g} h}
test basic-48.7.$noComp {expansion: odd usage} -constraints $constraints -body {
run {list {expand}[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 {expand}hej$::l1}
} {heja {b b} c d}
test basic-48.9.$noComp {expansion: Not all {expand} should trigger} $constraints {
run {list {expand}$::l1 \{expand\}$::l2 "{expand}$::l1" {{expand} i j k}}
} {a {b b} c d {{expand}e f {g g} h} {{expand}a {b b} c d} {{expand} i j k}}
test basic-48.10.$noComp {expansion: expansion of command word} -setup {
set cmd [list string range jultomte]
} -constraints $constraints -body {
run {{expand}$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 {{expand}$cmd {expand}$bar}
} -cleanup {
unset cmd bar
} -result {}
test basic-48.12.$noComp {expansion: odd usage} $constraints {
run {list {expand}$::l1 {expand}"hej hopp" {expand}$::l2}
} {a {b b} c d hej hopp e f {g g} h}
test basic-48.13.$noComp {expansion: odd usage} $constraints {
run {list {expand}$::l1 {expand}{hej hopp} {expand}$::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 { {expand}$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 {expand}$a($b) {expand}[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 {expand}$l $a$a}]
# A short number of words and a longer result (27)
set l [run {list {expand}$l $a$a {expand}$l $a$a {expand}$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_ {expand}$l $a$a {expand}$l $a$a {expand}$l}}]} {
error "An error was expected in the previous statement"
}
# Many words
set l [run {list {expand}$l $a$a {expand}$l $a$a \
{expand}$l $a$a {expand}$l $a$a \
{expand}$l $a$a {expand}$l $a$a \
{expand}$l $a$a {expand}$l $a$a \
{expand}$l $a$a {expand}$l $a$a \
{expand}$l $a$a {expand}$l $a$a \
{expand}$l $a$a {expand}$l $a$a \
{expand}$l $a$a {expand}$l $a$a \
{expand}$l $a$a {expand}$l $a$a \
{expand}$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 {expand}$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 { {expand}$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] {expand}$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 {expand}$::l1 {expand}"hej hopp" {expand}$::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 {expand}$::l1 {expand}{hej hopp} {expand}$::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 {expand}$::l1 {expand}"hej hopp {expand}$::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 { {expand}break }
}
lappend res $t
for {set t 0} {$t < 10} {incr t} {
run { {expand}continue }
set t 20
}
lappend res $t
lappend res [catch { run { {expand}{error Hejsan} } } err]
lappend res $err
} -cleanup {
unset res t
} -result {0 10 1 Hejsan}
} ;# End of noComp loop
# Clean up after expand tests
unset noComp l1 l2 constraints
rename l3 {}
rename run {}
#cleanup
catch {namespace delete {expand}[namespace children :: test_ns_*]}
catch {namespace delete george}
catch {interp delete test_interp}
catch {rename p ""}
catch {rename q ""}
catch {rename cmd ""}
catch {rename value:at: ""}
catch {unset x}
::tcltest::cleanupTests
return
|
Changes to tests/binary.test.
1 2 3 4 5 6 7 8 9 10 11 12 | # This file tests the tclBinary.c file and the "binary" Tcl command. # # 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 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. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# This file tests the tclBinary.c file and the "binary" Tcl command.
#
# 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 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.
#
# RCS: @(#) $Id: binary.test,v 1.11.4.2 2004/02/07 05:48:02 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
namespace import -force ::tcltest::*
}
test binary-0.1 {DupByteArrayInternalRep} {
|
| ︙ | ︙ | |||
1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 |
set y [binary format a* $x]
list $x $y
} "\u00a4 \u00a4"
test binary-46.5 {Tcl_BinaryObjCmd: handling of non-ISO8859-1 chars} {
set x [binary scan \u00a4 a* y]
list $x $y [encoding convertfrom iso8859-15 $y]
} "1 \u00a4 \u20ac"
# cleanup
::tcltest::cleanupTests
return
| > > > > > > > > | 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 |
set y [binary format a* $x]
list $x $y
} "\u00a4 \u00a4"
test binary-46.5 {Tcl_BinaryObjCmd: handling of non-ISO8859-1 chars} {
set x [binary scan \u00a4 a* y]
list $x $y [encoding convertfrom iso8859-15 $y]
} "1 \u00a4 \u20ac"
test binary-47.1 {Tcl_BinaryObjCmd: number cache reference count handling} {
# This test is only reliable when memory debugging is turned on,
# but without even memory debugging it should still generate the
# expected answers and might therefore still pick up memory corruption
# caused by [Bug 851747].
list [binary scan aba ccc x x x] $x
} {3 97}
# cleanup
::tcltest::cleanupTests
return
|
Changes to tests/cmdIL.test.
1 2 3 4 5 6 7 8 9 10 | # This file contains a collection of tests for the procedures in the # file tclCmdIL.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. # 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. # | | | > > > | > | > > | 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 |
# This file contains a collection of tests for the procedures in the
# file tclCmdIL.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.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: cmdIL.test,v 1.14.8.3 2004/02/07 05:48:02 dgp Exp $
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]]
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}}
test cmdIL-1.3 {Tcl_LsortObjCmd procedure, default options} {
lsort {d e c b a \{ d35 d300}
} {a b c d d300 d35 e \{}
test cmdIL-1.4 {Tcl_LsortObjCmd procedure, -ascii option} {
lsort -integer -ascii {d e c b a d35 d300}
} {a b c d d300 d35 e}
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} -setup {
proc cmp {a b} {
expr {[string match x* $b] - [string match x* $a]}
}
} -body {
lsort -command cmp {x1 abc x2 def x3 x4}
} -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}
test cmdIL-1.8 {Tcl_LsortObjCmd procedure, -dictionary option} {
lsort -dictionary {d e c b a d35 d300}
} {a b c d d35 d300 e}
test cmdIL-1.9 {Tcl_LsortObjCmd procedure, -dictionary option} {
|
| ︙ | ︙ | |||
78 79 80 81 82 83 84 |
test cmdIL-1.22 {Tcl_LsortObjCmd procedure, unique sort} {
lsort -integer -unique {3 1 2 3 1 4 3}
} {1 2 3 4}
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}}
| | > | > < | | > | > < | | > | > > | < > > > > | | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
test cmdIL-1.22 {Tcl_LsortObjCmd procedure, unique sort} {
lsort -integer -unique {3 1 2 3 1 4 3}
} {1 2 3 4}
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} -setup {
catch {rename 1 ""}
proc testcmp {a b} {return [string compare $a $b]}
} -body {
set l [list [list a b] [list c d]]
list [catch {lsort -command testcmp -index 1 $l} msg] $msg
} -cleanup {
rename testcmp ""
} -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]]
list [catch {lsort -index 1 -command testcmp $l} msg] $msg
} -cleanup {
rename testcmp ""
} -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}}
# 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} -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} {
lappend x [expr {[rand] & 0xfff}]
}
set y [lsort -integer $x]
set old -1
foreach el $y {
if {$el < $old} {
append result "list {$x} sorted to {$y}, element $el out of order\n"
break
}
set old $el
}
}
set result
} -cleanup {
rename rand ""
} -result {}
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
} -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}}
test cmdIL-3.3 {SortCompare procedure, -index option} {
list [catch {lsort -integer -index 2 {{20 10} {15 30 40}}} msg] $msg
} {1 {element 2 missing from sublist "20 10"}}
test cmdIL-3.4 {SortCompare procedure, -index option} {
|
| ︙ | ︙ | |||
178 179 180 181 182 183 184 |
} {1 {expected floating-point number but got "6...4"}}
test cmdIL-3.13 {SortCompare procedure, -real option} {
list [catch {lsort -real {3 1x7}} msg] $msg
} {1 {expected floating-point number but got "1x7"}}
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}
| | > > | | > > | | > > | | > > | | 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
} {1 {expected floating-point number but got "6...4"}}
test cmdIL-3.13 {SortCompare procedure, -real option} {
list [catch {lsort -real {3 1x7}} msg] $msg
} {1 {expected floating-point number but got "1x7"}}
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} -body {
proc cmp {a b} {
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)
invoked from within
"cmp 48 6"
(-compare command)
invoked from within
"lsort -command cmp {48 6}"}}
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}}
} -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
} -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}
} -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}
test cmdIL-4.1 {DictionaryCompare procedure, numerics, leading zeros} {
lsort -dictionary {a003b a03b}
} {a03b a003b}
|
| ︙ | ︙ | |||
382 383 384 385 386 387 388 |
{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}}
| | | | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 |
{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 {}
}
# cleanup
::tcltest::cleanupTests
return
# Local Variables:
# mode: tcl
# End:
|
Changes to tests/cmdInfo.test.
| ︙ | ︙ | |||
9 10 11 12 13 14 15 | # Copyright (c) 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. # | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# Copyright (c) 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.
#
# RCS: @(#) $Id: cmdInfo.test,v 1.7.4.1 2004/02/07 05:48:02 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest 2
namespace import -force ::tcltest::*
}
::tcltest::testConstraint testcmdinfo \
|
| ︙ | ︙ | |||
67 68 69 70 71 72 73 |
test cmdinfo-4.1 {Tcl_GetCommandName/Tcl_GetCommandFullName procedures} \
{testcmdtoken} {
set x [testcmdtoken create x1]
rename x1 newName
set y [testcmdtoken name $x]
rename newName x1
| | | | | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
test cmdinfo-4.1 {Tcl_GetCommandName/Tcl_GetCommandFullName procedures} \
{testcmdtoken} {
set x [testcmdtoken create x1]
rename x1 newName
set y [testcmdtoken name $x]
rename newName x1
lappend y {expand}[testcmdtoken name $x]
} {newName ::newName x1 ::x1}
catch {rename newTestCmd {}}
catch {rename newTestCmd2 {}}
test cmdinfo-5.1 {Names for commands created when inside namespaces} \
{testcmdtoken} {
# create namespace cmdInfoNs1
namespace eval cmdInfoNs1 {} ;# creates namespace cmdInfoNs1
# create namespace cmdInfoNs1::cmdInfoNs2 and execute a script in it
set x [namespace eval cmdInfoNs1::cmdInfoNs2 {
# the following creates a cmd in the global namespace
testcmdtoken create testCmd
}]
set y [testcmdtoken name $x]
rename ::testCmd newTestCmd
lappend y {expand}[testcmdtoken name $x]
} {testCmd ::testCmd newTestCmd ::newTestCmd}
test cmdinfo-6.1 {Names for commands created when outside namespaces} \
{testcmdtoken} {
set x [testcmdtoken create cmdInfoNs1::cmdInfoNs2::testCmd]
set y [testcmdtoken name $x]
rename cmdInfoNs1::cmdInfoNs2::testCmd newTestCmd2
lappend y {expand}[testcmdtoken name $x]
} {testCmd ::cmdInfoNs1::cmdInfoNs2::testCmd newTestCmd2 ::newTestCmd2}
# cleanup
catch {namespace delete cmdInfoNs1::cmdInfoNs2 cmdInfoNs1}
catch {rename x1 ""}
::tcltest::cleanupTests
return
|
Changes to tests/cmdMZ.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # The tests in this file cover the procedures in tclCmdMZ.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-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. # | | < < < | | | | | 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 |
# The tests in this file cover the procedures in tclCmdMZ.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-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.
#
# RCS: @(#) $Id: cmdMZ.test,v 1.15.2.3 2004/02/07 05:48:02 dgp Exp $
if {[catch {package require tcltest 2.0.2}]} {
puts stderr "Skipping tests in [info script]. tcltest 2.0.2 required."
return
}
namespace eval ::tcl::test::cmdMZ {
namespace import ::tcltest::cleanupTests
namespace import ::tcltest::makeFile
namespace import ::tcltest::removeFile
namespace import ::tcltest::temporaryDirectory
namespace import ::tcltest::test
# Tcl_PwdObjCmd
test cmdMZ-1.1 {Tcl_PwdObjCmd} {
list [catch {pwd a} msg] $msg
} {1 {wrong # args: should be "pwd"}}
test cmdMZ-1.2 {Tcl_PwdObjCmd: simple pwd} {
catch pwd
} 0
test cmdMZ-1.3 {Tcl_PwdObjCmd: simple pwd} {
expr [string length pwd]>0
} 1
test cmdMZ-1.4 {Tcl_PwdObjCmd: failure} {unixOnly 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.
set foodir [file join [temporaryDirectory] foo]
file delete -force $foodir
file mkdir $foodir
set cwd [pwd]
cd $foodir
file attr . -permissions 000
set result [list [catch {pwd} msg] $msg]
|
| ︙ | ︙ |
Changes to tests/compile.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # This file contains tests for the files tclCompile.c, tclCompCmds.c # and tclLiteral.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) 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. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # This file contains tests for the files tclCompile.c, tclCompCmds.c # and tclLiteral.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) 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. # # RCS: @(#) $Id: compile.test,v 1.27.2.1 2004/02/07 05:48:02 dgp Exp $ package require tcltest 2 namespace import -force ::tcltest::* # The following tests are very incomplete, although the rest of the # test suite covers this file fairly well. |
| ︙ | ︙ | |||
270 271 272 273 274 275 276 | # Special section for tests of tclLiteral.c # The following tests check for incorrect memory handling in # 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]] | | | | 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
# Special section for tests of tclLiteral.c
# The following tests check for incorrect memory handling in
# 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 memory [llength [info commands memory]]
test compile-12.1 {testing literal leak on interp delete} {memory} {
proc getbytes {} {
set lines [split [memory info] "\n"]
lindex [lindex $lines 3] 3
}
set end [getbytes]
for {set i 0} {$i < 5} {incr i} {
|
| ︙ | ︙ | |||
294 295 296 297 298 299 300 |
}
rename getbytes {}
set leak [expr {$end - $tmp}]
} 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.
| | | 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
}
rename getbytes {}
set leak [expr {$end - $tmp}]
} 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} {memory exec} {
makeFile {
for {set i 0} {$i < 5} {incr i} {
namespace eval bar {}
namespace delete bar
}
puts 0
} source.file
|
| ︙ | ︙ | |||
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
test compile-15.5 {proper TCL_RETURN code from [return]} {
proc p {} {catch {set a 1}; return}
set result [p]
rename p {}
set result
} ""
# cleanup
catch {rename p ""}
catch {namespace delete test_ns_compile}
catch {unset x}
catch {unset y}
catch {unset a}
::tcltest::cleanupTests
return
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 |
test compile-15.5 {proper TCL_RETURN code from [return]} {
proc p {} {catch {set a 1}; return}
set result [p]
rename p {}
set result
} ""
testConstraint testevalex [llength [info commands testevalex]]
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 {{expand}a } 255]"
} [lrepeat 255 a]
test compile-16.2.$noComp {TclCompileScript: word expansion} $constraints {
run "list [string repeat {{expand}a } 256]"
} [lrepeat 256 a]
test compile-16.3.$noComp {TclCompileScript: word expansion} $constraints {
run "list [string repeat {{expand}a } 257]"
} [lrepeat 257 a]
test compile-16.4.$noComp {TclCompileScript: word expansion} $constraints {
run {{expand}list}
} {}
test compile-16.5.$noComp {TclCompileScript: word expansion} $constraints {
run {{expand}list {expand}{x y z}}
} {x y z}
test compile-16.6.$noComp {TclCompileScript: word expansion} $constraints {
run {{expand}list {expand}[list x y z]}
} {x y z}
test compile-16.7.$noComp {TclCompileScript: word expansion} $constraints {
run {{expand}list {expand}[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 {{expand}list {expand}$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 {{expand}list {expand}$l$l}
} -constraints $constraints -cleanup {
unset l
} -result {x y zx y z}
test compile-16.10.$noComp {TclCompileScript: word expansion} -body {
run {{expand}\{}
} -constraints $constraints -returnCodes error \
-result {unmatched open brace in list}
test compile-16.11.$noComp {TclCompileScript: word expansion} -body {
proc badList {} {return \{}
run {{expand}[badList]}
} -constraints $constraints -cleanup {
rename badList {}
} -returnCodes error -result {unmatched open brace in list}
test compile-16.12.$noComp {TclCompileScript: word expansion} $constraints {
run {{expand}list x y z}
} {x y z}
test compile-16.13.$noComp {TclCompileScript: word expansion} $constraints {
run {{expand}list x y {expand}z}
} {x y z}
test compile-16.14.$noComp {TclCompileScript: word expansion} $constraints {
run {{expand}list x {expand}y z}
} {x y z}
test compile-16.15.$noComp {TclCompileScript: word expansion} $constraints {
run {list x y {expand}z}
} {x y z}
test compile-16.16.$noComp {TclCompileScript: word expansion} $constraints {
run {list x {expand}y z}
} {x y z}
test compile-16.17.$noComp {TclCompileScript: word expansion} $constraints {
run {list {expand}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 {{expand}[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 {{expand}[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 {{expand}[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 {{expand}[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]]
} ;# End of noComp loop
# cleanup
catch {rename p ""}
catch {namespace delete test_ns_compile}
catch {unset x}
catch {unset y}
catch {unset a}
::tcltest::cleanupTests
return
|
Changes to tests/dict.test.
1 2 3 4 5 6 7 8 9 10 11 | # 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. # | | > > > | 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 |
# 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.
#
# RCS: @(#) $Id: dict.test,v 1.2.2.3 2004/02/07 05:48:02 dgp Exp $
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]]
# 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} {
|
| ︙ | ︙ | |||
60 61 62 63 64 65 66 |
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
| | | | | | | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
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}
|
| ︙ | ︙ | |||
132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
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-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
| > | 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
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
|
| ︙ | ︙ | |||
196 197 198 199 200 201 202 |
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
| | < < | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
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} {
|
| ︙ | ︙ | |||
706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 |
} {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}}
# cleanup
::tcltest::cleanupTests
return
# Local Variables:
# mode: tcl
# End:
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 |
} {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 {
proc getbytes {} {
set lines [split [memory info] "\n"]
lindex [lindex $lines 3] 3
}
# 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}
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}
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}
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}
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}
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}
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}
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}
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}
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}
unset bepa
}
} -constraints memory -body {
set end [getbytes]
for {set i 0} {$i < 5} {incr i} {
stress
set tmp $end
set end [getbytes]
}
expr {$end - $tmp}
} -cleanup {
unset -nocomplain end i tmp
rename getbytes {}
rename stress {}
} -result 0
# cleanup
::tcltest::cleanupTests
return
# Local Variables:
# mode: tcl
# End:
|
Changes to tests/encoding.test.
1 2 3 4 5 6 7 8 9 10 | # This file contains a collection of tests for tclEncoding.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. # 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. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# This file contains a collection of tests for tclEncoding.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.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: encoding.test,v 1.18.2.1 2004/02/07 05:48:02 dgp Exp $
package require tcltest 2
namespace import -force ::tcltest::*
proc toutf {args} {
global x
lappend x "toutf $args"
|
| ︙ | ︙ | |||
537 538 539 540 541 542 543 |
# Difference should be empty.
set diff
} {}
}
}
| | | 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 |
# Difference should be empty.
set diff
} {}
}
}
file delete {expand}[glob -directory [temporaryDirectory] *.chars *.tcltestout]
# ===> Cut here <===
# EscapeFreeProc, GetTableEncoding, unilen
# are fully tested by the rest of this file
# cleanup
::tcltest::cleanupTests
return
|
Changes to tests/execute.test.
| ︙ | ︙ | |||
10 11 12 13 14 15 16 | # # 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. # | | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#
# 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.
#
# RCS: @(#) $Id: execute.test,v 1.13.4.2 2004/02/07 05:48:02 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest 2
namespace import -force ::tcltest::*
}
catch {namespace delete {expand}[namespace children :: test_ns_*]}
catch {rename foo ""}
catch {unset x}
catch {unset y}
catch {unset msg}
::tcltest::testConstraint testobj \
[expr {[info commands testobj] != {} \
|
| ︙ | ︙ | |||
503 504 505 506 507 508 509 |
# INST_FOREACH_STEP4 not tested
# INST_BEGIN_CATCH4 not tested
# INST_END_CATCH not tested
# INST_PUSH_RESULT not tested
# INST_PUSH_RETURN_CODE not tested
test execute-4.1 {Tcl_GetCommandFromObj, convert to tclCmdNameType} {
| | | | 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 |
# INST_FOREACH_STEP4 not tested
# INST_BEGIN_CATCH4 not tested
# INST_END_CATCH not tested
# INST_PUSH_RESULT not tested
# INST_PUSH_RETURN_CODE not tested
test execute-4.1 {Tcl_GetCommandFromObj, convert to tclCmdNameType} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
catch {unset x}
catch {unset y}
namespace eval test_ns_1 {
namespace export cmd1
proc cmd1 {args} {return "cmd1: $args"}
proc cmd2 {args} {return "cmd2: $args"}
}
namespace eval test_ns_1::test_ns_2 {
namespace import ::test_ns_1::*
}
set x "test_ns_1::"
set y "test_ns_2::"
list [namespace which -command ${x}${y}cmd1] \
[catch {namespace which -command ${x}${y}cmd2} msg] $msg \
[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 {namespace delete {expand}[namespace children :: test_ns_*]}
catch {rename foo ""}
catch {unset l}
proc foo {} {
return "global foo"
}
namespace eval test_ns_1 {
proc whichFoo {} {
|
| ︙ | ︙ | |||
543 544 545 546 547 548 549 |
return "namespace foo"
}
}
lappend l [test_ns_1::whichFoo]
set l
} {::foo ::test_ns_1::foo}
test execute-4.3 {Tcl_GetCommandFromObj, command never found} {
| | | | 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 |
return "namespace foo"
}
}
lappend l [test_ns_1::whichFoo]
set l
} {::foo ::test_ns_1::foo}
test execute-4.3 {Tcl_GetCommandFromObj, command never found} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
catch {rename foo ""}
namespace eval test_ns_1 {
proc foo {} {
return "namespace foo"
}
}
namespace eval test_ns_1 {
proc foo {} {
return "namespace foo"
}
}
list [namespace eval test_ns_1 {namespace which -command foo}] \
[rename test_ns_1::foo ""] \
[catch {namespace eval test_ns_1 {namespace which -command foo}} msg] $msg
} {::test_ns_1::foo {} 0 {}}
test execute-5.1 {SetCmdNameFromAny, set cmd name to empty heap string if NULL} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
catch {unset l}
proc {} {} {return {}}
{}
set l {}
lindex {} 0
{}
} {}
|
| ︙ | ︙ | |||
730 731 732 733 734 735 736 |
} {too many nested evaluations (infinite loop?)}
# cleanup
if {[info commands testobj] != {}} {
testobj freeallvars
}
| | | 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 |
} {too many nested evaluations (infinite loop?)}
# cleanup
if {[info commands testobj] != {}} {
testobj freeallvars
}
catch {namespace delete {expand}[namespace children :: test_ns_*]}
catch {rename foo ""}
catch {rename p ""}
catch {rename {} ""}
catch {rename { } ""}
catch {unset x}
catch {unset y}
catch {unset msg}
::tcltest::cleanupTests
return
|
Changes to tests/fCmd.test.
1 2 3 4 5 6 7 8 9 10 11 12 | # 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) 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. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# 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) 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.
#
# RCS: @(#) $Id: fCmd.test,v 1.27.2.4 2004/02/07 05:48:02 dgp Exp $
#
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest 2
namespace import -force ::tcltest::*
}
|
| ︙ | ︙ | |||
509 510 511 512 513 514 515 |
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} {
cleanup /tmp
createfile tf1
file rename tf1 /tmp
| | | | | 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 |
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} {
cleanup /tmp
createfile tf1
file rename tf1 /tmp
glob -nocomplain tf* /tmp/tf1
} {/tmp/tf1}
test fCmd-6.20 {CopyRenameOneFile: errno == EXDEV} {pcOnly} {
catch {file delete -force c:/tcl8975@ d:/tcl8975@}
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@
}
file delete -force c:/tcl8975@
set msg
} {d:/tcl8975@}
test fCmd-6.21 {CopyRenameOneFile: copy/rename: S_ISDIR(source)} \
{unixOnly notRoot} {
cleanup /tmp
file mkdir td1
file rename td1 /tmp
glob -nocomplain td* /tmp/td*
} {/tmp/td1}
test fCmd-6.22 {CopyRenameOneFile: copy/rename: !S_ISDIR(source)} \
{unixOnly notRoot} {
cleanup /tmp
createfile tf1
file rename tf1 /tmp
glob -nocomplain tf* /tmp/tf*
} {/tmp/tf1}
test fCmd-6.23 {CopyRenameOneFile: TclpCopyDirectory failed} \
{unixOnly notRoot xdev} {
cleanup /tmp
file mkdir td1/td2/td3
file attributes td1 -permissions 0000
set msg [list [catch {file rename td1 /tmp} msg] $msg]
|
| ︙ | ︙ | |||
865 866 867 868 869 870 871 |
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}
| | | 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 |
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} {nonPortable notRoot} {
cleanup
file mkdir td1
set dir [pwd]
cd td1
set res [list [catch {file rename [file join .. td1] [file join .. td1x]} msg] $msg]
cd $dir
set res
|
| ︙ | ︙ | |||
2150 2151 2152 2153 2154 2155 2156 |
} {1}
test fCmd-26.2 {TclDeleteFilesCmd: delete dir with symlink} {unixOnly notRoot} {
catch {file delete -force -- tfad1 tfad2}
file mkdir tfad1
file mkdir tfad2
| | | 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 |
} {1}
test fCmd-26.2 {TclDeleteFilesCmd: delete dir with symlink} {unixOnly notRoot} {
catch {file delete -force -- tfad1 tfad2}
file mkdir tfad1
file mkdir tfad2
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]
file delete tfad1
|
| ︙ | ︙ | |||
2190 2191 2192 2193 2194 2195 2196 |
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} {
catch {file delete -force -- foo.tmp}
createfile foo.tmp
set attrs [file attributes foo.tmp]
| | | | | 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 |
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} {
catch {file delete -force -- foo.tmp}
createfile foo.tmp
set attrs [file attributes foo.tmp]
list [catch {file attributes foo.tmp {expand}[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} {
catch {file delete -force -- foo.tmp}
createfile foo.tmp
set attrs [file attributes foo.tmp]
list [catch {file attributes foo.tmp {expand}[lrange $attrs 0 1]} msg] $msg [file delete -force -- foo.tmp]
} {0 {} {}}
test fCmd-27.6 {TclFileAttrsCmd - setting more than one option} {foundGroup} {
catch {file delete -force -- foo.tmp}
createfile foo.tmp
set attrs [file attributes foo.tmp]
list [catch {file attributes foo.tmp {expand}[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
|
| ︙ | ︙ | |||
2302 2303 2304 2305 2306 2307 2308 |
test fCmd-28.10 {file link: linking to nonexistent path} {linkDirectory} {
cd [temporaryDirectory]
file delete -force abc.link
set res [list [catch {file link abc.link abc2.doesnt} msg] $msg]
cd [workingDirectory]
set res
| | > > > > > > > > | 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 |
test fCmd-28.10 {file link: linking to nonexistent path} {linkDirectory} {
cd [temporaryDirectory]
file delete -force abc.link
set res [list [catch {file link abc.link abc2.doesnt} msg] $msg]
cd [workingDirectory]
set res
} {1 {could not create new link "abc.link": target "abc2.doesnt" doesn't exist}}
test fCmd-28.10.1 {file link: linking to nonexistent path} {linkDirectory} {
cd [temporaryDirectory]
file delete -force abc.link
set res [list [catch {file link doesnt/abc.link abc.dir} msg] $msg]
cd [workingDirectory]
set res
} {1 {could not create new link "doesnt/abc.link": no such file or directory}}
test fCmd-28.11 {file link: success with directory} {linkDirectory} {
cd [temporaryDirectory]
file delete -force abc.link
set res [list [catch {file link abc.link abc.dir} msg] $msg]
cd [workingDirectory]
set res
|
| ︙ | ︙ | |||
2328 2329 2330 2331 2332 2333 2334 |
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]])} {
| | > > | 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 |
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 abc.link ; cd ..': \
\"[file normalize $up]\" should be \"[file normalize $orig]\" or\
\"[file normalize [file dirname abc.dir]]\""
} else {
set res "ok"
}
cd [workingDirectory]
set res
} {ok}
|
| ︙ | ︙ | |||
2376 2377 2378 2379 2380 2381 2382 |
cd [workingDirectory]
set res
} {link abc.dir}
cd [temporaryDirectory]
file delete -force abc.link
file delete -force abc2.link
| | > > > | 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 |
cd [workingDirectory]
set res
} {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} {
cd [temporaryDirectory]
file delete -force abc.link
|
| ︙ | ︙ | |||
2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 |
test fCmd-28.18 {file link: glob -type d} {linkDirectory} {
cd [temporaryDirectory]
set res [lsort [glob -dir [pwd] -type d -tails abc*]]
cd [workingDirectory]
set res
} [lsort [list abc.link abc.dir abc2.dir]]
test fCmd-29.1 {weird memory corruption fault} {
catch {set res [open [file join ~a_totally_bogus_user_id/foo bar]]}
} 1
cd [temporaryDirectory]
file delete -force abc.link
cd [workingDirectory]
removeFile abc2.file
removeFile abc.file
removeDirectory abc2.dir
removeDirectory abc.dir
# cleanup
cleanup
::tcltest::cleanupTests
return
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 |
test fCmd-28.18 {file link: glob -type d} {linkDirectory} {
cd [temporaryDirectory]
set res [lsort [glob -dir [pwd] -type d -tails abc*]]
cd [workingDirectory]
set res
} [lsort [list abc.link abc.dir abc2.dir]]
test fCmd-28.19 {file link: relative paths} {winOnly linkDirectory} {
cd [temporaryDirectory]
file mkdir d1/d2/d3
set res [list [catch {file link d1/l2 d1/d2} err] $err]
lappend res [catch {file delete -force d1} err] $err
} {0 d1/d2 0 {}}
test fCmd-28.20 {file link: relative paths} {unixOnly linkDirectory} {
cd [temporaryDirectory]
file mkdir d1/d2/d3
list [catch {file link d1/l2 d1/d2} res] $res
} {1 {could not create new link "d1/l2": target "d1/d2" doesn't exist}}
test fCmd-28.21 {file link: relative paths} {unixOnly linkDirectory} {
cd [temporaryDirectory]
file mkdir d1/d2/d3
list [catch {file link d1/l2 d2} res] $res
} {0 d2}
test fCmd-28.22 {file link: relative paths} {unixOnly linkDirectory} {
cd [temporaryDirectory]
file mkdir d1/d2/d3
catch {file delete -force d1/l2}
list [catch {file link d1/l2 d2/d3} res] $res
} {0 d2/d3}
test fCmd-29.1 {weird memory corruption fault} {
catch {set res [open [file join ~a_totally_bogus_user_id/foo bar]]}
} 1
cd [temporaryDirectory]
file delete -force abc.link
file delete -force d1/d2
file delete -force d1
cd [workingDirectory]
removeFile abc2.file
removeFile abc.file
removeDirectory abc2.dir
removeDirectory abc.dir
# cleanup
cleanup
::tcltest::cleanupTests
return
|
Changes to tests/fileName.test.
1 2 3 4 5 6 7 8 9 10 11 12 | # This file tests the filename manipulation routines. # # 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-1996 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. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# This file tests the filename manipulation routines.
#
# 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-1996 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.
#
# RCS: @(#) $Id: fileName.test,v 1.31.2.2 2004/02/07 05:48:02 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
namespace import -force ::tcltest::*
}
tcltest::testConstraint testsetplatform [string equal testsetplatform [info commands testsetplatform]]
|
| ︙ | ︙ | |||
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 |
testsetplatform windows
list [catch {testtranslatefilename {c:/foo}} msg] $msg
} {0 {c:\foo}}
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
| > > > > | 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 |
testsetplatform windows
list [catch {testtranslatefilename {c:/foo}} msg] $msg
} {0 {c:\foo}}
test filename-10.3 {Tcl_TranslateFileName} {testsetplatform} {
testsetplatform windows
list [catch {testtranslatefilename {c:/\\foo/}} msg] $msg
} {0 {c:\foo}}
test filename-10.3.1 {Tcl_TranslateFileName} {testsetplatform} {
testsetplatform windows
list [catch {testtranslatefilename {c://///}} msg] $msg
} {0 c:\\}
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
|
| ︙ | ︙ | |||
1580 1581 1582 1583 1584 1585 1586 |
}
catch {
set tmpd [pwd]
cd [lindex [file volumes] 0]
set res2 [glob *]
cd $tmpd
}
| | > > > > | 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 |
}
catch {
set tmpd [pwd]
cd [lindex [file volumes] 0]
set res2 [glob *]
cd $tmpd
}
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
} {1 {bad argument to "-types": abcde}}
test filename-11.47 {Tcl_GlobCmd} {
list [catch {glob -types abcde -path foo *} msg] $msg
} {1 {bad argument to "-types": abcde}}
|
| ︙ | ︙ | |||
1869 1870 1871 1872 1873 1874 1875 |
# is reset...
string equal [glob -nocomplain ~wontexist ~blah ~] \
[glob -nocomplain ~ ~blah ~wontexist]
} {1}
test filename-15.5 {unix specific globbing} {unixOnly nonPortable} {
glob ~ouster/.csh*
} "/home/ouster/.cshrc"
| | > > > > > > > > > > > > > > > > > > | > > > > > > | | | | | | | | | | | 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 |
# is reset...
string equal [glob -nocomplain ~wontexist ~blah ~] \
[glob -nocomplain ~ ~blah ~wontexist]
} {1}
test filename-15.5 {unix specific globbing} {unixOnly nonPortable} {
glob ~ouster/.csh*
} "/home/ouster/.cshrc"
catch {close [open globTest/odd\\\[\]*?\{\}name w]}
test filename-15.6 {unix specific globbing} {unixOnly} {
global env
set temp $env(HOME)
set env(HOME) $env(HOME)/globTest/odd\\\[\]*?\{\}name
set result [list [catch {glob ~} msg] $msg]
set env(HOME) $temp
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} {winOnly} {
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)} {
cd c:/
file delete -force globTest
file mkdir globTest
close [open globTest/x1.BAT w]
close [open globTest/y1.Bat w]
close [open globTest/z1.bat w]
}
test filename-16.1 {windows specific globbing} {pcOnly} {
lsort [glob globTest/*.bat]
} {globTest/x1.BAT globTest/y1.Bat globTest/z1.bat}
test filename-16.2 {windows specific globbing} {pcOnly} {
list [catch {glob c:} res] $res
} {0 c:}
test filename-16.2.1 {windows specific globbing} {pcOnly} {
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} {pcOnly} {
glob -nocomplain c:\\\\
} c:/
test filename-16.4 {windows specific globbing} {pcOnly} {
glob -nocomplain c:/
} c:/
test filename-16.5 {windows specific globbing} {pcOnly} {
glob -nocomplain c:*bTest
} c:globTest
test filename-16.6 {windows specific globbing} {pcOnly} {
glob -nocomplain c:\\\\*bTest
} c:/globTest
test filename-16.7 {windows specific globbing} {pcOnly} {
glob -nocomplain c:/*bTest
} c:/globTest
test filename-16.8 {windows specific globbing} {pcOnly} {
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 -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 -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 -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 {
|
| ︙ | ︙ | |||
1950 1951 1952 1953 1954 1955 1956 |
expr {[lsearch -exact [glob {{.,*}*}] ".."] != -1}
} {1}
test filename-16.15 {windows specific globbing} {pcOnly} {
cd [lindex [glob -types d -dir C:/ *] 0]
glob ..
} {..}
test filename-16.16 {windows specific globbing} {pcOnly} {
| | | 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 |
expr {[lsearch -exact [glob {{.,*}*}] ".."] != -1}
} {1}
test filename-16.15 {windows specific globbing} {pcOnly} {
cd [lindex [glob -types d -dir C:/ *] 0]
glob ..
} {..}
test filename-16.16 {windows specific globbing} {pcOnly} {
file tail [lindex [glob -nocomplain "[lindex [glob -types d -dir C:/ *] 0]/.."] 0]
} {..}
test filename-17.1 {windows specific special files} {testsetplatform} {
testsetplatform win
list [file pathtype com1] [file pathtype con] [file pathtype lpt3] \
[file pathtype prn] [file pathtype nul] [file pathtype aux] \
[file pathtype foo]
|
| ︙ | ︙ |
Changes to tests/fileSystem.test.
| ︙ | ︙ | |||
20 21 22 23 24 25 26 |
namespace import ::tcltest::removeFile
namespace import ::tcltest::test
}
catch {
file delete -force link.file
file delete -force dir.link
| | | > | > > > > > > > > | > | | > | > > > > > > > > > | | | | | | | | | | | | | | | | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
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.dir linkinside.file]
}
makeFile "test file" gorp.file
makeDirectory dir.dir
makeDirectory [file join dir.dir dirinside.dir]
makeFile "test file in directory" [file join dir.dir inside.file]
proc testPathEqual {one two} {
if {[string equal $one $two]} {
return 1
} else {
return "not equal: $one $two"
}
}
if {[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 ..
}]} {
tcltest::testConstraint hasLinks 0
} else {
tcltest::testConstraint hasLinks 1
}
tcltest::testConstraint testsetplatform [string equal testsetplatform [info commands testsetplatform]]
if {[tcltest::testConstraint testsetplatform]} {
set platform [testgetplatform]
}
tcltest::testConstraint testsimplefilesystem \
[string equal testsimplefilesystem [info commands testsimplefilesystem]]
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.dir] [file normalize dir.link]
} {0}
test filesystem-1.2 {link normalisation} {hasLinks macOrUnix} {
testPathEqual [file normalize [file join gorp.file foo]] \
[file normalize [file join link.file foo]]
} {1}
test filesystem-1.3 {link normalisation} {hasLinks} {
testPathEqual [file normalize [file join dir.dir foo]] \
[file normalize [file join dir.link foo]]
} {1}
test filesystem-1.4 {link normalisation} {hasLinks} {
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} {
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.dir linkinside.file]] \
[file normalize [file join dir.link inside.file]]
} {0}
test filesystem-1.7 {link normalisation} {hasLinks macOrUnix} {
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.dir linkinside.filefoo]] \
[file normalize [file join dir.link inside.filefoo]]
} {0}
test filesystem-1.9 {link normalisation} {macOrUnix hasLinks} {
file delete -force dir.link
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} {
file link dir2.link dir.link
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] [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 *]] {
catch {file readlink $f}
|
| ︙ | ︙ | |||
125 126 127 128 129 130 131 132 133 134 135 |
file normalize C:/thislongnamedoesntexist
} {C:/thislongnamedoesntexist}
test filesystem-1.14 {file normalisation} {winOnly} {
# This used to be broken
file normalize c:/
} {C:/}
file delete -force dir2.file
file delete -force dir2.link
file delete -force link.file dir.link
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 |
file normalize C:/thislongnamedoesntexist
} {C:/thislongnamedoesntexist}
test filesystem-1.14 {file normalisation} {winOnly} {
# This used to be broken
file normalize c:/
} {C:/}
test filesystem-1.15 {file normalisation} {winOnly} {
file normalize c:/../
} {C:/}
test filesystem-1.16 {file normalisation} {winOnly} {
file normalize c:/.
} {C:/}
test filesystem-1.17 {file normalisation} {winOnly} {
file normalize c:/..
} {C:/}
test filesystem-1.17.1 {file normalisation} {winOnly} {
file normalize c:\\..
} {C:/}
test filesystem-1.18 {file normalisation} {winOnly} {
file normalize c:/./
} {C:/}
test filesystem-1.19 {file normalisation} {winOnly} {
file normalize w:/./../../..
} {w:/}
test filesystem-1.20 {file normalisation} {winOnly} {
file normalize //name/foo/../
} {//name/foo}
test filesystem-1.21 {file normalisation} {winOnly} {
file normalize C:///foo/./
} {C:/foo}
test filesystem-1.22 {file normalisation} {winOnly} {
file normalize //name/foo/.
} {//name/foo}
test filesystem-1.23 {file normalisation} {winOnly} {
file normalize c:/./foo
} {C:/foo}
test filesystem-1.24 {file normalisation} {winOnly} {
file normalize w:/./../../../a
} {w:/a}
test filesystem-1.25 {file normalisation} {winOnly} {
file normalize w:/./.././../../a
} {w:/a}
test filesystem-1.25.1 {file normalisation} {winOnly} {
file normalize w:/./.././..\\..\\a\\bb
} {w:/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
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 {$::tcl_platform(platform) == "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 {[tcltest::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-2.0 {new native path} {unixOnly} {
foreach f [lsort [glob -nocomplain /usr/bin/c*]] {
catch {file readlink $f}
}
# If we reach here we've succeeded. We used to crash above.
expr 1
|
| ︙ | ︙ | |||
194 195 196 197 198 199 200 |
-body {
testfilesystem 1
set filesystemReport {}
file exists foo
testfilesystem 0
set filesystemReport
}
| | | | | | 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 |
-body {
testfilesystem 1
set filesystemReport {}
file exists foo
testfilesystem 0
set filesystemReport
}
-result {*{access foo}}
}
test filesystem-4.1 {testfilesystem} {
-constraints Tcltest
-match glob
-body {
testfilesystem 1
set filesystemReport {}
catch {file stat foo bar}
testfilesystem 0
set filesystemReport
}
-result {*{stat foo}}
}
test filesystem-4.2 {testfilesystem} {
-constraints Tcltest
-match glob
-body {
testfilesystem 1
set filesystemReport {}
catch {file lstat foo bar}
testfilesystem 0
set filesystemReport
}
-result {*{lstat foo}}
}
test filesystem-4.3 {testfilesystem} {
-constraints Tcltest
-match glob
-body {
testfilesystem 1
set filesystemReport {}
catch {glob *}
testfilesystem 0
set filesystemReport
}
-result {*{matchindirectory *}*}
}
test filesystem-5.1 {cache and ~} {
-constraints Tcltest
-match regexp
-body {
set orig $env(HOME)
|
| ︙ | ︙ | |||
408 409 410 411 412 413 414 |
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]
| > > | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | > | 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 |
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
set res [glob -nocomplain -dir simplefs:/simpledir *]
testsimplefilesystem 0
file delete -force simpledir
cd $dir
set res
} {simplefs:/simpledir/simplefile}
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 unixOnly} {
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 unixOnly} {
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-8.1 {relative path objects and caching of pwd} {
set dir [pwd]
cd [tcltest::temporaryDirectory]
makeDirectory abc
|
| ︙ | ︙ |
Changes to tests/http.test.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | # Copyright (c) 1994-1996 Sun Microsystems, Inc. # Copyright (c) 1998-2000 by Ajuba Solutions. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 by Ajuba Solutions.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#
# RCS: @(#) $Id: http.test,v 1.33.4.3 2004/02/07 05:48:02 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest 2
namespace import -force ::tcltest::*
}
if {[catch {package require http 2} version]} {
|
| ︙ | ︙ | |||
96 97 98 99 100 101 102 |
catch {http::config -junk}
} 1
test http-1.4 {http::config} {
set savedconf [http::config]
http::config -proxyhost nowhere.come -proxyport 8080 -proxyfilter myFilter -useragent "Tcl Test Suite"
set x [http::config]
| | | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
catch {http::config -junk}
} 1
test http-1.4 {http::config} {
set savedconf [http::config]
http::config -proxyhost nowhere.come -proxyport 8080 -proxyfilter myFilter -useragent "Tcl Test Suite"
set x [http::config]
http::config {expand}$savedconf
set x
} {-accept */* -proxyfilter myFilter -proxyhost nowhere.come -proxyport 8080 -useragent {Tcl Test Suite}}
test http-1.5 {http::config} {
list [catch {http::config -proxyhost {} -junk 8080} msg] $msg
} {1 {Unknown option -junk, must be: -accept, -proxyfilter, -proxyhost, -proxyport, -useragent}}
|
| ︙ | ︙ |
Changes to tests/init.test.
1 2 3 4 5 6 7 8 9 10 11 12 | # Functionality covered: this file contains a collection of tests for the # auto loading and namespaces. # # 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. # | | | | 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 |
# Functionality covered: this file contains a collection of tests for the
# auto loading and namespaces.
#
# 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.
#
# RCS: @(#) $Id: init.test,v 1.9.4.3 2004/02/07 05:48:02 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
namespace import -force ::tcltest::*
}
# Clear out any namespaces called test_ns_*
catch {namespace delete {expand}[namespace children :: test_ns_*]}
# Six cases - white box testing
test init-1.1 {auto_qualify - absolute cmd - namespace} {
auto_qualify ::foo::bar ::blue
} ::foo::bar
|
| ︙ | ︙ |
Changes to tests/interp.test.
1 2 3 4 5 6 7 8 9 10 11 12 | # This file tests the multiple interpreter facility of Tcl # # 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-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. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# This file tests the multiple interpreter facility of Tcl
#
# 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-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.
#
# RCS: @(#) $Id: interp.test,v 1.22.2.3 2004/02/07 05:48:02 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest 2.1
namespace import -force ::tcltest::*
}
# The set of hidden commands is platform dependent:
|
| ︙ | ︙ | |||
2080 2081 2082 2083 2084 2085 2086 |
{knownBug} {
# Test that all the possibles error codes from Tcl get passed
# In both directions. This doesn't work.
set interp [interp create];
proc MyTestAlias {interp args} {
global aliasTrace;
lappend aliasTrace $args;
| | | 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 |
{knownBug} {
# Test that all the possibles error codes from Tcl get passed
# In both directions. This doesn't work.
set interp [interp create];
proc MyTestAlias {interp args} {
global aliasTrace;
lappend aliasTrace $args;
interp invokehidden $interp {expand}$args
}
foreach c {return} {
interp hide $interp $c;
interp alias $interp $c {} MyTestAlias $interp $c;
}
interp eval $interp {proc ret {code} {return -code $code ret$code}}
set res {}
|
| ︙ | ︙ |
Changes to tests/io.test.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | # 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. # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# 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.
#
# RCS: @(#) $Id: io.test,v 1.45.2.2 2004/02/07 05:48:02 dgp Exp $
if {[catch {package require tcltest 2}]} {
puts stderr "Skipping tests in [info script]. tcltest 2 required."
return
}
namespace eval ::tcl::test::io {
|
| ︙ | ︙ | |||
2143 2144 2145 2146 2147 2148 2149 |
set l ""
lappend l [lsort [testchannel open]]
set f [open $path(test1) w]
lappend l [lsort [testchannel open]]
close $f
lappend l [lsort [testchannel open]]
set x [list $consoleFileNames \
| | | 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 |
set l ""
lappend l [lsort [testchannel open]]
set f [open $path(test1) w]
lappend l [lsort [testchannel open]]
close $f
lappend l [lsort [testchannel open]]
set x [list $consoleFileNames \
[lsort [list {expand}$consoleFileNames $f]] \
$consoleFileNames]
string compare $l $x
} 0
test io-28.5 {Tcl_Close vs standard handles} {stdio unixOnly testchannel openpipe} {
file delete $path(script)
set f [open $path(script) w]
puts $f {
|
| ︙ | ︙ |
Changes to tests/ioUtil.test.
1 2 3 4 5 6 7 8 9 10 | # 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. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# 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.
#
# RCS: @(#) $Id: ioUtil.test,v 1.14.2.1 2004/02/07 05:48:03 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest 2
namespace import -force ::tcltest::*
}
::tcltest::testConstraint testopenfilechannelproc \
|
| ︙ | ︙ | |||
187 188 189 190 191 192 193 |
} {{"TestAccessProc1": could not be deleteed} {"TestAccessProc2": could not be deleteed} {"TestAccessProc3": could not be deleteed}}
# Some of the following tests require a writable current directory
set oldpwd [pwd]
cd [temporaryDirectory]
test ioUtil-3.1 {TclOpenFileChannel: Check that none of the test procs are there.} {testopenfilechannelproc} {
| | | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
} {{"TestAccessProc1": could not be deleteed} {"TestAccessProc2": could not be deleteed} {"TestAccessProc3": could not be deleteed}}
# Some of the following tests require a writable current directory
set oldpwd [pwd]
cd [temporaryDirectory]
test ioUtil-3.1 {TclOpenFileChannel: Check that none of the test procs are there.} {testopenfilechannelproc} {
catch {file delete -force {expand}[glob *testOpenFileChannel*]}
catch {file exists testOpenFileChannel1%.fil} err1
catch {file exists testOpenFileChannel2%.fil} err2
catch {file exists testOpenFileChannel3%.fil} err3
catch {file exists __testOpenFileChannel1%__.fil} err4
catch {file exists __testOpenFileChannel2%__.fil} err5
catch {file exists __testOpenFileChannel3%__.fil} err6
list $err1 $err2 $err3 $err4 $err5 $err6
|
| ︙ | ︙ |
Changes to tests/iogt.test.
1 2 3 4 5 6 7 8 9 10 11 12 | # -*- tcl -*- # Commands covered: transform, and stacking in general # # This file contains a collection of tests for Giot # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # Copyright (c) 2000 Ajuba Solutions. # Copyright (c) 2000 Andreas Kupries. # All rights reserved. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# -*- tcl -*-
# Commands covered: transform, and stacking in general
#
# This file contains a collection of tests for Giot
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# Copyright (c) 2000 Ajuba Solutions.
# Copyright (c) 2000 Andreas Kupries.
# All rights reserved.
#
# RCS: @(#) $Id: iogt.test,v 1.7.4.1 2004/02/07 05:48:03 dgp Exp $
if {[catch {package require tcltest 2.1}]} {
puts stderr "Skipping tests in [info script]. tcltest 2.1 required."
return
}
namespace eval ::tcl::test::iogt {
|
| ︙ | ︙ | |||
143 144 145 146 147 148 149 |
# transmission, then hand over to the test script.
# this has to start real transmission via 'flush'.
# The server is stopped after completion of the test.
# fixed port, not so good. lets hope for the best, for now.
set port 4000
| | | | 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# transmission, then hand over to the test script.
# this has to start real transmission via 'flush'.
# The server is stopped after completion of the test.
# fixed port, not so good. lets hope for the best, for now.
set port 4000
exec tclsh __echo_srv__.tcl \
$port $fdelay $idelay {expand}$blocks >@stdout &
after 500
#puts stdout "> $port" ; flush stdout
set sk [socket localhost $port]
fconfigure $sk \
|
| ︙ | ︙ |
Changes to tests/lindex.test.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | # Copyright (c) 1994 Sun Microsystems, Inc. # Copyright (c) 1998-1999 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. # | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 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.
#
# RCS: @(#) $Id: lindex.test,v 1.10.4.1 2004/02/07 05:48:03 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
namespace import -force ::tcltest::*
}
set minus -
testConstraint testevalex [llength [info commands testevalex]]
# Tests of Tcl_LindexObjCmd, NOT COMPILED
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} testevalex {
set 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} testevalex {
set x { 1 }
list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {b b}
test lindex-2.3 {multiple indices in list} testevalex {
set x {1 2}
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} testevalex {
set x \{
list [catch { testevalex {lindex {a b c} $x} } result] $result
} {1 bad\ index\ \"\{\":\ must\ be\ integer\ or\ end?-integer?}
# Indices that are integers or convertible to integers
test lindex-3.1 {integer -1} testevalex {
set x ${minus}1
list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {{} {}}
test lindex-3.2 {integer 0} testevalex {
set x [string range 00 0 0]
list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {a a}
test lindex-3.3 {integer 2} testevalex {
set x [string range 22 0 0]
list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {c c}
test lindex-3.4 {integer 3} testevalex {
set x [string range 33 0 0]
list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {{} {}}
test lindex-3.5 {bad octal} testevalex {
set x 08
list [catch { testevalex {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} testevalex {
set x -09
list [catch { testevalex {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.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]
} {2147483646 {} 2147483647 2147483648}
# Indices relative to end
test lindex-4.1 {index = end} testevalex {
set x end
list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {c c}
test lindex-4.2 {index = end--1} testevalex {
set x end--1
list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {{} {}}
test lindex-4.3 {index = end-0} testevalex {
set x end-0
list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {c c}
test lindex-4.4 {index = end-2} testevalex {
set x end-2
list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {a a}
test lindex-4.5 {index = end-3} testevalex {
set x end-3
list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {{} {}}
test lindex-4.6 {bad octal} testevalex {
set x end-08
list [catch { testevalex {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} testevalex {
set x end--09
list [catch { testevalex {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} testevalex {
set x end-0a2
list [catch { testevalex {lindex {a b c} $x} } result] $result
} "1 {bad index \"end-0a2\": must be integer or end?-integer?}"
test lindex-4.9 {incomplete end} testevalex {
set x en
list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {c c}
test lindex-4.10 {incomplete end-} testevalex {
set x end-
list [catch { testevalex {lindex {a b c} $x} } result] $result
} "1 {bad index \"end-\": must be 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 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} testevalex {
testevalex {lindex {{{a b} {c d}} {{e f} {g h}}} 1 0 1}
} f
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} 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} 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} testevalex {
testevalex {lindex {a "b c" d} 1}
} {b c}
test lindex-7.2 {quoted elements} testevalex {
testevalex {lindex {"{}" b c} 0}
} {{}}
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} testevalex {
set x 0
testevalex {lindex $x $x}
} {0}
test lindex-8.2 {data reuse} testevalex {
set a 0
testevalex {lindex $a $a $a}
} 0
test lindex-8.3 {data reuse} testevalex {
set a 1
testevalex {lindex $a $a $a}
} {}
test lindex-8.4 {data reuse} testevalex {
set x [list 0 0]
testevalex {lindex $x $x}
} {0}
test lindex-8.5 {data reuse} testevalex {
set x 0
testevalex {lindex $x [list $x $x]}
} {0}
test lindex-8.6 {data reuse} testevalex {
set x [list 1 1]
testevalex {lindex $x $x}
} {}
test lindex-8.7 {data reuse} testevalex {
set x 1
testevalex {lindex $x [list $x $x]}
} {}
#----------------------------------------------------------------------
# Compilation tests for lindex
test lindex-9.1 {wrong # args} {
|
| ︙ | ︙ | |||
465 466 467 468 469 470 471 |
set x 1
catch {
lindex $x [list $x $x]
} result
set result
} {}
| < | 465 466 467 468 469 470 471 472 473 474 475 476 |
set x 1
catch {
lindex $x [list $x $x]
} result
set result
} {}
catch { unset minus }
# cleanup
::tcltest::cleanupTests
return
|
Changes to tests/lset.test.
| ︙ | ︙ | |||
18 19 20 21 22 23 24 |
namespace import -force ::tcltest::*
}
proc failTrace {name1 name2 op} {
error "trace failed"
}
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | | | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | | | | | | | | | | | | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 |
namespace import -force ::tcltest::*
}
proc failTrace {name1 name2 op} {
error "trace failed"
}
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} 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} 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} testevalex {
set x {0 1 2}
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} testevalex {
set x {0 1 2}
list [catch {
testevalex {lset x {{bad}1} 3}
} msg] $msg
} "1 {bad index \"{bad}1\": must be integer or end?-integer?}"
test lset-3.1 {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1 2}
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} testevalex {
set x {0 1}
set y $x
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} testevalex {
set x {0 1}
set y $x
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} testevalex {
set x {0 1 2}
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} testevalex {
set x {0 1}
set y $x
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} testevalex {
set x {0 1}
set y $x
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} testevalex {
set a "x \{"
list [catch {
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} testevalex {
set a {x y z}
list [catch {
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} testevalex {
set a {x y z}
list [catch {
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} testevalex {
set a {x y z}
list [catch {
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} testevalex {
set a {x y z}
list [catch {
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} testevalex {
set a {x y z}
list [catch {
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} testevalex {
set a "x \{"
list [catch {
testevalex {lset a 0 y}
} msg] $msg
} {1 {unmatched open brace in list}}
test lset-4.8 {lset, not compiled, 3 args, bad index} testevalex {
set a {x y z}
list [catch {
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} testevalex {
set a {x y z}
list [catch {
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} testevalex {
set a {x y z}
list [catch {
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} testevalex {
set a {x y z}
list [catch {
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} testevalex {
set a {x y z}
list [catch {
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} testevalex {
list [catch {
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} testevalex {
list [catch {
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} testevalex {
set a {x y z}
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} testevalex {
set a {x y z}
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} testevalex {
set a {x y z}
list [testevalex {lset a 2 a}] $a
} {{x y a} {x y a}}
test lset-6.4 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
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} testevalex {
set a {x y z}
list [testevalex {lset a end a}] $a
} {{x y a} {x y a}}
test lset-6.6 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
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} testevalex {
set a {x y z}
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} testevalex {
set a {x y z}
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} testevalex {
set a {x y z}
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} testevalex {
set a {x y z}
list [testevalex {lset a [list end-2] a}] $a
} {{a y z} {a y z}}
test lset-7.1 {lset, not compiled, data sharing} testevalex {
set a 0
list [testevalex {lset a $a {gag me}}] $a
} {{{gag me}} {{gag me}}}
test lset-7.2 {lset, not compiled, data sharing} testevalex {
set a [list 0]
list [testevalex {lset a $a {gag me}}] $a
} {{{gag me}} {{gag me}}}
test lset-7.3 {lset, not compiled, data sharing} testevalex {
set a {x y}
list [testevalex {lset a 0 $a}] $a
} {{{x y} y} {{x y} y}}
test lset-7.4 {lset, not compiled, data sharing} testevalex {
set a {x y}
list [testevalex {lset a [list 0] $a}] $a
} {{{x y} y} {{x y} y}}
test lset-7.5 {lset, not compiled, data sharing} testevalex {
set n 0
set a {x y}
list [testevalex {lset a $n $n}] $a $n
} {{0 y} {0 y} 0}
test lset-7.6 {lset, not compiled, data sharing} testevalex {
set n [list 0]
set a {x y}
list [testevalex {lset a $n $n}] $a $n
} {{0 y} {0 y} 0}
test lset-7.7 {lset, not compiled, data sharing} testevalex {
set n 0
set a [list $n $n]
list [testevalex {lset a $n 1}] $a $n
} {{1 0} {1 0} 0}
test lset-7.8 {lset, not compiled, data sharing} testevalex {
set n [list 0]
set a [list $n $n]
list [testevalex {lset a $n 1}] $a $n
} {{1 0} {1 0} 0}
test lset-7.9 {lset, not compiled, data sharing} testevalex {
set a 0
list [testevalex {lset a $a $a}] $a
} {0 0}
test lset-7.10 {lset, not compiled, data sharing} testevalex {
set a [list 0]
list [testevalex {lset a $a $a}] $a
} {0 0}
test lset-8.1 {lset, not compiled, malformed sublist} testevalex {
set a [list "a \{" b]
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} testevalex {
set a [list "a \{" b]
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} testevalex {
set a {{b c} {d e}}
list [catch {testevalex {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} testevalex {
set a {{b c} {d e}}
list [catch {testevalex {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} testevalex {
set a {{b c} {d e} {f g}}
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} testevalex {
set a {{b c} {d e} {f g}}
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} testevalex {
set a {{b c} {d e} {f g}}
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} testevalex {
set a {{b c} {d e} {f g}}
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} testevalex {
set a {{b c} {d e} {f g}}
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} testevalex {
set a {{b c} {d e} {f g}}
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} testevalex {
set a {{b c} {d e} {f g}}
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} testevalex {
set a {{b c} {d e} {f g}}
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} testevalex {
set a x
list [testevalex {lset a y}] $a
} {y y}
test lset-9.2 {lset, not compiled, entire variable} testevalex {
set a x
list [testevalex {lset a {} y}] $a
} {y y}
test lset-10.1 {lset, not compiled, shared data} testevalex {
set row {p q}
set a [list $row $row]
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} testevalex {
set row {p q}
set a [list $row $row]
list [testevalex {lset a {0 0} x}] $a
} {{{x q} {p q}} {{x q} {p q}}}
test lset-11.1 {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
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} testevalex {
set a {{b c} {d e}}
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} testevalex {
set a {{b c} {d e}}
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} testevalex {
set a {{b c} {d e}}
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} testevalex {
set a {{b c} {d e}}
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} testevalex {
set a {{b c} {d e}}
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} testevalex {
set a {{b c} {d e}}
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} testevalex {
set a {{b c} {d e}}
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} 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 } {
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} testevalex {
set a 0
list [testevalex {lset a $a $a $a $a {gag me}}] $a
} {{{{{{gag me}}}}} {{{{{gag me}}}}}}
test lset-13.1 {lset, not compiled, shimmering hell} testevalex {
set a [list 0]
list [testevalex {lset a $a $a $a $a {gag me}}] $a
} {{{{{{gag me}}}}} {{{{{gag me}}}}}}
test lset-13.2 {lset, not compiled, shimmering hell} testevalex {
set a [list 0 0 0 0]
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?} testevalex {
set a { { 1 2 } { 3 4 } }
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?} testevalex {
set a { { 1 2 } { 3 4 } }
catch { testevalex {lset a 1 5 5} }
list $a [lindex $a 1]
} "{ { 1 2 } { 3 4 } } { 3 4 }"
catch {unset noRead}
catch {unset noWrite}
catch {rename failTrace {}}
catch {unset ::x}
|
| ︙ | ︙ |
Changes to tests/misc.test.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | # Copyright (c) 1992-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. # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# Copyright (c) 1992-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.
#
# RCS: @(#) $Id: misc.test,v 1.6.4.1 2004/02/07 05:48:03 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
namespace import -force ::tcltest::*
}
test misc-1.1 {error in variable ref. in command in array reference} {
|
| ︙ | ︙ | |||
61 62 63 64 65 66 67 68 69 70 71 |
# 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)
invoked from within
"tstProc"}]
# cleanup
::tcltest::cleanupTests
return
| > > > > < < < < < < < < < < < < | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# 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)
invoked from within
"tstProc"}]
for {set i 1} {$i<300} {incr i} {
test misc-2.$i {hash table with sys-alloc} "testhashsystemhash $i" OK
}
# cleanup
::tcltest::cleanupTests
return
|
Changes to tests/msgcat.test.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # Note that after running these tests, entries will be left behind in the # message catalogs for locales foo, foo_BAR, and foo_BAR_baz. # | | | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# Note that after running these tests, entries will be left behind in the
# message catalogs for locales foo, foo_BAR, and foo_BAR_baz.
#
# RCS: @(#) $Id: msgcat.test,v 1.12.2.1 2004/02/07 05:48:03 dgp Exp $
package require Tcl 8.2
if {[catch {package require tcltest 2}]} {
puts stderr "Skipping tests in [info script]. tcltest 2 required."
return
}
if {[catch {package require msgcat 1.4}]} {
puts stderr "Skipping tests in [info script]. No msgcat 1.4 found to test."
return
}
namespace eval ::msgcat::test {
namespace import ::msgcat::*
namespace import ::tcltest::test
namespace import ::tcltest::cleanupTests
|
| ︙ | ︙ | |||
107 108 109 110 111 112 113 |
test msgcat-1.5 {mcpreferences, single element} -setup {
variable locale [mclocale]
mclocale en
} -cleanup {
mclocale $locale
} -body {
mcpreferences
| | | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
test msgcat-1.5 {mcpreferences, single element} -setup {
variable locale [mclocale]
mclocale en
} -cleanup {
mclocale $locale
} -body {
mcpreferences
} -result {en {}}
test msgcat-1.6 {mclocale set, two elements} -setup {
variable locale [mclocale]
} -cleanup {
mclocale $locale
} -body {
mclocale en_US
|
| ︙ | ︙ | |||
133 134 135 136 137 138 139 |
test msgcat-1.8 {mcpreferences, two elements} -setup {
variable locale [mclocale]
mclocale en_US
} -cleanup {
mclocale $locale
} -body {
mcpreferences
| | | 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
test msgcat-1.8 {mcpreferences, two elements} -setup {
variable locale [mclocale]
mclocale en_US
} -cleanup {
mclocale $locale
} -body {
mcpreferences
} -result {en_us en {}}
test msgcat-1.9 {mclocale set, three elements} -setup {
variable locale [mclocale]
} -cleanup {
mclocale $locale
} -body {
mclocale en_US_funky
|
| ︙ | ︙ | |||
159 160 161 162 163 164 165 |
test msgcat-1.11 {mcpreferences, three elements} -setup {
variable locale [mclocale]
mclocale en_US_funky
} -cleanup {
mclocale $locale
} -body {
mcpreferences
| | | 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
test msgcat-1.11 {mcpreferences, three elements} -setup {
variable locale [mclocale]
mclocale en_US_funky
} -cleanup {
mclocale $locale
} -body {
mcpreferences
} -result {en_us_funky en_us en {}}
# Tests msgcat-2.*: [mcset], [mcmset], namespace partitioning
test msgcat-2.1 {mcset, global scope} {
namespace eval :: ::msgcat::mcset foo_BAR text1 text2
} {text2}
|
| ︙ | ︙ | |||
242 243 244 245 246 247 248 |
# Tests msgcat-3.*: [mcset], [mc], catalog "inheritance"
#
# Test mcset and mc, ensuring that more specific locales
# (e.g. en_UK) will search less specific locales
# (e.g. en) for translation strings.
#
| | | > | | | > | | > > | | > > > > | 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
# Tests msgcat-3.*: [mcset], [mc], catalog "inheritance"
#
# Test mcset and mc, ensuring that more specific locales
# (e.g. en_UK) will search less specific locales
# (e.g. en) for translation strings.
#
# Do this for the 15 permutations of
# locales: {foo foo_BAR foo_BAR_baz}
# 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
# ov2 should be resolved in foo, foo_BAR
# ov2 should resolve to foo_BAR in foo_BAR_baz
# ov1 should be resolved in foo
# ov1 should resolve to foo in foo_BAR, foo_BAR_baz
# ov4 should be resolved in none, and call mcunknown
#
variable count 2
variable result
array set result {
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 {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
mcset foo_BAR ov2 ov2_foo_BAR
mcset foo_BAR ov3 ov3_foo_BAR
mcset foo_BAR_baz ov3 ov3_foo_BAR_baz
variable locale [mclocale]
|
| ︙ | ︙ | |||
360 361 362 363 364 365 366 |
rename SavedMcunknown ::msgcat::mcunknown
} -body {
mc unk2
} -result unknown:foo:unk2:[info level]
# Tests msgcat-5.*: [mcload]
| | | | > > | > > | | | | | | | > > > > > > > > > > > > > > | | < > > > | > > | 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 |
rename SavedMcunknown ::msgcat::mcunknown
} -body {
mc unk2
} -result unknown:foo:unk2:[info level]
# Tests msgcat-5.*: [mcload]
variable locales {{} foo foo_BAR foo_BAR_baz}
set msgdir [makeDirectory msgdir]
foreach loc $locales {
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} {
test msgcat-5.$count {mcload} -setup {
variable locale [mclocale]
mclocale $loc
} -cleanup {
mclocale $locale
} -body {
mcload $msgdir
} -result [expr { $count+1 }]
incr count
}
# Even though foo_BAR_notexist does not exist,
# 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 $msgdir
} -result 3
test msgcat-5.5 {mcload} -setup {
variable locale [mclocale]
mclocale no_FI_notexist
} -cleanup {
mclocale $locale
} -body {
mcload $msgdir
} -result 1
test msgcat-5.6 {mcload} -setup {
variable locale [mclocale]
mclocale foo
mcload $msgdir
} -cleanup {
mclocale $locale
} -body {
mc abc
} -result abc-foo
test msgcat-5.7 {mcload} -setup {
variable locale [mclocale]
mclocale foo_BAR
mcload $msgdir
} -cleanup {
mclocale $locale
} -body {
mc abc
} -result abc-foo_BAR
test msgcat-5.8 {mcload} -setup {
variable locale [mclocale]
mclocale foo_BAR_baz
mcload $msgdir
} -cleanup {
mclocale $locale
} -body {
mc abc
} -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 def
} -result unknown:no_fi_notexist:def
foreach loc $locales {
if { $loc eq {} } {
set msg ROOT
} else {
set msg [string tolower $loc]
}
removeFile $msg.msg msgdir
}
removeDirectory msgdir
# Tests msgcat-6.*: [mcset], [mc] namespace inheritance
#
# Test mcset and mc, ensuring that resolution for messages
# proceeds from the current ns to its parent and so on to the
|
| ︙ | ︙ |
Changes to tests/namespace-old.test.
| ︙ | ︙ | |||
10 11 12 13 14 15 16 | # Copyright (c) 1997 Sun Microsystems, Inc. # Copyright (c) 1997 Lucent Technologies # 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. # | | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1997 Lucent Technologies
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: namespace-old.test,v 1.6.20.1 2004/02/07 05:48:03 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
namespace import -force ::tcltest::*
}
# Clear out any namespaces called test_ns_*
catch {namespace delete {expand}[namespace children :: test_ns_*]}
test namespace-old-1.1 {usage for "namespace" command} {
list [catch {namespace} msg] $msg
} {1 {wrong # args: should be "namespace subcommand ?arg ...?"}}
test namespace-old-1.2 {global namespace's name is "::" or {}} {
list [namespace current] [namespace eval {} {namespace current}]
|
| ︙ | ︙ | |||
247 248 249 250 251 252 253 |
}
list [catch $cmd msg] $msg
} {1 {unknown namespace "ns*" in namespace delete command}}
test namespace-old-4.4 {command "namespace delete" handles multiple args} {
set cmd {
namespace eval test_ns_delete {
| | | | 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
}
list [catch $cmd msg] $msg
} {1 {unknown namespace "ns*" in namespace delete command}}
test namespace-old-4.4 {command "namespace delete" handles multiple args} {
set cmd {
namespace eval test_ns_delete {
namespace delete \
{expand}[namespace children [namespace current] ns?]
}
}
list [catch $cmd msg] $msg [namespace children test_ns_delete]
} {0 {} ::test_ns_delete::another}
# -----------------------------------------------------------------------
# TEST: namespace hierarchy
|
| ︙ | ︙ |
Changes to tests/namespace.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # Functionality covered: this file contains a collection of tests for the # procedures in tclNamesp.c that implement Tcl's basic support for # namespaces. Other namespace-related tests appear in variable.test. # # 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-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. # | | | | 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 |
# Functionality covered: this file contains a collection of tests for the
# procedures in tclNamesp.c that implement Tcl's basic support for
# namespaces. Other namespace-related tests appear in variable.test.
#
# 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-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.
#
# RCS: @(#) $Id: namespace.test,v 1.21.4.2 2004/02/07 05:48:03 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest 2
namespace import -force ::tcltest::*
}
# Clear out any namespaces called test_ns_*
catch {namespace delete {expand}[namespace children :: test_ns_*]}
test namespace-1.1 {TclInitNamespaces, GetNamespaceFromObj, NamespaceChildrenCmd} {
namespace children :: test_ns_*
} {}
catch {unset l}
test namespace-2.1 {Tcl_GetCurrentNamespace} {
|
| ︙ | ︙ | |||
75 76 77 78 79 80 81 |
proc test_ns_1::r {} {
set a 123
}
test_ns_1::r ;# pushes then pop's r's frame
} {123}
test namespace-6.1 {Tcl_CreateNamespace} {
| | | | | 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
proc test_ns_1::r {} {
set a 123
}
test_ns_1::r ;# pushes then pop's r's frame
} {123}
test namespace-6.1 {Tcl_CreateNamespace} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
list [lsort [namespace children :: test_ns_*]] \
[namespace eval test_ns_1 {namespace current}] \
[namespace eval test_ns_2 {namespace current}] \
[namespace eval ::test_ns_3 {namespace current}] \
[namespace eval ::test_ns_4 \
{namespace eval foo {namespace current}}] \
[namespace eval ::test_ns_5 \
{namespace eval ::test_ns_6 {namespace current}}] \
[lsort [namespace children :: test_ns_*]]
} {{} ::test_ns_1 ::test_ns_2 ::test_ns_3 ::test_ns_4::foo ::test_ns_6 {::test_ns_1 ::test_ns_2 ::test_ns_3 ::test_ns_4 ::test_ns_5 ::test_ns_6}}
test namespace-6.2 {Tcl_CreateNamespace, odd number of :'s in name is okay} {
list [namespace eval :::test_ns_1::::foo {namespace current}] \
[namespace eval test_ns_2:::::foo {namespace current}]
} {::test_ns_1::foo ::test_ns_2::foo}
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 {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_1:: {
namespace eval test_ns_2:: {}
namespace eval test_ns_3:: {}
}
lsort [namespace children ::test_ns_1]
} [lsort {::test_ns_1::test_ns_2 ::test_ns_1::test_ns_3}]
test namespace-6.5 {Tcl_CreateNamespace, relative ns names now only looked up in current ns} {
set trigger {
namespace eval test_ns_2 {namespace current}
}
set l {}
lappend l [namespace eval test_ns_1 $trigger]
namespace eval test_ns_1::test_ns_2 {}
lappend l [namespace eval test_ns_1 $trigger]
} {::test_ns_1::test_ns_2 ::test_ns_1::test_ns_2}
test namespace-7.1 {Tcl_DeleteNamespace, active call frames in ns} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {
proc p {} {
namespace delete [namespace current]
return [namespace current]
}
}
list [test_ns_1::p] [catch {test_ns_1::p} msg] $msg
|
| ︙ | ︙ | |||
157 158 159 160 161 162 163 |
}
list [interp eval test_interp {test_ns_2::q}] \
[interp eval test_interp {namespace delete ::}] \
[catch {interp eval test_interp {set a 123}} msg] $msg \
[interp delete test_interp]
} {{::test_ns_1 27} {} 1 {invalid command name "set"} {}}
test namespace-8.2 {TclTeardownNamespace, remove deleted ns from parent} {
| | | | | | | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
}
list [interp eval test_interp {test_ns_2::q}] \
[interp eval test_interp {namespace delete ::}] \
[catch {interp eval test_interp {set a 123}} msg] $msg \
[interp delete test_interp]
} {{::test_ns_1 27} {} 1 {invalid command name "set"} {}}
test namespace-8.2 {TclTeardownNamespace, remove deleted ns from parent} {
catch {namespace delete {expand}[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] \
[namespace delete test_ns_1::test_ns_2] \
[namespace children test_ns_1]
} {::test_ns_1::test_ns_2 {} {}}
test namespace-8.3 {TclTeardownNamespace, delete child namespaces} {
catch {namespace delete {expand}[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] \
[namespace delete test_ns_1::test_ns_2] \
[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 namespace-8.4 {TclTeardownNamespace, cmds imported from deleted ns go away} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_export {
namespace export cmd1 cmd2
proc cmd1 {args} {return "cmd1: $args"}
proc cmd2 {args} {return "cmd2: $args"}
}
namespace eval test_ns_import {
namespace import ::test_ns_export::*
proc p {} {return foo}
}
list [lsort [info commands test_ns_import::*]] \
[namespace delete test_ns_export] \
[info commands test_ns_import::*]
} [list [lsort {::test_ns_import::p ::test_ns_import::cmd1 ::test_ns_import::cmd2}] {} ::test_ns_import::p]
test namespace-9.1 {Tcl_Import, empty import pattern} {
catch {namespace delete {expand}[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} {
list [catch {namespace eval test_ns_import {namespace import fred::x}} msg] $msg
} {1 {unknown namespace in import pattern "fred::x"}}
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 {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_export {
namespace export cmd1
proc cmd1 {args} {return "cmd1: $args"}
proc cmd2 {args} {return "cmd2: $args"}
}
namespace eval test_ns_import {
namespace import ::test_ns_export::*
|
| ︙ | ︙ | |||
223 224 225 226 227 228 229 |
test namespace-9.6 {Tcl_Import, cmd redefinition ok if allowOverwrite!=0} {
namespace eval test_ns_import {
namespace import -force ::test_ns_export::*
cmd1 555
}
} {cmd1: 555}
test namespace-9.7 {Tcl_Import, links are preserved if cmd is redefined} {
| | | | 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
test namespace-9.6 {Tcl_Import, cmd redefinition ok if allowOverwrite!=0} {
namespace eval test_ns_import {
namespace import -force ::test_ns_export::*
cmd1 555
}
} {cmd1: 555}
test namespace-9.7 {Tcl_Import, links are preserved if cmd is redefined} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_export {
namespace export cmd1
proc cmd1 {args} {return "cmd1: $args"}
}
namespace eval test_ns_import {
namespace import -force ::test_ns_export::*
}
list [test_ns_import::cmd1 a b c] \
[test_ns_export::cmd1 d e f] \
[proc test_ns_export::cmd1 {args} {return "new1: $args"}] \
[namespace origin test_ns_import::cmd1] \
[namespace origin test_ns_export::cmd1] \
[test_ns_import::cmd1 g h i] \
[test_ns_export::cmd1 j k l]
} {{cmd1: a b c} {cmd1: d e f} {} ::test_ns_export::cmd1 ::test_ns_export::cmd1 {new1: g h i} {new1: j k l}}
test namespace-10.1 {Tcl_ForgetImport, check for valid namespaces} {
catch {namespace delete {expand}[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} {
namespace eval test_ns_export {
namespace export cmd1
proc cmd1 {args} {return "cmd1: $args"}
proc cmd2 {args} {return "cmd2: $args"}
|
| ︙ | ︙ | |||
267 268 269 270 271 272 273 |
namespace forget ::test_ns_export::cmd1
lappend l [info commands ::test_ns_import::*]
lappend l [catch {cmd1 777} msg] $msg
}
} [list [lsort {::test_ns_import::p ::test_ns_import::cmd1}] ::test_ns_import::p 1 {invalid command name "cmd1"}]
test namespace-11.1 {TclGetOriginalCommand, check if not imported cmd} {
| | | 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
namespace forget ::test_ns_export::cmd1
lappend l [info commands ::test_ns_import::*]
lappend l [catch {cmd1 777} msg] $msg
}
} [list [lsort {::test_ns_import::p ::test_ns_import::cmd1}] ::test_ns_import::p 1 {invalid command name "cmd1"}]
test namespace-11.1 {TclGetOriginalCommand, check if not imported cmd} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_export {
namespace export cmd1
proc cmd1 {args} {return "cmd1: $args"}
}
list [namespace origin set] [namespace origin test_ns_export::cmd1]
} {::set ::test_ns_export::cmd1}
test namespace-11.2 {TclGetOriginalCommand, directly imported cmd} {
|
| ︙ | ︙ | |||
291 292 293 294 295 296 297 |
namespace import ::test_ns_import1::*
proc q {} {return [cmd1 123]}
}
list [test_ns_import2::q] [namespace origin test_ns_import2::cmd1]
} {{cmd1: 123} ::test_ns_export::cmd1}
test namespace-12.1 {InvokeImportedCmd} {
| | | | 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
namespace import ::test_ns_import1::*
proc q {} {return [cmd1 123]}
}
list [test_ns_import2::q] [namespace origin test_ns_import2::cmd1]
} {{cmd1: 123} ::test_ns_export::cmd1}
test namespace-12.1 {InvokeImportedCmd} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_export {
namespace export cmd1
proc cmd1 {args} {namespace current}
}
namespace eval test_ns_import {
namespace import ::test_ns_export::*
}
list [test_ns_import::cmd1]
} {::test_ns_export}
test namespace-13.1 {DeleteImportedCmd, deletes imported cmds} {
namespace eval test_ns_import {
set l {}
lappend l [info commands ::test_ns_import::*]
namespace forget ::test_ns_export::cmd1
lappend l [info commands ::test_ns_import::*]
}
} {::test_ns_import::cmd1 {}}
test namespace-14.1 {TclGetNamespaceForQualName, absolute names} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
variable v 10
namespace eval test_ns_1::test_ns_2 {
variable v 20
}
namespace eval test_ns_2 {
variable v 30
}
|
| ︙ | ︙ | |||
390 391 392 393 394 395 396 |
catch {rename test_ns_1::test_ns_2:: {}}
set l {}
lappend l [catch {test_ns_1::test_ns_2:: hello} msg] $msg
proc test_ns_1::test_ns_2:: {args} {return "\{\}: $args"}
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} {
| | | | | 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 |
catch {rename test_ns_1::test_ns_2:: {}}
set l {}
lappend l [catch {test_ns_1::test_ns_2:: hello} msg] $msg
proc test_ns_1::test_ns_2:: {args} {return "\{\}: $args"}
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 {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {
variable {}
set test_ns_1::(x) y
}
set test_ns_1::(x)
} y
test namespace-14.13 {TclGetNamespaceForQualName, namespace other than global ns can't have empty name} {
catch {namespace delete {expand}[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 {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_delete {
namespace eval test_ns_delete2 {}
proc cmd {args} {namespace current}
}
list [namespace delete ::test_ns_delete::test_ns_delete2] \
[namespace children ::test_ns_delete]
} {{} {}}
|
| ︙ | ︙ | |||
430 431 432 433 434 435 436 |
namespace eval test_ns_delete2 {}
namespace eval test_ns_delete {
list [catch {namespace delete test_ns_delete2} msg] $msg
}
} {1 {unknown namespace "test_ns_delete2" in namespace delete command}}
test namespace-16.1 {Tcl_FindCommand, absolute name found} {
| | | 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 |
namespace eval test_ns_delete2 {}
namespace eval test_ns_delete {
list [catch {namespace delete test_ns_delete2} msg] $msg
}
} {1 {unknown namespace "test_ns_delete2" in namespace delete command}}
test namespace-16.1 {Tcl_FindCommand, absolute name found} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {
proc cmd {args} {return "[namespace current]::cmd: $args"}
variable v "::test_ns_1::cmd"
eval $v one
}
} {::test_ns_1::cmd: one}
test namespace-16.2 {Tcl_FindCommand, absolute name found} {
|
| ︙ | ︙ | |||
498 499 500 501 502 503 504 |
namespace eval test_ns_1 {
list [catch {cmd3 a b c} msg] $msg
}
} {1 {invalid command name "cmd3"}}
catch {unset x}
test namespace-17.1 {Tcl_FindNamespaceVar, absolute name found} {
| | | 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 |
namespace eval test_ns_1 {
list [catch {cmd3 a b c} msg] $msg
}
} {1 {invalid command name "cmd3"}}
catch {unset x}
test namespace-17.1 {Tcl_FindNamespaceVar, absolute name found} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
set x 314159
namespace eval test_ns_1 {
set ::x
}
} {314159}
test namespace-17.2 {Tcl_FindNamespaceVar, absolute name found} {
namespace eval test_ns_1 {
|
| ︙ | ︙ | |||
561 562 563 564 565 566 567 |
set test_ns_1::a
} {hello}
catch {unset x}
catch {unset l}
catch {rename foo {}}
test namespace-18.1 {TclResetShadowedCmdRefs, one-level check for command shadowing} {
| | | 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 |
set test_ns_1::a
} {hello}
catch {unset x}
catch {unset l}
catch {rename foo {}}
test namespace-18.1 {TclResetShadowedCmdRefs, one-level check for command shadowing} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
proc foo {} {return "global foo"}
namespace eval test_ns_1 {
proc trigger {} {
return [foo]
}
}
set l ""
|
| ︙ | ︙ | |||
602 603 604 605 606 607 608 |
lappend l [test_ns_1::trigger]
set l
} {{foo in ::test_ns_2} {foo in ::test_ns_1::test_ns_2}}
catch {unset l}
catch {rename foo {}}
test namespace-19.1 {GetNamespaceFromObj, global name found} {
| | | 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 |
lappend l [test_ns_1::trigger]
set l
} {{foo in ::test_ns_2} {foo in ::test_ns_1::test_ns_2}}
catch {unset l}
catch {rename foo {}}
test namespace-19.1 {GetNamespaceFromObj, global name found} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_1::test_ns_2 {}
namespace children ::test_ns_1
} {::test_ns_1::test_ns_2}
test namespace-19.2 {GetNamespaceFromObj, relative name found} {
namespace eval test_ns_1 {
namespace children test_ns_2
}
|
| ︙ | ︙ | |||
632 633 634 635 636 637 638 |
namespace delete test_ns_1::test_ns_2
namespace eval test_ns_1::test_ns_2::test_ns_3 {}
lappend l [test_ns_1::foo]
set l
} {{} ::test_ns_1::test_ns_2::test_ns_3}
test namespace-20.1 {Tcl_NamespaceObjCmd, bad subcommand} {
| | | | 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 |
namespace delete test_ns_1::test_ns_2
namespace eval test_ns_1::test_ns_2::test_ns_3 {}
lappend l [test_ns_1::foo]
set l
} {{} ::test_ns_1::test_ns_2::test_ns_3}
test namespace-20.1 {Tcl_NamespaceObjCmd, bad subcommand} {
catch {namespace delete {expand}[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, ensemble, eval, exists, export, forget, import, inscope, origin, parent, qualifiers, tail, or which}}
test namespace-20.3 {Tcl_NamespaceObjCmd, abbreviations are okay} {
namespace ch :: test_ns_*
} {}
test namespace-21.1 {NamespaceChildrenCmd, no args} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_1::test_ns_2 {}
expr {[string first ::test_ns_1 [namespace children]] != -1}
} {1}
test namespace-21.2 {NamespaceChildrenCmd, no args} {
namespace eval test_ns_1 {
namespace children
}
|
| ︙ | ︙ | |||
675 676 677 678 679 680 681 |
} {::test_ns_1::test_ns_foo}
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-22.1 {NamespaceCodeCmd, bad args} {
| | | 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 |
} {::test_ns_1::test_ns_foo}
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-22.1 {NamespaceCodeCmd, bad args} {
catch {namespace delete {expand}[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"}}
test namespace-22.2 {NamespaceCodeCmd, arg is already scoped value} {
namespace eval test_ns_1 {
proc cmd {} {return "test_ns_1::cmd"}
}
|
| ︙ | ︙ | |||
709 710 711 712 713 714 715 |
}
namespace eval test_ns_2 [namespace eval test_ns_1 {
namespace code {set v}
}]
} {42}
test namespace-23.1 {NamespaceCurrentCmd, bad args} {
| | | | | 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 |
}
namespace eval test_ns_2 [namespace eval test_ns_1 {
namespace code {set v}
}]
} {42}
test namespace-23.1 {NamespaceCurrentCmd, bad args} {
catch {namespace delete {expand}[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"}}
test namespace-23.2 {NamespaceCurrentCmd, at global level} {
namespace current
} {::}
test namespace-23.3 {NamespaceCurrentCmd, in nested ns} {
namespace eval test_ns_1::test_ns_2 {
namespace current
}
} {::test_ns_1::test_ns_2}
test namespace-24.1 {NamespaceDeleteCmd, no args} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
namespace delete
} {}
test namespace-24.2 {NamespaceDeleteCmd, one arg} {
namespace eval test_ns_1::test_ns_2 {}
namespace delete ::test_ns_1
} {}
test namespace-24.3 {NamespaceDeleteCmd, two args} {
namespace eval test_ns_1::test_ns_2 {}
list [namespace delete ::test_ns_1::test_ns_2] [namespace delete ::test_ns_1]
} {{} {}}
test namespace-24.4 {NamespaceDeleteCmd, unknown ns} {
list [catch {namespace delete ::test_ns_foo} msg] $msg
} {1 {unknown namespace "::test_ns_foo" in namespace delete command}}
test namespace-25.1 {NamespaceEvalCmd, bad args} {
catch {namespace delete {expand}[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, ensemble, eval, exists, export, forget, import, inscope, origin, parent, qualifiers, tail, or which}}
catch {unset v}
test namespace-25.3 {NamespaceEvalCmd, new namespace} {
|
| ︙ | ︙ | |||
777 778 779 780 781 782 783 |
"xxxx"
(in namespace eval "::test_ns_1" script line 1)
invoked from within
"namespace eval test_ns_1 {xxxx}"}}
catch {unset v}
test namespace-26.1 {NamespaceExportCmd, no args and new ns} {
| | | 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 |
"xxxx"
(in namespace eval "::test_ns_1" script line 1)
invoked from within
"namespace eval test_ns_1 {xxxx}"}}
catch {unset v}
test namespace-26.1 {NamespaceExportCmd, no args and new ns} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
namespace export
} {}
test namespace-26.2 {NamespaceExportCmd, just -clear arg} {
namespace export -clear
} {}
test namespace-26.3 {NamespaceExportCmd, pattern can't specify a namespace} {
namespace eval test_ns_1 {
|
| ︙ | ︙ | |||
826 827 828 829 830 831 832 |
namespace eval test_ns_2 {
namespace import ::test_ns_1::*
}
list [lsort [info commands test_ns_2::*]] [test_ns_2::cmd4 hello]
} [list [lsort {::test_ns_2::cmd4 ::test_ns_2::cmd1 ::test_ns_2::cmd3}] {cmd4: hello}]
test namespace-27.1 {NamespaceForgetCmd, no args} {
| | | | | 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 |
namespace eval test_ns_2 {
namespace import ::test_ns_1::*
}
list [lsort [info commands test_ns_2::*]] [test_ns_2::cmd4 hello]
} [list [lsort {::test_ns_2::cmd4 ::test_ns_2::cmd1 ::test_ns_2::cmd3}] {cmd4: hello}]
test namespace-27.1 {NamespaceForgetCmd, no args} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
namespace forget
} {}
test namespace-27.2 {NamespaceForgetCmd, args must be valid namespaces} {
list [catch {namespace forget ::test_ns_1::xxx} msg] $msg
} {1 {unknown namespace in namespace forget pattern "::test_ns_1::xxx"}}
test namespace-27.3 {NamespaceForgetCmd, arg is forgotten} {
namespace eval test_ns_1 {
namespace export cmd*
proc cmd1 {args} {return "cmd1: $args"}
proc cmd2 {args} {return "cmd2: $args"}
}
namespace eval test_ns_2 {
namespace import ::test_ns_1::*
namespace forget ::test_ns_1::cmd1
}
info commands ::test_ns_2::*
} {::test_ns_2::cmd2}
test namespace-28.1 {NamespaceImportCmd, no args} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
namespace import
} {}
test namespace-28.2 {NamespaceImportCmd, no args and just "-force"} {
namespace import -force
} {}
test namespace-28.3 {NamespaceImportCmd, arg is imported} {
namespace eval test_ns_1 {
namespace export cmd2
proc cmd1 {args} {return "cmd1: $args"}
proc cmd2 {args} {return "cmd2: $args"}
}
namespace eval test_ns_2 {
namespace import ::test_ns_1::*
namespace forget ::test_ns_1::cmd1
}
info commands test_ns_2::*
} {::test_ns_2::cmd2}
test namespace-29.1 {NamespaceInscopeCmd, bad args} {
catch {namespace delete {expand}[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
|
| ︙ | ︙ | |||
891 892 893 894 895 896 897 |
} {::test_ns_1::cmd: v=747, args=}
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-30.1 {NamespaceOriginCmd, bad args} {
| | | 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 |
} {::test_ns_1::cmd: v=747, args=}
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-30.1 {NamespaceOriginCmd, bad args} {
catch {namespace delete {expand}[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} {
list [catch {namespace origin x y} msg] $msg
} {1 {wrong # args: should be "namespace origin name"}}
test namespace-30.3 {NamespaceOriginCmd, command not found} {
list [catch {namespace origin fred} msg] $msg
|
| ︙ | ︙ | |||
924 925 926 927 928 929 930 |
[namespace origin p] \
[namespace origin cmd1] \
[namespace origin ::test_ns_2::cmd2]
}
} {::foreach ::test_ns_2::p ::test_ns_1::cmd1 ::test_ns_1::cmd2}
test namespace-31.1 {NamespaceParentCmd, bad args} {
| | | | 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 |
[namespace origin p] \
[namespace origin cmd1] \
[namespace origin ::test_ns_2::cmd2]
}
} {::foreach ::test_ns_2::p ::test_ns_1::cmd1 ::test_ns_1::cmd2}
test namespace-31.1 {NamespaceParentCmd, bad args} {
catch {namespace delete {expand}[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} {
namespace parent
} {}
test namespace-31.3 {NamespaceParentCmd, namespace specified} {
namespace eval test_ns_1 {
namespace eval test_ns_2 {
namespace eval test_ns_3 {}
}
}
list [namespace parent ::] \
[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-32.1 {NamespaceQualifiersCmd, bad args} {
catch {namespace delete {expand}[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} {
list [catch {namespace qualifiers x y} msg] $msg
} {1 {wrong # args: should be "namespace qualifiers string"}}
test namespace-32.3 {NamespaceQualifiersCmd, simple name} {
namespace qualifiers foo
|
| ︙ | ︙ | |||
971 972 973 974 975 976 977 |
namespace qualifiers :::::
} {}
test namespace-32.8 {NamespaceQualifiersCmd, odd number of :s} {
namespace qualifiers foo:::
} {foo}
test namespace-33.1 {NamespaceTailCmd, bad args} {
| | | 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 |
namespace qualifiers :::::
} {}
test namespace-32.8 {NamespaceQualifiersCmd, odd number of :s} {
namespace qualifiers foo:::
} {foo}
test namespace-33.1 {NamespaceTailCmd, bad args} {
catch {namespace delete {expand}[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} {
list [catch {namespace tail x y} msg] $msg
} {1 {wrong # args: should be "namespace tail string"}}
test namespace-33.3 {NamespaceTailCmd, simple name} {
namespace tail foo
|
| ︙ | ︙ | |||
997 998 999 1000 1001 1002 1003 |
namespace tail :::::
} {}
test namespace-33.8 {NamespaceTailCmd, odd number of :s} {
namespace tail foo:::
} {}
test namespace-34.1 {NamespaceWhichCmd, bad args} {
| | | 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 |
namespace tail :::::
} {}
test namespace-33.8 {NamespaceTailCmd, odd number of :s} {
namespace tail foo:::
} {}
test namespace-34.1 {NamespaceWhichCmd, bad args} {
catch {namespace delete {expand}[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
|
| ︙ | ︙ | |||
1050 1051 1052 1053 1054 1055 1056 |
[namespace which -variable v3] \
[namespace which -variable ::test_ns_2::v2] \
[catch {namespace which -variable ::test_ns_2::noSuchVar} msg] $msg
}
} {::env ::test_ns_3::v3 ::test_ns_2::v2 0 {}}
test namespace-35.1 {FreeNsNameInternalRep, resulting ref count > 0} {
| | | 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 |
[namespace which -variable v3] \
[namespace which -variable ::test_ns_2::v2] \
[catch {namespace which -variable ::test_ns_2::noSuchVar} msg] $msg
}
} {::env ::test_ns_3::v3 ::test_ns_2::v2 0 {}}
test namespace-35.1 {FreeNsNameInternalRep, resulting ref count > 0} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {
proc p {} {
namespace delete [namespace current]
return [namespace current]
}
}
test_ns_1::p
|
| ︙ | ︙ | |||
1073 1074 1075 1076 1077 1078 1079 |
[namespace delete test_ns_1] \
[catch {test_ns_1::q} msg] $msg
} {::test_ns_1 {} 1 {invalid command name "test_ns_1::q"}}
catch {unset x}
catch {unset y}
test namespace-36.1 {DupNsNameInternalRep} {
| | | | | | 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 |
[namespace delete test_ns_1] \
[catch {test_ns_1::q} msg] $msg
} {::test_ns_1 {} 1 {invalid command name "test_ns_1::q"}}
catch {unset x}
catch {unset y}
test namespace-36.1 {DupNsNameInternalRep} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {}
set x "::test_ns_1"
list [namespace parent $x] [set y $x] [namespace parent $y]
} {:: ::test_ns_1 ::}
catch {unset x}
catch {unset y}
test namespace-37.1 {SetNsNameFromAny, ns name found} {
catch {namespace delete {expand}[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} {
namespace eval test_ns_1 {
list [catch {namespace children ::test_ns_1::test_ns_foo} msg] $msg
}
} {1 {unknown namespace "::test_ns_1::test_ns_foo" in namespace children command}}
test namespace-38.1 {UpdateStringOfNsName} {
catch {namespace delete {expand}[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 {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval ::test_ns_z::test_me { variable foo }
list [namespace exists ::] \
[namespace exists ::bogus_namespace] \
[namespace exists ::test_ns_z] \
[namespace exists test_ns_z] \
[namespace exists ::test_ns_z::foo] \
[namespace exists ::test_ns_z::test_me] \
|
| ︙ | ︙ | |||
1305 1306 1307 1308 1309 1310 1311 |
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}
}
}
| | < | | 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 |
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 {
|
| ︙ | ︙ | |||
1331 1332 1333 1334 1335 1336 1337 |
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}
}
}
| | < | | < | | 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 |
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 {
|
| ︙ | ︙ | |||
1632 1633 1634 1635 1636 1637 1638 |
"foo bar"}}
# cleanup
catch {rename cmd1 {}}
catch {unset l}
catch {unset msg}
catch {unset trigger}
| | | 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 |
"foo bar"}}
# cleanup
catch {rename cmd1 {}}
catch {unset l}
catch {unset msg}
catch {unset trigger}
namespace delete {expand}[namespace children :: test_ns_*]
::tcltest::cleanupTests
return
|
Changes to tests/parse.test.
1 2 3 4 5 6 7 8 9 10 | # This file contains a collection of tests for the procedures in the # file tclParse.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. # 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. # | | < | > | | | | | | | > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > | > | > | | > > > > > | | | > | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 |
# This file contains a collection of tests for the procedures in the
# file tclParse.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.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: parse.test,v 1.15.2.2 2004/02/07 05:48:03 dgp Exp $
if {[catch {package require tcltest 2.0.2}]} {
puts stderr "Skipping tests in [info script]. tcltest 2.0.2 required."
return
}
namespace eval ::tcl::test::parse {
namespace import ::tcltest::test
namespace import ::tcltest::testConstraint
namespace import ::tcltest::cleanupTests
namespace import ::tcltest::bytestring
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} 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} testparser {
testparser " \n\t foo" 0
} {- foo 1 simple foo 1 text foo 0 {}}
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} 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} 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} testparser {
testparser " \\\n" 0
} {- {} 0 {}}
test parse-1.8 {Tcl_ParseCommand procedure, eof in leading space} testparser {
testparser " foo" 3
} {- {} 0 { foo}}
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} 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} 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} testparser {
testparser "# \\\n" 0
} {\#\ \ \ \\\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} 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} 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} 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} testparser {
testparser "foo " 5
} {- {foo } 1 simple foo 1 text foo 0 { }}
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} 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} 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} testparser {
testparser {foo} 0
} {- foo 1 simple foo 1 text foo 0 {}}
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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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
} "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-5.11 {Tcl_ParseCommand: {expand} parsing} testparser {
testparser {{expan}} 0
} {- {{expan}} 1 simple {{expan}} 1 text expan 0 {}}
test parse-5.12 {Tcl_ParseCommand: {expand} parsing} -constraints {
testparser
} -body {
testparser {{expan}x} 0
} -returnCodes error -result {extra characters after close-brace}
test parse-5.13 {Tcl_ParseCommand: {expand} parsing} testparser {
testparser {{expandy}} 0
} {- {{expandy}} 1 simple {{expandy}} 1 text expandy 0 {}}
test parse-5.14 {Tcl_ParseCommand: {expand} parsing} -constraints {
testparser
} -body {
testparser {{expandy}x} 0
} -returnCodes error -result {extra characters after close-brace}
test parse-5.15 {Tcl_ParseCommand: {expand} parsing} -constraints {
testparser
} -body {
testparser {{expand}{123456}x} 0
} -returnCodes error -result {extra characters after close-brace}
test parse-5.16 {Tcl_ParseCommand: {expand} parsing} testparser {
testparser {{123456\
}} 0
} {- {{123456 }} 1 simple {{123456 }} 1 text {123456 } 0 {}}
test parse-5.17 {Tcl_ParseCommand: {expand} parsing} -constraints {
testparser
} -body {
testparser {{123456\
}x} 0
} -returnCodes error -result {extra characters after close-brace}
test parse-5.18 {Tcl_ParseCommand: {expand} parsing} testparser {
testparser {{expand\
}} 0
} {- {{expand }} 1 simple {{expand }} 1 text {expand } 0 {}}
test parse-5.19 {Tcl_ParseCommand: {expand} parsing} -constraints {
testparser
} -body {
testparser {{expand\
}x} 0
} -returnCodes error -result {extra characters after close-brace}
test parse-5.20 {Tcl_ParseCommand: {expand} parsing} testparser {
testparser {{123456}} 0
} {- {{123456}} 1 simple {{123456}} 1 text 123456 0 {}}
test parse-5.21 {Tcl_ParseCommand: {expand} parsing} -constraints {
testparser
} -body {
testparser {{123456}x} 0
} -returnCodes error -result {extra characters after close-brace}
test parse-5.22 {Tcl_ParseCommand: {expand} parsing} testparser {
testparser {{expand}} 0
} {- {{expand}} 1 simple {{expand}} 1 text expand 0 {}}
test parse-5.23 {Tcl_ParseCommand: {expand} parsing} testparser {
testparser {{expand} } 0
} {- {{expand} } 1 simple {{expand}} 1 text expand 0 {}}
test parse-5.24 {Tcl_ParseCommand: {expand} parsing} testparser {
testparser {{expand}x} 0
} {- {{expand}x} 1 expand {{expand}x} 1 text x 0 {}}
test parse-5.25 {Tcl_ParseCommand: {expand} parsing} testparser {
testparser {{expand}
} 0
} {- {{expand}
} 1 simple {{expand}} 1 text expand 0 {}}
test parse-5.26 {Tcl_ParseCommand: {expand} parsing} testparser {
testparser {{expand};} 0
} {- {{expand};} 1 simple {{expand}} 1 text expand 0 {}}
test parse-5.27 {Tcl_ParseCommand: {expand} parsing} testparser {
testparser "{expand}\\\n foo bar" 0
} {- \{expand\}\\\n\ foo\ bar 3 simple {{expand}} 1 text expand 0 simple foo 1 text foo 0 simple bar 1 text bar 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} 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} 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} testparser {
list [catch {testparser {$x([a )} 0} msg] $msg
} {1 {missing close-bracket}}
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} 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} 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
"testparser {a [b {}c d] e} 0"}}
test parse-6.8 {ParseTokens procedure, error in command substitution} {
info complete {a [b {}c d]}
} {1}
test parse-6.9 {ParseTokens procedure, error in command substitution} {
info complete {a [b "c d}
} {0}
test parse-6.10 {ParseTokens procedure, incomplete sub-command} {
info complete {puts [
expr 1+1
#this is a comment ]}
} {0}
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} 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} 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} 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} 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} 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} 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} 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} 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 {}}
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
set x [catch {testevalobjv 10 asdf poiu} msg]
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 {
return "unknown $args"
}
set x [catch {testevalobjv 0 asdf poiu} msg]
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 {
error "I don't like that command"
}
set x [catch {testevalobjv 0 asdf poiu} msg]
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 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} -constraints {
testevalobjv
} -setup {
proc x {} {
set y 23
set z [testevalobjv 1 set y]
return [list $z $y]
}
set ::y 16
} -cleanup {
unset ::y
} -body {
x
} -result {16 23}
test parse-8.8 {Tcl_EvalObjv procedure, async handlers} -constraints {
testevalobjv testasync
} -setup {
variable ::aresult
variable ::acode
proc async1 {result code} {
variable ::aresult
variable ::acode
set aresult $result
set acode $code
return "new result"
}
set handler1 [testasync create async1]
set aresult xxx
set acode yyy
} -cleanup {
testasync delete
} -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}
test parse-9.1 {Tcl_LogCommandInfo, line numbers} testevalex {
catch {unset x}
list [catch {testevalex {for {} 1 {} {
# asdf
set x
}}}] $errorInfo
|
| ︙ | ︙ | |||
301 302 303 304 305 306 307 |
invoked from within
"testevalex {for {} 1 {} {
# asdf
set x
}}"}}
| | | | | | | | | | | | | | | | | > > | > | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 |
invoked from within
"testevalex {for {} 1 {} {
# asdf
set x
}}"}}
test parse-9.2 {Tcl_LogCommandInfo, truncating long commands} testevalex {
list [testevalex {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} testevalex {
testevalex {concat test}
} {test}
test parse-10.2 {Tcl_EvalTokens, backslash sequences} testevalex {
testevalex {concat test\063\062test}
} {test32test}
test parse-10.3 {Tcl_EvalTokens, nested commands} testevalex {
testevalex {concat [expr 2 + 6]}
} {8}
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} testevalex {
set a hello
testevalex {concat $a}
} {hello}
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} testevalex {
catch {unset a}
set a(12) 46
testevalex {concat $a(1[expr 3 - 1])}
} {46}
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} 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} testevalex {
set a 123
testevalex {concat $a}
} {123}
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} testevalex {
testevalex {concat [expr 2][expr 4][expr 6]}
} {246}
test parse-10.13 {Tcl_EvalTokens, string values} testevalex {
testevalex {concat {a" b"}}
} {a" b"}
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} -constraints {
testevalex
} -setup {
proc x {} {
set y 777
set z [testevalex "set y" global]
return [list $z $y]
}
set ::y 321
} -cleanup {
unset ::y
} -body {
x
} -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} 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} 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} testevalex {
list [catch {testevalex {break}} msg] $msg
} {3 {}}
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} testevalex {
list [testevalex {set a b; set c d}] $a $c
} {d b d}
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} 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} testevalex {
testevalex {concat xyz; }
} {xyz}
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} testevalex {
testevalex {}
} {}
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} 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} 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} testparsevarname {
testparsevarname {$abcd} 0 0
} {- {} 0 variable {$abcd} 1 text abcd 0 {}}
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} 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} testparser {
testparser "\$\{\{\} " 0
} {- \$\{\{\}\ 1 word \$\{\{\} 2 variable \$\{\{\} 1 text \{ 0 {}}
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} 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} 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} 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} 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 ::} 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} 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. ::} testparsevarname {
testparsevarname {$ab:cd} 0 0
} {- {} 0 variable {$ab} 1 text ab 0 :cd}
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 ::} testparsevarname {
testparsevarname {$ab:::cd} 5 0
} {- {} 0 variable {$ab::} 1 text ab:: 0 :cd}
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 (} testparsevarname {
testparsevarname {$ab(cd)} 3 0
} {- {} 0 variable {$ab} 1 text ab 0 (cd)}
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} 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} 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} 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} 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} 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} testparsevar {
set abc 24
testparsevar {$abc.fg}
} {24 .fg}
test parse-13.2 {Tcl_ParseVar procedure, no variable name} testparsevar {
testparsevar {$}
} {{$} {}}
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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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
"testparser {foo "a b c"d} 0"}}
test parse-15.5 {CommandComplete procedure} {
|
| ︙ | ︙ | |||
704 705 706 707 708 709 710 |
test parse-15.49 {CommandComplete procedure} {
info complete "abc\\\n "
} 1
test parse-15.50 {CommandComplete procedure} {
info complete "abc\\\n"
} 0
test parse-15.51 {CommandComplete procedure} "
| | | | | 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 |
test parse-15.49 {CommandComplete procedure} {
info complete "abc\\\n "
} 1
test parse-15.50 {CommandComplete procedure} {
info complete "abc\\\n"
} 0
test parse-15.51 {CommandComplete procedure} "
info complete \"\\\{abc\\\}\\\{\"
" 1
test parse-15.52 {CommandComplete procedure} {
info complete "\"abc\"("
} 1
test parse-15.53 {CommandComplete procedure} "
info complete \" # \{\"
" 1
test parse-15.54 {CommandComplete procedure} "
info complete \"foo bar;# \{\"
" 1
test parse-15.55 {CommandComplete procedure} {
info complete "set x [bytestring \0]; puts hi"
} 1
test parse-15.56 {CommandComplete procedure} {
info complete "set x [bytestring \0]; \{"
} 0
|
| ︙ | ︙ | |||
849 850 851 852 853 854 855 |
} 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
| | > | | | 940 941 942 943 944 945 946 947 948 949 950 951 |
} 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
cleanupTests
}
namespace delete ::tcl::test::parse
return
|
Changes to tests/pkg.test.
1 2 3 4 5 6 7 8 9 10 11 12 | # Commands covered: pkg # # 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-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. # | | | | 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 |
# Commands covered: pkg
#
# 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-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.
#
# RCS: @(#) $Id: pkg.test,v 1.9.14.2 2004/02/07 05:48:03 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
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]
interp eval $i [list namespace import -force ::tcltest::*]
interp eval $i {
package forget {expand}[package names]
set oldPkgUnknown [package unknown]
package unknown {}
set oldPath $auto_path
set auto_path ""
test pkg-1.1 {Tcl_PkgProvide procedure} {
package forget t
|
| ︙ | ︙ |
Changes to tests/pkgMkIndex.test.
1 2 3 4 5 6 7 8 9 10 | # This file contains tests for the pkg_mkIndex command. # Note that the tests are limited to Tcl scripts only, there are no shared # libraries against which to test. # # 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. # All rights reserved. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# This file contains tests for the pkg_mkIndex command.
# Note that the tests are limited to Tcl scripts only, there are no shared
# libraries against which to test.
#
# 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.
# All rights reserved.
#
# RCS: @(#) $Id: pkgMkIndex.test,v 1.23.4.2 2004/02/07 05:48:03 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest 2
namespace import -force ::tcltest::*
}
set fullPkgPath [makeDirectory pkg]
|
| ︙ | ︙ | |||
85 86 87 88 89 90 91 |
rename package package_original
proc package { args } {
if {[string compare [lindex $args 0] ifneeded] == 0} {
set pkg [lindex $args 1]
set ver [lindex $args 2]
set ::PKGS($pkg:$ver) [lindex $args 3]
} else {
| | | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
rename package package_original
proc package { args } {
if {[string compare [lindex $args 0] ifneeded] == 0} {
set pkg [lindex $args 1]
set ver [lindex $args 2]
set ::PKGS($pkg:$ver) [lindex $args 3]
} else {
return [package_original {expand}$args]
}
}
array set ::PKGS {}
}
set dir [file dirname $filePath]
$slave eval {set curdir [pwd]}
|
| ︙ | ︙ | |||
144 145 146 147 148 149 150 |
#
# Results:
# Returns a two element list:
# 0: 1 if the procedure encountered an error, 0 otherwise.
# 1: the error result if element 0 was 1
proc pkgtest::createIndex { args } {
| | | | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
#
# Results:
# Returns a two element list:
# 0: 1 if the procedure encountered an error, 0 otherwise.
# 1: the error result if element 0 was 1
proc pkgtest::createIndex { args } {
set parsed [parseArgs {expand}$args]
set options [lindex $parsed 0]
set dirPath [lindex $parsed 1]
set patternList [lindex $parsed 2]
file mkdir $dirPath
if {[catch {
file delete [file join $dirPath pkgIndex.tcl]
pkg_mkIndex {expand}$options $dirPath {expand}$patternList
} err]} {
return [list 1 $err]
}
return [list 0 {}]
}
|
| ︙ | ︙ | |||
227 228 229 230 231 232 233 |
# 0: 1 if the procedure encountered an error, 0 otherwise.
# 1: if no error, this is the parsed generated index file, in the format
# returned by pkgtest::parseIndex.
# If error, this is the error result.
proc pkgtest::runCreatedIndex {rv args} {
if {[lindex $rv 0] == 0} {
| | | | | 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# 0: 1 if the procedure encountered an error, 0 otherwise.
# 1: if no error, this is the parsed generated index file, in the format
# returned by pkgtest::parseIndex.
# If error, this is the error result.
proc pkgtest::runCreatedIndex {rv args} {
if {[lindex $rv 0] == 0} {
set parsed [parseArgs {expand}$args]
set dirPath [lindex $parsed 1]
set idxFile [file join $dirPath pkgIndex.tcl]
if {[catch {
set result [list 0 [makePkgList [parseIndex $idxFile]]]
} err]} {
set result [list 1 $err]
}
file delete $idxFile
} else {
set result $rv
}
return $result
}
proc pkgtest::runIndex { args } {
set rv [createIndex {expand}$args]
return [runCreatedIndex $rv {expand}$args]
}
# If there is no match to the patterns, make sure the directory hasn't
# changed on us
test pkgMkIndex-1.1 {nothing matches pattern - current dir is the same} {
list [pkgtest::runIndex -lazy $fullPkgPath nomatch.tcl] [pwd]
|
| ︙ | ︙ |
Changes to tests/proc.test.
| ︙ | ︙ | |||
9 10 11 12 13 14 15 | # # 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. # | | | | | | | | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
#
# 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.
#
# RCS: @(#) $Id: proc.test,v 1.11.4.1 2004/02/07 05:48:03 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
namespace import -force ::tcltest::*
}
catch {namespace delete {expand}[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 {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {
namespace eval baz {}
}
proc test_ns_1::baz::p {} {
return "p in [namespace current]"
}
list [test_ns_1::baz::p] \
[namespace eval test_ns_1 {baz::p}] \
[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 {namespace delete {expand}[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 {namespace delete {expand}[namespace children :: test_ns_*]}
proc :: {} {
return "empty called"
}
list [::] \
[info body {}]
} {{empty called} {
return "empty called"
}}
test proc-1.4 {Tcl_ProcObjCmd, simple proc name and proc defined in namespace} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {
namespace eval baz {
proc p {} {
return "p in [namespace current]"
}
}
}
list [test_ns_1::baz::p] \
[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 {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_1::baz {}
namespace eval test_ns_1 {
proc baz::p {} {
return "p in [namespace current]"
}
}
list [test_ns_1::baz::p] \
[info commands test_ns_1::baz::*] \
[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 {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {
proc q: {} {return "q:"}
proc value:at: {} {return "value:at:"}
}
list [namespace eval test_ns_1 {q:}] \
[namespace eval test_ns_1 {value:at:}] \
[test_ns_1::q:] \
|
| ︙ | ︙ | |||
99 100 101 102 103 104 105 |
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}}
test proc-2.1 {TclFindProc, simple proc name and proc not in namespace} {
| | | | | | | | | | | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
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}}
test proc-2.1 {TclFindProc, simple proc name and proc not in namespace} {
catch {namespace delete {expand}[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 {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {
namespace eval baz {
proc p {} {return "p in [namespace current]"}
}
}
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 {namespace delete {expand}[namespace children :: test_ns_*]}
namespace eval test_ns_1::baz {}
namespace eval test_ns_1 {
proc baz::p {} {return "p in [namespace current]"}
}
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 {namespace delete {expand}[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 {namespace delete {expand}[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 {namespace delete {expand}[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 {namespace delete {expand}[namespace children :: test_ns_*]}
catch {rename p ""}
proc p {} {return "p in [namespace current]"}
namespace eval test_ns_1::baz {
p
}
} {p in ::}
test proc-3.4 {TclObjInterpProc, procs execute in the namespace in which they were defined unless renamed into new namespace} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
catch {rename p ""}
namespace eval test_ns_1::baz {
proc p {} {return "p in [namespace current]"}
rename ::test_ns_1::baz::p ::p
list [p] [namespace which p]
}
} {{p in ::} ::p}
test proc-3.5 {TclObjInterpProc, any old result is reset before appending error msg about missing arguments} {
proc p {x} {info commands 3m}
list [catch {p} msg] $msg
} {1 {wrong # args: should be "p x"}}
catch {namespace delete {expand}[namespace children :: test_ns_*]}
catch {rename p ""}
catch {rename {} ""}
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\"."
|
| ︙ | ︙ |
Changes to tests/reg.test.
1 2 3 4 5 6 7 8 9 10 11 | # reg.test -- # # 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. # (Don't panic if you are seeing this as part of the reg distribution # and aren't using Tcl -- reg's own regression tester also knows how # to read this file, ignoring the Tcl-isms.) # # Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# reg.test --
#
# 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.
# (Don't panic if you are seeing this as part of the reg distribution
# and aren't using Tcl -- reg's own regression tester also knows how
# to read this file, ignoring the Tcl-isms.)
#
# Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
#
# RCS: @(#) $Id: reg.test,v 1.17.2.2 2004/02/07 05:48:03 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest 2
namespace import -force ::tcltest::*
}
# All tests require the testregexp command, return if this
|
| ︙ | ︙ | |||
227 228 229 230 231 232 233 |
}
# 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]
| | < | < | 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
}
# 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]
f [linsert $testid end ARE] ${f} $re $target {expand}$args
f [linsert $testid end BRE] ${f}b $re $target {expand}$args
return
}
set f [flags $flags]
set infoflags [infoflags $flags]
set ccmd [concat [list testregexp -$ask] $f [list $re]]
set nsub [expr [llength $args] - 1]
|
| ︙ | ︙ | |||
279 280 281 282 283 284 285 |
}
# 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]
| | | > > | | | 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
}
# 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]
matchexpected $opts [linsert $testid end ARE] \
${f} $re $target {expand}$args
matchexpected $opts [linsert $testid end BRE] \
${f}b $re $target {expand}$args
return
}
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]]
|
| ︙ | ︙ | |||
328 329 330 331 332 333 334 |
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} {
| | | | | 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
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} {
matchexpected {} {expand}$args
}
# match expected (full fanciness)
# i testno flags re target mat submat ...
proc i {args} {
matchexpected -indices {expand}$args
}
# 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"]
matchexpected -indices {expand}$args
}
# test is a knownBug
proc knownBug {args} {
set ::regBug 1
uplevel #0 $args
set ::regBug 0
|
| ︙ | ︙ | |||
1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 |
test reg-32.9 {canmatch functionality -- more complex case} {knownBug} {
set pat {((\B\B|\Bh+line)[ \t]*|[^\B]%[^\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}
# cleanup
::tcltest::cleanupTests
return
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 |
test reg-32.9 {canmatch functionality -- more complex case} {knownBug} {
set pat {((\B\B|\Bh+line)[ \t]*|[^\B]%[^\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}
# Tests reg-33.*: Checks for bug fixes
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} {
regsub {(^|\n)+\.*b} \n.b {} tmp
} 1
test reg-33.11 {Bug 840258} {
regsub {(^|[\n\r]+)\.*\?<.*?(\n|\r)+} \
"TQ\r\n.?<5000267>Test already stopped\r\n" {} tmp
} 1
# cleanup
::tcltest::cleanupTests
return
|
Changes to tests/resource.test.
1 2 3 4 5 6 7 8 9 10 11 12 | # 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. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# 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.
#
# RCS: @(#) $Id: resource.test,v 1.7.26.2 2004/02/07 05:48:03 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
namespace import -force ::tcltest::*
}
test resource-1.1 {resource tests} {macOnly} {
|
| ︙ | ︙ | |||
144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
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
| > > > > | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
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}
test resource-5.5 {resource types lists} {macOnly} {
# This should not crash
catch {foreach f [resource types] { resource list $f }}
} {0}
# 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
|
| ︙ | ︙ |
Changes to tests/switch.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # Commands covered: switch # # 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) 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. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# Commands covered: switch
#
# 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) 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.
#
# RCS: @(#) $Id: switch.test,v 1.9.2.1 2004/02/07 05:48:03 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
namespace import -force ::tcltest::*
}
test switch-1.1 {simple patterns} {
|
| ︙ | ︙ | |||
85 86 87 88 89 90 91 |
-* {concat glob}
-glob {concat exact}
default {concat none}
}
} exact
test switch-3.6 {-exact vs. -glob vs. -regexp} {
list [catch {switch -foo a b c} msg] $msg
| | | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
-* {concat glob}
-glob {concat exact}
default {concat 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, -indexvar, -matchvar, -regexp, or --}}
test switch-4.1 {error in executed command} {
list [catch {switch a a {error "Just a test"} default {format 1}} msg] \
$msg $errorInfo
} {1 {Just a test} {Just a test
while executing
"error "Just a test""
|
| ︙ | ︙ | |||
356 357 358 359 360 361 362 363 364 365 |
rename cswtest2-glob {}
rename iswtest2-glob {}
rename cswtest-exact {}
rename iswtest-exact {}
rename cswtest2-exact {}
rename iswtest2-exact {}
# cleanup
::tcltest::cleanupTests
return
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 |
rename cswtest2-glob {}
rename iswtest2-glob {}
rename cswtest-exact {}
rename iswtest-exact {}
rename cswtest2-exact {}
rename iswtest2-exact {}
# 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}}
# cleanup
::tcltest::cleanupTests
return
|
Changes to tests/trace.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # Commands covered: trace # # 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 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. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# Commands covered: trace
#
# 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 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: trace.test,v 1.28.2.3 2004/02/07 05:48:03 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
namespace import -force ::tcltest::*
}
testConstraint testcmdtrace [llength [info commands testcmdtrace]]
|
| ︙ | ︙ | |||
1342 1343 1344 1345 1346 1347 1348 |
$tc eval [list proc foo {} {}]
$tc eval [list trace add command foo {rename delete} traceCommand]
interp delete $tc
set info
} {}
proc traceDelete {cmd old new op} {
| | | 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 |
$tc eval [list proc foo {} {}]
$tc eval [list trace add command foo {rename delete} traceCommand]
interp delete $tc
set info
} {}
proc traceDelete {cmd old new op} {
trace remove command $cmd {expand}[lindex [trace info command $cmd] 0]
global info
set info [list $old $new $op]
}
proc traceCmdrename {cmd old new op} {
rename $old someothername
}
proc traceCmddelete {cmd old new op} {
|
| ︙ | ︙ | |||
1598 1599 1600 1601 1602 1603 1604 |
{expr {$n * [factorial [expr {$n -1 }]]}} 0 6 leavestep
{return 6} enterstep
{return 6} 2 6 leavestep
{if {$n != 1} { return [expr {$n * [factorial [expr {$n -1 }]]}] }} 2 6 leavestep
{factorial 3} 0 6 leave}
proc traceDelete {cmd args} {
| | | 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 |
{expr {$n * [factorial [expr {$n -1 }]]}} 0 6 leavestep
{return 6} enterstep
{return 6} 2 6 leavestep
{if {$n != 1} { return [expr {$n * [factorial [expr {$n -1 }]]}] }} 2 6 leavestep
{factorial 3} 0 6 leave}
proc traceDelete {cmd args} {
trace remove execution $cmd {expand}[lindex [trace info execution $cmd] 0]
global info
set info $args
}
test trace-24.1 {delete trace during enter trace} {
set info {}
trace add execution foo enter [list traceDelete foo]
|
| ︙ | ︙ |
Changes to tests/unixInit.test.
1 2 3 4 5 6 7 8 9 10 11 12 | # The file tests the functions in the tclUnixInit.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 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. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# The file tests the functions in the tclUnixInit.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 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.
#
# RCS: @(#) $Id: unixInit.test,v 1.30.4.1 2004/02/07 05:48:03 dgp Exp $
package require tcltest 2
namespace import -force ::tcltest::*
catch {unset path}
if {[info exists env(TCL_LIBRARY)]} {
set oldlibrary $env(TCL_LIBRARY)
unset env(TCL_LIBRARY)
|
| ︙ | ︙ | |||
262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
set x [lrange [getlibpath /tmp/sparkly/tcltest] 0 4]
file delete -force /tmp/sparkly
file delete -force /tmp/library
set x
} [list /tmp/lib/tcl[info tclversion] /lib/tcl[info tclversion] \
/tmp/library /library /tcl[info patchlevel]/library]
test unixInit-3.1 {TclpSetInitialEncodings} -constraints {
unixOnly stdio
} -body {
set env(LANG) C
set f [open "|[list [interpreter]]" w+]
fconfigure $f -buffering none
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 |
set x [lrange [getlibpath /tmp/sparkly/tcltest] 0 4]
file delete -force /tmp/sparkly
file delete -force /tmp/library
set x
} [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 {
set tmpDir [makeDirectory tmp]
set sparklyDir [makeDirectory sparkly $tmpDir]
set execPath [file join [makeDirectory bin $sparklyDir] tcltest]
file copy [interpreter] $execPath
set libDir [makeDirectory lib $sparklyDir]
set scriptDir [makeDirectory tcl[info tclversion] $libDir]
makeFile {} init.tcl $scriptDir
set saveDir [pwd]
cd $libDir
} -body {
# Checking for Bug 832657
lrange [getlibpath [file join .. bin tcltest]] 2 3
} -cleanup {
cd $saveDir
unset saveDir
removeFile init.tcl $scriptDir
unset scriptDir
removeDirectory tcl[info tclversion] $libDir
unset libDir
file delete $execPath
unset execPath
removeDirectory bin $sparklyDir
removeDirectory lib $sparklyDir
unset sparklyDir
removeDirectory sparkly $tmpDir
unset tmpDir
removeDirectory tmp
} -result [list [file join [temporaryDirectory] tmp sparkly library] \
[file join [temporaryDirectory] tmp library] ]
test unixInit-3.1 {TclpSetInitialEncodings} -constraints {
unixOnly stdio
} -body {
set env(LANG) C
set f [open "|[list [interpreter]]" w+]
fconfigure $f -buffering none
|
| ︙ | ︙ |
Changes to tests/upvar.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # Commands covered: 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 # 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 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. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# Commands covered: 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
# 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 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: upvar.test,v 1.7.26.1 2004/02/07 05:48:03 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
namespace import -force ::tcltest::*
}
test upvar-1.1 {reading variables with upvar} {
|
| ︙ | ︙ | |||
316 317 318 319 320 321 322 |
} {1 {variable "a" has traces: can't use for upvar}}
test upvar-8.8 {create nested array with upvar} {
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}}
test upvar-8.9 {upvar won't create namespace variable that refers to procedure variable} {
| | | 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 |
} {1 {variable "a" has traces: can't use for upvar}}
test upvar-8.8 {create nested array with upvar} {
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}}
test upvar-8.9 {upvar won't create namespace variable that refers to procedure variable} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
catch {rename MakeLink ""}
namespace eval ::test_ns_1 {}
proc MakeLink {a} {
namespace eval ::test_ns_1 {
upvar a a
}
unset ::test_ns_1::a
|
| ︙ | ︙ |
Changes to tests/winConsole.test.
1 2 3 4 5 6 7 8 9 10 11 | # This file tests the tclWinConsole.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) 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. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# This file tests the tclWinConsole.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) 1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: winConsole.test,v 1.5.26.1 2004/02/07 05:48:03 dgp Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
namespace import -force ::tcltest::*
}
|
| ︙ | ︙ | |||
35 36 37 38 39 40 41 |
fconfigure stdin -blocking 0 -buffering line
set result {}
vwait result
#cleanup the fileevent
fileevent stdin readable {}
| | | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
fconfigure stdin -blocking 0 -buffering line
set result {}
vwait result
#cleanup the fileevent
fileevent stdin readable {}
fconfigure stdin {expand}$oldmode
set result
} "abcdef"
#cleanup
::tcltest::cleanupTests
return
|
Changes to tests/winFCmd.test.
1 2 3 4 5 6 7 8 9 10 11 12 | # This file tests the tclWinFCmd.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) 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. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# This file tests the tclWinFCmd.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) 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.
#
# RCS: @(#) $Id: winFCmd.test,v 1.20.4.3 2004/02/07 05:48:03 dgp Exp $
#
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
namespace import -force ::tcltest::*
}
|
| ︙ | ︙ | |||
35 36 37 38 39 40 41 |
proc cleanup {args} {
foreach p ". $args" {
set x ""
catch {
set x [glob -directory $p tf* td*]
}
if {$x != ""} {
| | | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
proc cleanup {args} {
foreach p ". $args" {
set x ""
catch {
set x [glob -directory $p tf* td*]
}
if {$x != ""} {
catch {file delete -force -- {expand}$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"]} {
|
| ︙ | ︙ | |||
606 607 608 609 610 611 612 |
} {1 {nul EACCES}}
test winFCmd-6.11 {TclpRemoveDirectory: attr == -1} {pcOnly nt} {
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"
| | | 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 |
} {1 {nul EACCES}}
test winFCmd-6.11 {TclpRemoveDirectory: attr == -1} {pcOnly nt} {
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"
} [list 1 [list / EACCES or EEXIST]]
test winFCmd-6.12 {TclpRemoveDirectory: errno == EACCES} {pcOnly 95} {
cleanup
createfile tf1
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
|
| ︙ | ︙ | |||
1012 1013 1014 1015 1016 1017 1018 |
} "${d}:/bar"
test winFCmd-16.8 {Windows file normalization} {pcOnly} {
file norm ///bar
} "${d}:/bar"
test winFCmd-16.9 {Windows file normalization} {pcOnly} {
file norm /bar/foo
} "${d}:/bar/foo"
| < | > > > > > > > > > | > | | 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 |
} "${d}:/bar"
test winFCmd-16.8 {Windows file normalization} {pcOnly} {
file norm ///bar
} "${d}:/bar"
test winFCmd-16.9 {Windows file normalization} {pcOnly} {
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} {
file norm ${dd}:foo
} "${dd}:/foo"
test winFCmd-16.11 {Windows file normalization} {pcOnly cdrom} {
cd ${d}:
cd $cdrom
cd ${d}:
cd $cdrom
# Must not crash
set result "no crash"
} {no crash}
cd $pwd
unset d dd pwd
# 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} {
# foreach chmodsrc {000 755} {
# foreach dest "tfn tfe tdn tdempty tdfull td1/td2 $p $p/td1 {} nul" {
# foreach chmoddst {000 755} {
|
| ︙ | ︙ |
Changes to tests/winFile.test.
1 2 3 4 5 6 7 8 9 10 11 12 | # 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. # # 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. # | | < | > > > | > > > > > > > > > | 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 |
# 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.
#
# 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.
#
# RCS: @(#) $Id: winFile.test,v 1.10.2.1 2004/02/07 05:48:03 dgp Exp $
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::*
if {[info commands ::testvolumetype] == ""} {
tcltest::testConstraint notNTFS 0
} else {
if {![string equal "NTFS" [testvolumetype]]} {
tcltest::testConstraint notNTFS 0
} else {
tcltest::testConstraint notNTFS 1
}
}
test winFile-1.1 {TclpGetUserHome} {pcOnly} {
list [catch {glob ~nosuchuser} msg] $msg
} {1 {user "nosuchuser" doesn't exist}}
test winFile-1.2 {TclpGetUserHome} {pcOnly nt nonPortable} {
# The administrator account should always exist.
|
| ︙ | ︙ | |||
73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
and [testvolumetype $vol] are different"
break
}
}
}
set res
} {volume types ok}
# cleanup
::tcltest::cleanupTests
return
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
and [testvolumetype $vol] are different"
break
}
}
}
set res
} {volume types ok}
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
proc getuser {fname} {
set tryname $fname
if {[file isdirectory $fname]} {
set tryname [file dirname $fname]
}
set tail [file tail $tryname]
set dirtext [exec cmd /c dir /q [file nativename $fname]]
set owner ""
foreach line [split $dirtext "\n"] {
if {[string match -nocase "* $tail" $line]} {
set attrs [string range $line \
0 end-[string length $tail]]
regexp { [A-Z]+\\.*$} $attrs owner
set owner [string trim $owner]
}
}
if {"" == "$owner"} {
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 ""
}
}
# 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 {
notNTFS pcOnly nt
} -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 {
notNTFS pcOnly nt
} -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 {
notNTFS pcOnly nt
} -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 {
notNTFS pcOnly nt
} -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 {
notNTFS pcOnly nt
} -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 {}
file delete $fname
# cleanup
::tcltest::cleanupTests
return
|
| ︙ | ︙ |
Changes to tests/winPipe.test.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | # # Copyright (c) 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. # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # # Copyright (c) 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. # # RCS: @(#) $Id: winPipe.test,v 1.22.4.1 2004/02/07 05:48:03 dgp Exp $ package require tcltest namespace import -force ::tcltest::* testConstraint exec [llength [info commands exec]] set bindir [file join [pwd] [file dirname [info nameofexecutable]]] |
| ︙ | ︙ | |||
311 312 313 314 315 316 317 318 319 |
lappend x [catch {close $f} msg] $msg
} {writable timeout 0 {}}
set path(echoArgs.tcl) [makeFile {
puts "[list $argv0 $argv]"
} echoArgs.tcl]
test winpipe-7.1 {BuildCommandLine: null arguments} {pcOnly exec} {
exec [interpreter] $path(echoArgs.tcl) foo "" bar
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 |
lappend x [catch {close $f} msg] $msg
} {writable timeout 0 {}}
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} {
exec $env(COMSPEC) /c echo foo "" bar
} {foo "" bar}
test winpipe-7.2 {BuildCommandLine: null arguments} {pcOnly 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
} {foo \" bar}
test winpipe-7.4 {BuildCommandLine: dbl quote quoting #2} {pcOnly 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
} {foo "\" " bar}
test winpipe-7.6 {BuildCommandLine: dbl quote quoting #4} {pcOnly 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} {
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}
} {\"hello\" \"\"hello\"\" \"\"\"hello\"\"\" \"\\\"hello\\\"\" "he llo" "he \" llo"}
test winpipe-7.9 {BuildCommandLine: N backslashes followed a quote rule #1} {pcOnly exec} {
exec $env(COMSPEC) /c echo foo \\ bar
} {foo \ bar}
test winpipe-7.10 {BuildCommandLine: N backslashes followed a quote rule #2} {pcOnly exec} {
exec $env(COMSPEC) /c echo foo \\\\ bar
} {foo \\ bar}
test winpipe-7.11 {BuildCommandLine: N backslashes followed a quote rule #3} {pcOnly exec} {
exec $env(COMSPEC) /c echo foo \\\ \\ bar
} {foo "\ \\" bar}
test winpipe-7.12 {BuildCommandLine: N backslashes followed a quote rule #4} {pcOnly exec} {
exec $env(COMSPEC) /c echo foo \\\ \\\\ bar
} {foo "\ \\\\" bar}
test winpipe-7.13 {BuildCommandLine: N backslashes followed a quote rule #5} {pcOnly exec} {
exec $env(COMSPEC) /c echo foo \\\ \\\\\\ bar
} {foo "\ \\\\\\" bar}
test winpipe-7.14 {BuildCommandLine: N backslashes followed a quote rule #6} {pcOnly exec} {
exec $env(COMSPEC) /c echo foo \\\ \\\" bar
} {foo "\ \\\"" bar}
test winpipe-7.15 {BuildCommandLine: N backslashes followed a quote rule #7} {pcOnly exec} {
exec $env(COMSPEC) /c echo foo \\\ \\\\\" bar
} {foo "\ \\\\\"" bar}
test winpipe-7.16 {BuildCommandLine: N backslashes followed a quote rule #8} {pcOnly exec} {
exec $env(COMSPEC) /c echo foo \\\ \\\\\\\" bar
} {foo "\ \\\\\\\"" bar}
test winpipe-7.17 {BuildCommandLine: special chars #4} {pcOnly exec} {
exec $env(COMSPEC) /c echo foo \{ bar
} "foo \{ bar"
test winpipe-7.18 {BuildCommandLine: special chars #5} {pcOnly 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} {
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} {
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} {
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} {
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} {
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} {
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} {
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} {
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} {
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} {
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} {
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} {
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} {
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} {
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} {
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} {
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} {
exec [interpreter] $path(echoArgs.tcl) foo * makefile.?c bar
} [list $path(echoArgs.tcl) [list foo * makefile.?c bar]]
# restore old values for env(TMP) and env(TEMP)
if {[catch {set env(TMP) $env_tmp}]} {
unset env(TMP)
}
if {[catch {set env(TEMP) $env_temp}]} {
|
| ︙ | ︙ |
Changes to tools/man2tcl.c.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 | * man2tcl ?fileName? * * 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. * | | > > > > > > > | 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 | * man2tcl ?fileName? * * 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. * * RCS: @(#) $Id: man2tcl.c,v 1.7.4.1 2004/02/07 05:48:03 dgp Exp $ */ static char sccsid[] = "@(#) man2tcl.c 1.3 95/08/12 17:34:08"; #include <stdio.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! */ #ifndef errno extern int errno; #endif /* * Current line number, used for error messages. */ static int lineNumber; |
| ︙ | ︙ |
Changes to tools/tcl.wse.in.
| ︙ | ︙ | |||
1059 1060 1061 1062 1063 1064 1065 |
item: If/While Statement
Variable=COMPONENTS
Value=A
Flags=00001010
end
item: Install File
Source=${__TCLBASEDIR__}\library\msgcat\pkgIndex.tcl
| | | | 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 |
item: If/While Statement
Variable=COMPONENTS
Value=A
Flags=00001010
end
item: Install File
Source=${__TCLBASEDIR__}\library\msgcat\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.4\msgcat.tcl
Flags=0000000010000010
end
item: Install File
Source=${__TCLBASEDIR__}\library\tcltest\pkgIndex.tcl
Destination=%MAINDIR%\lib\tcl%VER%\tcltest2.0\pkgIndex.tcl
Flags=0000000000000010
end
|
| ︙ | ︙ |
Changes to tools/tcltk-man2html.tcl.
| ︙ | ︙ | |||
475 476 477 478 479 480 481 |
man-puts <P>$rest
return
}
if {[next-op-is .RE rest]} {
return
}
}
| | | 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 |
man-puts <P>$rest
return
}
if {[next-op-is .RE rest]} {
return
}
}
man-puts <DL><DD>
while {[more-text]} {
set line [next-text]
if {[is-a-directive $line]} {
split-directive $line code rest
switch -exact $code {
.RE {
break
|
| ︙ | ︙ | |||
508 509 510 511 512 513 514 |
## process .IP lists which may be plain indents,
## numeric lists, or definition lists
##
proc output-IP-list {context code rest} {
global manual
if {![string length $rest]} {
# blank label, plain indent, no contents entry
| | | 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 |
## process .IP lists which may be plain indents,
## numeric lists, or definition lists
##
proc output-IP-list {context code rest} {
global manual
if {![string length $rest]} {
# blank label, plain indent, no contents entry
man-puts <DL><DD>
while {[more-text]} {
set line [next-text]
if {[is-a-directive $line]} {
split-directive $line code rest
if {[string equal $code ".IP"] && [string equal $rest {}]} {
man-puts "<P>"
continue
|
| ︙ | ︙ | |||
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 |
if {[string compare $context ".SH"]} {
man-puts <P>
}
man-puts <DL>
lappend manual(section-toc) <DL>
backup-text 1
set accept_RE 0
while {[more-text]} {
set line [next-text]
if {[is-a-directive $line]} {
split-directive $line code rest
switch -exact $code {
.IP {
if {$accept_RE} {
output-IP-list .IP $code $rest
continue
}
if {[string equal $manual(section) "ARGUMENTS"] || \
[regexp {^\[\d+\]$} $rest]} {
| > | | | 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 |
if {[string compare $context ".SH"]} {
man-puts <P>
}
man-puts <DL>
lappend manual(section-toc) <DL>
backup-text 1
set accept_RE 0
set para {}
while {[more-text]} {
set line [next-text]
if {[is-a-directive $line]} {
split-directive $line code rest
switch -exact $code {
.IP {
if {$accept_RE} {
output-IP-list .IP $code $rest
continue
}
if {[string equal $manual(section) "ARGUMENTS"] || \
[regexp {^\[\d+\]$} $rest]} {
man-puts "$para<DT>$rest<DD>"
} else {
man-puts "$para<DT>[long-toc $rest]<DD>"
}
if {[string equal $manual(name):$manual(section) \
"selection:DESCRIPTION"]} {
if {[match-text .RE @rest .RS .RS]} {
man-puts <DT>[long-toc $rest]<DD>
}
}
|
| ︙ | ︙ | |||
586 587 588 589 590 591 592 |
} else {
output-directive $line
}
}
.PP {
if {[match-text @rest1 .br @rest2 .RS]} {
# yet another nroff kludge as above
| | > | 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 |
} else {
output-directive $line
}
}
.PP {
if {[match-text @rest1 .br @rest2 .RS]} {
# yet another nroff kludge as above
man-puts "$para<DT>[long-toc $rest1]"
man-puts "<DT>[long-toc $rest2]<DD>"
incr accept_RE 1
} elseif {[match-text @rest .RE]} {
# gad, this is getting ridiculous
if {!$accept_RE} {
man-puts "</DL><P>$rest<DL>"
backup-text 1
set para {}
break
} else {
man-puts "<P>$rest"
incr accept_RE -1
}
} elseif {$accept_RE} {
output-directive $line
|
| ︙ | ︙ | |||
621 622 623 624 625 626 627 628 |
backup-text 1
break
}
}
} else {
man-puts $line
}
}
| > | | 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 |
backup-text 1
break
}
}
} else {
man-puts $line
}
set para <P>
}
man-puts "$para</DL>"
lappend manual(section-toc) </DL>
if {$accept_RE} {
manerror "missing .RE in output-IP-list"
}
}
}
##
|
| ︙ | ︙ | |||
1398 1399 1400 1401 1402 1403 1404 |
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 {
| | > > | 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 |
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"]]
|
| ︙ | ︙ |
Changes to unix/Makefile.in.
1 2 3 4 5 6 7 | # # 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. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # # 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. # # RCS: @(#) $Id: Makefile.in,v 1.127.2.4 2004/02/07 05:48:03 dgp Exp $ VERSION = @TCL_VERSION@ MAJOR_VERSION = @TCL_MAJOR_VERSION@ MINOR_VERSION = @TCL_MINOR_VERSION@ PATCH_LEVEL = @TCL_PATCH_LEVEL@ #---------------------------------------------------------------- |
| ︙ | ︙ | |||
628 629 630 631 632 633 634 | if [ ! -d $$i ] ; then \ echo "Making directory $$i"; \ mkdir -p $$i; \ chmod 755 $$i; \ else true; \ fi; \ done; | | | 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 | if [ ! -d $$i ] ; then \ echo "Making directory $$i"; \ mkdir -p $$i; \ chmod 755 $$i; \ else true; \ fi; \ done; @for i in http2.4 http1.0 opt0.4 encoding msgcat1.4 tcltest2.2; \ do \ 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; \ else true; \ fi; \ |
| ︙ | ︙ | |||
666 667 668 669 670 671 672 | $(INSTALL_DATA) $$j $(SCRIPT_INSTALL_DIR)/http2.4; \ done; @echo "Installing library opt0.4 directory"; @for j in $(TOP_DIR)/library/opt/*.tcl ; \ do \ $(INSTALL_DATA) $$j $(SCRIPT_INSTALL_DIR)/opt0.4; \ done; | | | | 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 | $(INSTALL_DATA) $$j $(SCRIPT_INSTALL_DIR)/http2.4; \ done; @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.4 directory"; @for j in $(TOP_DIR)/library/msgcat/*.tcl ; \ do \ $(INSTALL_DATA) $$j $(SCRIPT_INSTALL_DIR)/msgcat1.4; \ done; @echo "Installing library tcltest2.2 directory"; @for j in $(TOP_DIR)/library/tcltest/*.tcl ; \ do \ $(INSTALL_DATA) $$j $(SCRIPT_INSTALL_DIR)/tcltest2.2; \ done; @echo "Installing library encoding directory"; |
| ︙ | ︙ |
Changes to unix/configure.
| ︙ | ︙ | |||
10896 10897 10898 10899 10900 10901 10902 |
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"
# AIX-5 uses ELF style dynamic libraries
SHLIB_CFLAGS=""
| < < < < < < < < < < < < < < < < < < < < < < > > > > > > > > > > > > > > > > > > > > > > < > > > > > > > > > > > > > > > > | 10896 10897 10898 10899 10900 10901 10902 10903 10904 10905 10906 10907 10908 10909 10910 10911 10912 10913 10914 10915 10916 10917 10918 10919 10920 10921 10922 10923 10924 10925 10926 10927 10928 10929 10930 10931 10932 10933 10934 10935 10936 10937 10938 10939 10940 10941 10942 10943 10944 10945 10946 10947 10948 10949 10950 10951 10952 10953 10954 10955 10956 10957 10958 10959 10960 10961 10962 10963 10964 10965 10966 10967 10968 10969 10970 10971 10972 10973 10974 10975 10976 10977 10978 10979 10980 10981 10982 10983 10984 10985 10986 10987 10988 10989 10990 10991 10992 10993 10994 10995 10996 10997 10998 |
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"
# AIX-5 uses ELF style dynamic libraries
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"
LDFLAGS=""
LD_LIBRARY_PATH_VAR="LIBPATH"
# 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
EXTRA_CFLAGS="-q64"
LDFLAGS="-q64"
RANLIB="${RANLIB} -X64"
AR="${AR} -X64"
SHLIB_LD_FLAGS="-b64"
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
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
SHLIB_LD="${TCL_SRC_DIR}/unix/ldAix /bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry ${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-*)
if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes" ; then
# AIX requires the _r compiler when gcc isn't being used
if test "${CC}" != "cc_r" ; then
CC=${CC}_r
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=""
SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
LDFLAGS=""
CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
LD_LIBRARY_PATH_VAR="LIBPATH"
TCL_NEEDS_EXP_FILE=1
TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.exp'
# 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.$ac_objext"
DL_LIBS="-lld"
fi
# 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
EXTRA_CFLAGS="-q64"
LDFLAGS="-q64"
RANLIB="${RANLIB} -X64"
AR="${AR} -X64"
SHLIB_LD_FLAGS="-b64"
fi
fi
SHLIB_LD="${TCL_SRC_DIR}/unix/ldAix /bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry ${SHLIB_LD_FLAGS}"
# 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
|
| ︙ | ︙ | |||
11048 11049 11050 11051 11052 11053 11054 | if test $libbsd = yes; then MATH_LIBS="$MATH_LIBS -lbsd" cat >>confdefs.h <<\_ACEOF #define USE_DELTA_FOR_TZ 1 _ACEOF | < < < < < < < < < < < < < < < | 11063 11064 11065 11066 11067 11068 11069 11070 11071 11072 11073 11074 11075 11076 |
if test $libbsd = yes; then
MATH_LIBS="$MATH_LIBS -lbsd"
cat >>confdefs.h <<\_ACEOF
#define USE_DELTA_FOR_TZ 1
_ACEOF
fi
;;
BeOS*)
SHLIB_CFLAGS="-fPIC"
SHLIB_LD="${CC} -nostart"
SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
|
| ︙ | ︙ | |||
11442 11443 11444 11445 11446 11447 11448 11449 11450 11451 |
fi
;;
Linux*)
SHLIB_CFLAGS="-fPIC"
SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
# 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.
| > < | | 11442 11443 11444 11445 11446 11447 11448 11449 11450 11451 11452 11453 11454 11455 11456 11457 11458 11459 11460 |
fi
;;
Linux*)
SHLIB_CFLAGS="-fPIC"
SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
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"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
LDFLAGS="-Wl,--export-dynamic"
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
|
| ︙ | ︙ | |||
11799 11800 11801 11802 11803 11804 11805 | SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="-Wl,-Bexport" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; | | | 11799 11800 11801 11802 11803 11804 11805 11806 11807 11808 11809 11810 11811 11812 11813 |
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
LDFLAGS="-Wl,-Bexport"
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
;;
NetBSD-*|FreeBSD-[1-2].*)
# Not available on all versions: check for include file.
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
|
| ︙ | ︙ | |||
11993 11994 11995 11996 11997 11998 11999 12000 12001 12002 12003 12004 12005 12006 |
# FreeBSD doesn't handle version numbers with dots.
UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
TCL_LIB_VERSIONS_OK=nodots
;;
FreeBSD-*)
# FreeBSD 3.* and greater have ELF.
SHLIB_CFLAGS="-fPIC"
SHLIB_LD="ld -Bshareable -x"
SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 11993 11994 11995 11996 11997 11998 11999 12000 12001 12002 12003 12004 12005 12006 12007 12008 12009 12010 12011 12012 12013 12014 12015 12016 12017 12018 12019 12020 12021 12022 12023 12024 12025 12026 12027 12028 12029 12030 12031 12032 12033 12034 12035 12036 12037 12038 12039 12040 12041 12042 12043 12044 12045 12046 12047 12048 |
# FreeBSD doesn't handle version numbers with dots.
UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
TCL_LIB_VERSIONS_OK=nodots
;;
OpenBSD-*)
SHLIB_LD="${CC} -shared"
SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
LDFLAGS=""
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
echo "$as_me:$LINENO: checking for ELF" >&5
echo $ECHO_N "checking for ELF... $ECHO_C" >&6
cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#ifdef __ELF__
yes
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "yes" >/dev/null 2>&1; then
echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1.0'
else
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1.0'
fi
rm -f conftest*
# OpenBSD doesn't do version numbers with dots.
UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
TCL_LIB_VERSIONS_OK=nodots
;;
FreeBSD-*)
# FreeBSD 3.* and greater have ELF.
SHLIB_CFLAGS="-fPIC"
SHLIB_LD="ld -Bshareable -x"
SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
|
| ︙ | ︙ | |||
12613 12614 12615 12616 12617 12618 12619 | case $system in AIX-*) ;; BSD/OS*) ;; IRIX*) ;; | | | 12655 12656 12657 12658 12659 12660 12661 12662 12663 12664 12665 12666 12667 12668 12669 | case $system in AIX-*) ;; BSD/OS*) ;; IRIX*) ;; NetBSD-*|FreeBSD-*) ;; Rhapsody-*|Darwin-*) ;; RISCos-*) ;; SCO_SV-3.2*) ;; |
| ︙ | ︙ |
Changes to unix/mkLinks.
| ︙ | ︙ | |||
1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 |
if test -r join.n; then
rm -f join.n.*
$ZIP join.n
fi
if test -r lappend.n; then
rm -f lappend.n.*
$ZIP lappend.n
fi
if test -r library.n; then
rm -f library.n.*
$ZIP library.n
rm -f auto_execok.n auto_execok.n.*
rm -f auto_import.n auto_import.n.*
rm -f auto_load.n auto_load.n.*
| > > > > | 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 |
if test -r join.n; then
rm -f join.n.*
$ZIP join.n
fi
if test -r lappend.n; then
rm -f lappend.n.*
$ZIP lappend.n
fi
if test -r lassign.n; then
rm -f lassign.n.*
$ZIP lassign.n
fi
if test -r library.n; then
rm -f library.n.*
$ZIP library.n
rm -f auto_execok.n auto_execok.n.*
rm -f auto_import.n auto_import.n.*
rm -f auto_load.n auto_load.n.*
|
| ︙ | ︙ |
Changes to unix/tcl.m4.
| ︙ | ︙ | |||
832 833 834 835 836 837 838 |
CC=${CC}_r
fi
AC_MSG_RESULT(Using $CC for compiling with threads)
fi
LIBS="$LIBS -lc"
# AIX-5 uses ELF style dynamic libraries
SHLIB_CFLAGS=""
| < < < < < < < < < < < < < < < < < < < < < < > > > > > > > > > > > > > > > > > > > > > > < > > > > > > > > > > > > > > > < < < < < < < < < < < < < < | 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 |
CC=${CC}_r
fi
AC_MSG_RESULT(Using $CC for compiling with threads)
fi
LIBS="$LIBS -lc"
# AIX-5 uses ELF style dynamic libraries
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"
LDFLAGS=""
LD_LIBRARY_PATH_VAR="LIBPATH"
# Check to enable 64-bit flags for compiler/linker
if test "$do64bit" = "yes" ; then
if test "$GCC" = "yes" ; then
AC_MSG_WARN("64bit mode not supported with GCC on $system")
else
do64bit_ok=yes
EXTRA_CFLAGS="-q64"
LDFLAGS="-q64"
RANLIB="${RANLIB} -X64"
AR="${AR} -X64"
SHLIB_LD_FLAGS="-b64"
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
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
SHLIB_LD="${TCL_SRC_DIR}/unix/ldAix /bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry ${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-*)
if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes" ; then
# AIX requires the _r compiler when gcc isn't being used
if test "${CC}" != "cc_r" ; then
CC=${CC}_r
fi
AC_MSG_RESULT(Using $CC for compiling with threads)
fi
LIBS="$LIBS -lc"
SHLIB_CFLAGS=""
SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
LDFLAGS=""
CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
LD_LIBRARY_PATH_VAR="LIBPATH"
TCL_NEEDS_EXP_FILE=1
TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.exp'
# AIX v<=4.1 has some different flags than 4.2+
if test "$system" = "AIX-4.1" -o "`uname -v`" -lt "4" ; then
AC_LIBOBJ([tclLoadAix])
DL_LIBS="-lld"
fi
# Check to enable 64-bit flags for compiler/linker
if test "$do64bit" = "yes" ; then
if test "$GCC" = "yes" ; then
AC_MSG_WARN("64bit mode not supported with GCC on $system")
else
do64bit_ok=yes
EXTRA_CFLAGS="-q64"
LDFLAGS="-q64"
RANLIB="${RANLIB} -X64"
AR="${AR} -X64"
SHLIB_LD_FLAGS="-b64"
fi
fi
SHLIB_LD="${TCL_SRC_DIR}/unix/ldAix /bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry ${SHLIB_LD_FLAGS}"
# 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_SUFFIX=".so"
|
| ︙ | ︙ | |||
1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 |
fi
;;
Linux*)
SHLIB_CFLAGS="-fPIC"
SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
# 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.
| > < | | 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 |
fi
;;
Linux*)
SHLIB_CFLAGS="-fPIC"
SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
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"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
LDFLAGS="-Wl,--export-dynamic"
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
|
| ︙ | ︙ | |||
1218 1219 1220 1221 1222 1223 1224 | SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="-Wl,-Bexport" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; | | | 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 | SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="-Wl,-Bexport" 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="" SHLIB_SUFFIX=".so" |
| ︙ | ︙ | |||
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 |
])
# FreeBSD doesn't handle version numbers with dots.
UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
TCL_LIB_VERSIONS_OK=nodots
;;
FreeBSD-*)
# FreeBSD 3.* and greater have ELF.
SHLIB_CFLAGS="-fPIC"
SHLIB_LD="ld -Bshareable -x"
SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
| > > > > > > > > > > > > > > > > > > > > > > > > > | 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 |
])
# FreeBSD doesn't handle version numbers with dots.
UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
TCL_LIB_VERSIONS_OK=nodots
;;
OpenBSD-*)
SHLIB_LD="${CC} -shared"
SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
LDFLAGS=""
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
AC_MSG_CHECKING(for ELF)
AC_EGREP_CPP(yes, [
#ifdef __ELF__
yes
#endif
],
[AC_MSG_RESULT(yes)
SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1.0'],
[AC_MSG_RESULT(no)
SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1.0']
)
# OpenBSD doesn't do version numbers with dots.
UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
TCL_LIB_VERSIONS_OK=nodots
;;
FreeBSD-*)
# FreeBSD 3.* and greater have ELF.
SHLIB_CFLAGS="-fPIC"
SHLIB_LD="ld -Bshareable -x"
SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
|
| ︙ | ︙ | |||
1697 1698 1699 1700 1701 1702 1703 | case $system in AIX-*) ;; BSD/OS*) ;; IRIX*) ;; | | | 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 | case $system in AIX-*) ;; BSD/OS*) ;; IRIX*) ;; NetBSD-*|FreeBSD-*) ;; Rhapsody-*|Darwin-*) ;; RISCos-*) ;; SCO_SV-3.2*) ;; |
| ︙ | ︙ |
Changes to unix/tclUnixChan.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* * tclUnixChan.c * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* * tclUnixChan.c * * 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. * * RCS: @(#) $Id: tclUnixChan.c,v 1.42.4.1 2004/02/07 05:48:04 dgp Exp $ */ #include "tclInt.h" /* Internal definitions for Tcl. */ #include "tclPort.h" /* Portability features for Tcl. */ #include "tclIO.h" /* To get Channel type declaration. */ /* |
| ︙ | ︙ | |||
1773 1774 1775 1776 1777 1778 1779 | case O_RDWR: channelPermissions = (TCL_READABLE | TCL_WRITABLE); break; default: /* * This may occurr if modeString was "", for example. */ | | > > > | 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 |
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
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) {
|
| ︙ | ︙ | |||
1885 1886 1887 1888 1889 1890 1891 |
FileState *fsPtr;
char channelName[16 + TCL_INTEGER_SPACE];
int fd = (int) handle;
Tcl_ChannelType *channelTypePtr;
#ifdef DEPRECATED
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
#endif /* DEPRECATED */
| | | > > | | > | 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 |
FileState *fsPtr;
char channelName[16 + TCL_INTEGER_SPACE];
int fd = (int) handle;
Tcl_ChannelType *channelTypePtr;
#ifdef DEPRECATED
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
#endif /* DEPRECATED */
struct sockaddr sockaddr;
socklen_t sockaddrLen = sizeof(sockaddr);
if (mode == 0) {
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
if (isatty(fd)) {
fsPtr = TtyInit(fd, 0);
channelTypePtr = &ttyChannelType;
sprintf(channelName, "serial%d", fd);
} else
#endif /* SUPPORTS_TTY */
if (getsockname(fd, (struct sockaddr *)&sockaddr, &sockaddrLen) == 0
&& sockaddrLen > 0
&& sockaddr.sa_family == AF_INET) {
return MakeTcpClientChannelMode((ClientData) fd, mode);
} else {
channelTypePtr = &fileChannelType;
fsPtr = (FileState *) ckalloc((unsigned) sizeof(FileState));
sprintf(channelName, "file%d", fd);
}
|
| ︙ | ︙ | |||
2992 2993 2994 2995 2996 2997 2998 | return (Tcl_Channel) NULL; } fd = 2; mode = TCL_WRITABLE; bufMode = "none"; break; default: | | | 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 |
return (Tcl_Channel) 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);
|
| ︙ | ︙ | |||
3184 3185 3186 3187 3188 3189 3190 |
}
/*
* Initialize the ready masks and compute the mask offsets.
*/
if (fd >= FD_SETSIZE) {
| | | 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 |
}
/*
* Initialize the ready masks and compute the mask offsets.
*/
if (fd >= FD_SETSIZE) {
Tcl_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 = 1 << (fd%(NBBY*sizeof(fd_mask)));
/*
* Loop in a mini-event loop of our own, waiting for either the
|
| ︙ | ︙ | |||
3313 3314 3315 3316 3317 3318 3319 |
/*
* 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.
*/
| | | > | 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 |
/*
* 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) {
Tcl_Panic("file info ptr not on thread channel list");
}
#endif /* DEPRECATED */
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ |
Changes to unix/tclUnixFCmd.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* * tclUnixFCmd.c * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* * tclUnixFCmd.c * * 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. * * RCS: @(#) $Id: tclUnixFCmd.c,v 1.29.2.3 2004/02/07 05:48:04 dgp Exp $ * * 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. * |
| ︙ | ︙ | |||
106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
typedef int (TraversalProc) _ANSI_ARGS_((Tcl_DString *srcPtr,
Tcl_DString *dstPtr, CONST Tcl_StatBuf *statBufPtr, int type,
Tcl_DString *errorPtr));
/*
* Constants and variables necessary for file attributes subcommand.
*/
enum {
UNIX_GROUP_ATTRIBUTE,
UNIX_OWNER_ATTRIBUTE,
UNIX_PERMISSIONS_ATTRIBUTE,
#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
| > > > > | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
typedef int (TraversalProc) _ANSI_ARGS_((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.
*/
enum {
UNIX_GROUP_ATTRIBUTE,
UNIX_OWNER_ATTRIBUTE,
UNIX_PERMISSIONS_ATTRIBUTE,
#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
|
| ︙ | ︙ | |||
467 468 469 470 471 472 473 |
{
int srcFd;
int dstFd;
u_int blockSize; /* Optimal I/O blocksize for filesystem */
char *buffer; /* Data buffer for copy */
size_t nread;
| > > > > > > | | | 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 |
{
int srcFd;
int dstFd;
u_int blockSize; /* Optimal I/O blocksize for filesystem */
char *buffer; /* Data buffer for copy */
size_t nread;
#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 BINMODE, /* INTL: Native. */
statBufPtr->st_mode);
if (dstFd < 0) {
close(srcFd);
return TCL_ERROR;
}
#ifdef HAVE_ST_BLKSIZE
|
| ︙ | ︙ |
Changes to unix/tclUnixFile.c.
1 2 3 4 5 6 7 8 9 10 11 | /* * tclUnixFile.c -- * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * tclUnixFile.c -- * * 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. * * RCS: @(#) $Id: tclUnixFile.c,v 1.32.4.2 2004/02/07 05:48:09 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" static int NativeMatchType(CONST char* nativeName, Tcl_GlobTypeData *types); |
| ︙ | ︙ | |||
205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
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;
fileNamePtr = Tcl_FSGetTranslatedPath(interp, pathPtr);
if (fileNamePtr == NULL) {
return TCL_ERROR;
}
if (pattern == NULL || (*pattern == '\0')) {
| > > > > > | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
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;
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')) {
|
| ︙ | ︙ | |||
263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
native = Tcl_UtfToExternalDString(NULL, dirName, -1, &ds);
if ((TclOSstat(native, &statBuf) != 0) /* INTL: Native. */
|| !S_ISDIR(statBuf.st_mode)) {
Tcl_DStringFree(&dsOrig);
Tcl_DStringFree(&ds);
return TCL_OK;
}
d = opendir(native); /* INTL: Native. */
if (d == NULL) {
Tcl_DStringFree(&ds);
Tcl_ResetResult(interp);
| > | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
native = Tcl_UtfToExternalDString(NULL, dirName, -1, &ds);
if ((TclOSstat(native, &statBuf) != 0) /* INTL: Native. */
|| !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);
|
| ︙ | ︙ | |||
566 567 568 569 570 571 572 |
{
return TclOSlstat(Tcl_FSGetNativePath(pathPtr), bufPtr);
}
/*
*---------------------------------------------------------------------------
*
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | < < < < < < < < < < < < < < < < | 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 |
{
return TclOSlstat(Tcl_FSGetNativePath(pathPtr), bufPtr);
}
/*
*---------------------------------------------------------------------------
*
* TclpGetNativeCwd --
*
* This function replaces the library version of getcwd().
*
* Results:
* 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.
*
*----------------------------------------------------------------------
*/
ClientData
TclpGetNativeCwd(clientData)
ClientData clientData;
{
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.
*
*----------------------------------------------------------------------
*/
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. */
{
char buffer[MAXPATHLEN+1];
|
| ︙ | ︙ | |||
710 711 712 713 714 715 716 |
TclpObjLink(pathPtr, toPtr, linkAction)
Tcl_Obj *pathPtr;
Tcl_Obj *toPtr;
int linkAction;
{
if (toPtr != NULL) {
CONST char *src = Tcl_FSGetNativePath(pathPtr);
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > | | | | > > < < < < < > > > > > > > > > > > > > > > > | > > > | > > | 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 |
TclpObjLink(pathPtr, toPtr, linkAction)
Tcl_Obj *pathPtr;
Tcl_Obj *toPtr;
int linkAction;
{
if (toPtr != NULL) {
CONST char *src = Tcl_FSGetNativePath(pathPtr);
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 (access(target, F_OK) == -1) {
/* target doesn't exist */
errno = ENOENT;
return NULL;
}
if (target == NULL) {
return NULL;
}
}
if (access(src, F_OK) != -1) {
/* src exists */
errno = EEXIST;
return NULL;
}
/*
* Check symbolic link flag first, since we prefer to
* create these.
*/
if (linkAction & TCL_CREATE_SYMBOLIC_LINK) {
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;
}
} else {
errno = ENODEV;
return NULL;
}
return toPtr;
} else {
Tcl_Obj* linkPtr = NULL;
|
| ︙ | ︙ | |||
790 791 792 793 794 795 796 | * * Side effects: * None. * *--------------------------------------------------------------------------- */ Tcl_Obj* | | | | 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 |
*
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
Tcl_Obj*
TclpFilesystemPathType(pathPtr)
Tcl_Obj* pathPtr;
{
/* All native paths are of the same type */
return NULL;
}
/*
*---------------------------------------------------------------------------
|
| ︙ | ︙ |
Changes to unix/tclUnixInit.c.
1 2 3 4 5 6 7 8 9 | /* * tclUnixInit.c -- * * Contains the Unix-specific interpreter initialization functions. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright (c) 1999 by Scriptics Corporation. * All rights reserved. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | /* * tclUnixInit.c -- * * Contains the Unix-specific interpreter initialization functions. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright (c) 1999 by Scriptics Corporation. * All rights reserved. * * RCS: @(#) $Id: tclUnixInit.c,v 1.35.2.1 2004/02/07 05:48:10 dgp Exp $ */ #if defined(HAVE_CFBUNDLE) #include <CoreFoundation/CoreFoundation.h> #endif #include "tclInt.h" #include "tclPort.h" |
| ︙ | ︙ | |||
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
*
*---------------------------------------------------------------------------
*/
void
TclpInitPlatform()
{
tclPlatform = TCL_PLATFORM_UNIX;
/*
* 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;
| > > > > | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
*
*---------------------------------------------------------------------------
*/
void
TclpInitPlatform()
{
#ifdef DJGPP
tclPlatform = TCL_PLATFORM_WINDOWS;
#else
tclPlatform = TCL_PLATFORM_UNIX;
#endif
/*
* 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;
|
| ︙ | ︙ | |||
334 335 336 337 338 339 340 |
/*
* The variable path holds an absolute path. Take care not to
* overwrite pathv[0] since that might produce a relative path.
*/
if (path != NULL) {
| > > > | > > > > > > > > > > > > > > > | 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 |
/*
* 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);
|
| ︙ | ︙ | |||
389 390 391 392 393 394 395 396 397 398 399 400 401 402 |
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 *) 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.
| > | 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 |
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.
|
| ︙ | ︙ |
Changes to unix/tclUnixNotfy.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* * 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. * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* * 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. * * 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. * * RCS: @(#) $Id: tclUnixNotfy.c,v 1.12.2.2 2004/02/07 05:48:11 dgp Exp $ */ #include "tclInt.h" #include "tclPort.h" #include <signal.h> extern TclStubs tclStubs; |
| ︙ | ︙ | |||
206 207 208 209 210 211 212 |
* Start the Notifier thread if necessary.
*/
Tcl_MutexLock(¬ifierMutex);
if (notifierCount == 0) {
if (Tcl_CreateThread(¬ifierThread, NotifierThreadProc, NULL,
TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS) != TCL_OK) {
| | | 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
* Start the Notifier thread if necessary.
*/
Tcl_MutexLock(¬ifierMutex);
if (notifierCount == 0) {
if (Tcl_CreateThread(¬ifierThread, NotifierThreadProc, NULL,
TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS) != TCL_OK) {
Tcl_Panic("Tcl_InitNotifier: unable to start notifier thread");
}
}
notifierCount++;
/*
* Wait for the notifier pipe to be created.
*/
|
| ︙ | ︙ | |||
259 260 261 262 263 264 265 |
/*
* 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) {
if (triggerPipe < 0) {
| | | 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
/*
* 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) {
if (triggerPipe < 0) {
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
|
| ︙ | ︙ | |||
865 866 867 868 869 870 871 |
int i, status, index, bit, numFdBits, receivePipe;
long found, word;
struct timeval poll = {0., 0.}, *timePtr;
int maskSize = 3 * ((MASK_SIZE) / sizeof(long)) * sizeof(fd_mask);
char buf[2];
if (pipe(fds) != 0) {
| | | | | | | 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 |
int i, status, index, bit, numFdBits, receivePipe;
long found, word;
struct timeval poll = {0., 0.}, *timePtr;
int maskSize = 3 * ((MASK_SIZE) / sizeof(long)) * sizeof(fd_mask);
char buf[2];
if (pipe(fds) != 0) {
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) {
Tcl_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) {
Tcl_Panic("NotifierThreadProc: could not make trigger pipe non blocking.");
}
#else
if (ioctl(receivePipe, (int) FIONBIO, &status) < 0) {
Tcl_Panic("NotifierThreadProc: could not make receive pipe non blocking.");
}
if (ioctl(fds[1], (int) FIONBIO, &status) < 0) {
Tcl_Panic("NotifierThreadProc: could not make trigger pipe non blocking.");
}
#endif
/*
* Install the write end of the pipe into the global variable.
*/
|
| ︙ | ︙ |
Changes to unix/tclUnixPort.h.
| ︙ | ︙ | |||
15 16 17 18 19 20 21 | * * 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. * | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | * * 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. * * RCS: @(#) $Id: tclUnixPort.h,v 1.28.2.2 2004/02/07 05:48:11 dgp Exp $ */ #ifndef _TCLUNIXPORT #define _TCLUNIXPORT #ifndef _TCLINT # include "tclInt.h" |
| ︙ | ︙ | |||
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 | /* * Not all systems declare the errno variable in errno.h. so this * file does it explicitly. The list of system error messages also * isn't generally declared in a header file anywhere. */ extern int errno; /* * Not all systems declare all the errors that Tcl uses! Provide some * work-arounds... */ #ifndef EOVERFLOW | > > | 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 | /* * Not all systems declare the errno variable in errno.h. so this * file does it explicitly. The list of system error messages also * isn't generally declared in a header file anywhere. */ #ifdef NO_ERRNO extern int errno; #endif /* NO_ERRNO */ /* * Not all systems declare all the errors that Tcl uses! Provide some * work-arounds... */ #ifndef EOVERFLOW |
| ︙ | ︙ | |||
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 | /* * The default platform eol translation on Unix is TCL_TRANSLATE_LF. */ #ifdef DJGPP #define TCL_PLATFORM_TRANSLATION TCL_TRANSLATE_CRLF #else #define TCL_PLATFORM_TRANSLATION TCL_TRANSLATE_LF #endif /* * The following macros have trivial definitions, allowing generic code to * address platform-specific issues. */ #define TclpGetPid(pid) ((unsigned long) (pid)) #define TclpReleaseFile(file) /* Nothing. */ /* | > | < < | | | < | 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 | /* * The default platform eol translation on Unix is TCL_TRANSLATE_LF. */ #ifdef DJGPP #define TCL_PLATFORM_TRANSLATION TCL_TRANSLATE_CRLF typedef int socklen_t; #else #define TCL_PLATFORM_TRANSLATION TCL_TRANSLATE_LF #endif /* * The following macros have trivial definitions, allowing generic code to * address platform-specific issues. */ #define TclpGetPid(pid) ((unsigned long) (pid)) #define TclpReleaseFile(file) /* Nothing. */ /* * The following defines wrap the system memory allocation routines. */ #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 * functions. */ #define TclpExit exit |
| ︙ | ︙ |
Changes to unix/tclUnixThrd.c.
| ︙ | ︙ | |||
912 913 914 915 916 917 918 |
struct lock {
Tcl_Mutex tlock;
pthread_mutex_t plock;
} *lockPtr;
lockPtr = malloc(sizeof(struct lock));
if (lockPtr == NULL) {
| | | 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 |
struct lock {
Tcl_Mutex tlock;
pthread_mutex_t plock;
} *lockPtr;
lockPtr = malloc(sizeof(struct lock));
if (lockPtr == NULL) {
Tcl_Panic("could not allocate lock");
}
lockPtr->tlock = (Tcl_Mutex) &lockPtr->plock;
pthread_mutex_init(&lockPtr->plock, NULL);
return &lockPtr->tlock;
}
static void
|
| ︙ | ︙ |
Changes to unix/tclXtNotify.c.
1 2 3 4 5 6 7 8 9 10 11 | /* * tclXtNotify.c -- * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * tclXtNotify.c -- * * 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. * * RCS: @(#) $Id: tclXtNotify.c,v 1.4.34.1 2004/02/07 05:48:11 dgp Exp $ */ #include <X11/Intrinsic.h> #include <tclInt.h> /* * This structure is used to keep track of the notifier info for a |
| ︙ | ︙ | |||
131 132 133 134 135 136 137 |
if (appContext != NULL) {
/*
* We already have a context. We do not allow switching contexts
* after initialization, so we panic.
*/
| | | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
if (appContext != NULL) {
/*
* 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.
|
| ︙ | ︙ |
Changes to win/Makefile.in.
1 2 3 4 5 6 7 | # # 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. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # # 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. # # RCS: @(#) $Id: Makefile.in,v 1.71.2.3 2004/02/07 05:48:11 dgp Exp $ 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 |
| ︙ | ︙ | |||
464 465 466 467 468 469 470 | if [ ! -d $$i ] ; then \ echo "Making directory $$i"; \ $(MKDIR) $$i; \ chmod 755 $$i; \ else true; \ fi; \ done; | | | 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 | if [ ! -d $$i ] ; then \ echo "Making directory $$i"; \ $(MKDIR) $$i; \ chmod 755 $$i; \ else true; \ fi; \ done; @for i in dde1.3 reg1.1; \ do \ if [ ! -d $(LIB_INSTALL_DIR)/$$i ] ; then \ echo "Making directory $(LIB_INSTALL_DIR)/$$i"; \ $(MKDIR) $(LIB_INSTALL_DIR)/$$i; \ else true; \ fi; \ done; |
| ︙ | ︙ | |||
488 489 490 491 492 493 494 | if [ -f $$i ]; then \ echo "Installing $$i to $(LIB_INSTALL_DIR)/"; \ $(COPY) $$i "$(LIB_INSTALL_DIR)"; \ fi; \ done @if [ -f $(DDE_DLL_FILE) ]; then \ echo installing $(DDE_DLL_FILE); \ | | | | | 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 | if [ -f $$i ]; then \ echo "Installing $$i to $(LIB_INSTALL_DIR)/"; \ $(COPY) $$i "$(LIB_INSTALL_DIR)"; \ fi; \ done @if [ -f $(DDE_DLL_FILE) ]; then \ echo installing $(DDE_DLL_FILE); \ $(COPY) $(DDE_DLL_FILE) $(LIB_INSTALL_DIR)/dde1.3; \ $(COPY) $(ROOT_DIR)/library/dde/pkgIndex.tcl \ $(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.3; \ fi @if [ -f $(REG_DLL_FILE) ]; then \ echo installing $(REG_DLL_FILE); \ $(COPY) $(REG_DLL_FILE) $(LIB_INSTALL_DIR)/reg1.1; \ $(COPY) $(ROOT_DIR)/library/reg/pkgIndex.tcl \ $(LIB_INSTALL_DIR)/reg1.1; \ fi |
| ︙ | ︙ | |||
517 518 519 520 521 522 523 | do \ if [ ! -d $$i ] ; then \ echo "Making directory $$i"; \ $(MKDIR) $$i; \ else true; \ fi; \ done; | | | 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 | do \ if [ ! -d $$i ] ; then \ echo "Making directory $$i"; \ $(MKDIR) $$i; \ else true; \ fi; \ done; @for i in http1.0 http2.4 opt0.4 encoding msgcat1.4 tcltest2.2; \ do \ if [ ! -d $(SCRIPT_INSTALL_DIR)/$$i ] ; then \ echo "Making directory $(SCRIPT_INSTALL_DIR)/$$i"; \ $(MKDIR) $(SCRIPT_INSTALL_DIR)/$$i; \ else true; \ fi; \ done; |
| ︙ | ︙ | |||
551 552 553 554 555 556 557 | $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/http2.4"; \ done; @echo "Installing library opt0.4 directory"; @for j in $(ROOT_DIR)/library/opt/*.tcl; \ do \ $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/opt0.4"; \ done; | | | | 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 | $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/http2.4"; \ done; @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.4 directory"; @for j in $(ROOT_DIR)/library/msgcat/*.tcl; \ do \ $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/msgcat1.4"; \ 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 encodings"; |
| ︙ | ︙ |
Changes to win/configure.
| ︙ | ︙ | |||
1273 1274 1275 1276 1277 1278 1279 | TCL_VERSION=8.5 TCL_MAJOR_VERSION=8 TCL_MINOR_VERSION=5 TCL_PATCH_LEVEL="a0" VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION | | | | 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 | TCL_VERSION=8.5 TCL_MAJOR_VERSION=8 TCL_MINOR_VERSION=5 TCL_PATCH_LEVEL="a0" VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION TCL_DDE_VERSION=1.3 TCL_DDE_MAJOR_VERSION=1 TCL_DDE_MINOR_VERSION=3 TCL_DDE_PATCH_LEVEL="" DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION TCL_REG_VERSION=1.1 TCL_REG_MAJOR_VERSION=1 TCL_REG_MINOR_VERSION=1 TCL_REG_PATCH_LEVEL="" |
| ︙ | ︙ |
Changes to win/configure.in.
1 2 3 4 5 | #! /bin/bash -norc # This file is an input file used by the GNU "autoconf" program to # generate the file "configure", which is run during Tcl installation # to configure the system for the local environment. # | | | | | 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 | #! /bin/bash -norc # This file is an input file used by the GNU "autoconf" program to # generate the file "configure", which is run during Tcl installation # to configure the system for the local environment. # # RCS: @(#) $Id: configure.in,v 1.74.2.2 2004/02/07 05:48:12 dgp Exp $ AC_INIT(../generic/tcl.h) AC_PREREQ(2.57) # 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=5 TCL_PATCH_LEVEL="a0" VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION TCL_DDE_VERSION=1.3 TCL_DDE_MAJOR_VERSION=1 TCL_DDE_MINOR_VERSION=3 TCL_DDE_PATCH_LEVEL="" DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION TCL_REG_VERSION=1.1 TCL_REG_MAJOR_VERSION=1 TCL_REG_MINOR_VERSION=1 TCL_REG_PATCH_LEVEL="" |
| ︙ | ︙ |
Changes to win/makefile.bc.
| ︙ | ︙ | |||
123 124 125 126 127 128 129 | ###################################################################### NAMEPREFIX = tcl STUBPREFIX = $(NAMEPREFIX)stub DOTVERSION = 8.5 VERSION = 85 | | | | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | ###################################################################### NAMEPREFIX = tcl STUBPREFIX = $(NAMEPREFIX)stub DOTVERSION = 8.5 VERSION = 85 DDEVERSION = 13 DDEDOTVERSION = 1.3 REGVERSION = 11 REGDOTVERSION = 1.1 BINROOT = .. !IF "$(NODEBUG)" == "1" TMPDIRNAME = Release |
| ︙ | ︙ | |||
429 430 431 432 433 434 435 | -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\http2.4" -@copy "$(ROOT)\library\http\http.tcl" "$(SCRIPT_INSTALL_DIR)\http2.4" -@copy "$(ROOT)\library\http\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\http2.4" @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" | | | | | | | | | 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 | -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\http2.4" -@copy "$(ROOT)\library\http\http.tcl" "$(SCRIPT_INSTALL_DIR)\http2.4" -@copy "$(ROOT)\library\http\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\http2.4" @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.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.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 $(TCLDDEDLLNAME) -@$(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" @echo installing encoding files -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\encoding" -@copy "$(ROOT)\library\encoding\*.enc" "$(SCRIPT_INSTALL_DIR)\encoding" |
| ︙ | ︙ |
Changes to win/makefile.vc.
1 2 3 4 5 6 7 8 9 10 11 | #------------------------------------------------------------------------------ # makefile.vc -- # # Microsoft Visual C++ makefile for use with nmake.exe v1.62+ (VC++ 5.0+) # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # Copyright (c) 1995-1996 Sun Microsystems, Inc. # Copyright (c) 1998-2000 Ajuba Solutions. # Copyright (c) 2001 ActiveState Corporation. | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #------------------------------------------------------------------------------ # makefile.vc -- # # Microsoft Visual C++ makefile for use with nmake.exe v1.62+ (VC++ 5.0+) # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # Copyright (c) 1995-1996 Sun Microsystems, Inc. # Copyright (c) 1998-2000 Ajuba Solutions. # Copyright (c) 2001 ActiveState Corporation. # Copyright (c) 2001-2004 David Gravereaux. # #------------------------------------------------------------------------------ # RCS: @(#) $Id: makefile.vc,v 1.107.2.4 2004/02/07 05:48:12 dgp Exp $ #------------------------------------------------------------------------------ !if "$(MSVCDIR)" == "" MSG = ^ You'll need to run vcvars32.bat from Developer Studio, first, to setup^ the environment. Jump to this line to read the new instructions. !error $(MSG) |
| ︙ | ︙ | |||
89 90 91 92 93 94 95 96 97 98 99 100 101 102 | # Sets optional memory and bytecode compiler debugging code added # to the core. The default is for none. Any combination of the # above may be used (comma separated). 'none' will over-ride # everything to nothing. # # memdbg = Enables the debugging memory allocator. # compdbg = Enables byte compilation logging. # # MACHINE=(IX86|IA64|ALPHA) # Set the machine type used for the compiler, linker, and # resource compiler. This hook is needed to tell the tools # when alternate platforms are requested. IX86 is the default # when not specified. # | > > > > > > > > | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | # Sets optional memory and bytecode compiler debugging code added # to the core. The default is for none. Any combination of the # above may be used (comma separated). 'none' will over-ride # everything to nothing. # # memdbg = Enables the debugging memory allocator. # compdbg = Enables byte compilation logging. # # CHECKS=nodep,fullwarn,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. # # MACHINE=(IX86|IA64|ALPHA) # Set the machine type used for the compiler, linker, and # resource compiler. This hook is needed to tell the tools # when alternate platforms are requested. IX86 is the default # when not specified. # |
| ︙ | ︙ | |||
155 156 157 158 159 160 161 | !error $(MSG) !endif PROJECT = tcl !include "rules.vc" STUBPREFIX = $(PROJECT)stub | > > | > > > > > > > > > | | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | !error $(MSG) !endif PROJECT = tcl !include "rules.vc" STUBPREFIX = $(PROJECT)stub !if [nmakehlp -g ../generic/tcl.h TCL_VERSION] == 85 DOTVERSION = 8.5 !elseif [nmakehlp -g ../generic/tcl.h TCL_VERSION] == 86 DOTVERSION = 8.6 !elseif [nmakehlp -g ../generic/tcl.h TCL_VERSION] == 90 DOTVERSION = 9.0 !elseif [nmakehlp -g ../generic/tcl.h TCL_VERSION] == 0 MSG =^ Can't get version string from ../generic/tcl.h !error $(MSG) !endif VERSION = $(DOTVERSION:.=) DDEDOTVERSION = 1.3 DDEVERSION = $(DDEDOTVERSION:.=) REGDOTVERSION = 1.1 REGVERSION = $(REGDOTVERSION:.=) BINROOT = . ROOT = .. |
| ︙ | ︙ | |||
329 330 331 332 333 334 335 | ### This cranks the optimization level to maximize speed cdebug = -O2 -Op -Gs !else cdebug = !endif !else if "$(MACHINE)" == "IA64" ### Warnings are too many, can't support warnings into errors. | | | | > > > > > > > | 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 | ### This cranks the optimization level to maximize speed cdebug = -O2 -Op -Gs !else cdebug = !endif !else if "$(MACHINE)" == "IA64" ### Warnings are too many, can't support warnings into errors. cdebug = -Z7 -Od -GZ !else cdebug = -Z7 -WX -Od -GZ !endif ### Declarations common to all compiler options cflags = -nologo -c -YX -Fp$(TMP_DIR)^\ !if $(FULLWARNINGS) cflags = $(cflags) -W4 !else cflags = $(cflags) -W3 !endif !if $(PENT_0F_ERRATA) cflags = $(cflags) -QI0f !endif !if $(ITAN_B_ERRATA) cflags = $(cflags) -QIA64_Bx |
| ︙ | ︙ | |||
379 380 381 382 383 384 385 386 387 388 389 390 391 392 | ldebug = -debug:full -debugtype:cv !else ldebug = -release -opt:ref -opt:icf,3 !endif ### Declarations common to all linker options lflags = -nologo -machine:$(MACHINE) $(ldebug) !if $(PROFILE) lflags = $(lflags) -profile !endif !if $(ALIGN98_HACK) && !$(STATIC_BUILD) ### Align sections for PE size savings. | > > > > | 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 | ldebug = -debug:full -debugtype:cv !else ldebug = -release -opt:ref -opt:icf,3 !endif ### Declarations common to all linker options lflags = -nologo -machine:$(MACHINE) $(ldebug) !if $(FULLWARNINGS) lflags = $(lflags) -warn:3 !endif !if $(PROFILE) lflags = $(lflags) -profile !endif !if $(ALIGN98_HACK) && !$(STATIC_BUILD) ### Align sections for PE size savings. |
| ︙ | ︙ | |||
400 401 402 403 404 405 406 | lflags = $(lflags) -ws:aggressive !endif dlllflags = $(lflags) -dll conlflags = $(lflags) -subsystem:console guilflags = $(lflags) -subsystem:windows | | | 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 | lflags = $(lflags) -ws:aggressive !endif dlllflags = $(lflags) -dll conlflags = $(lflags) -subsystem:console guilflags = $(lflags) -subsystem:windows baselibs = kernel32.lib user32.lib #--------------------------------------------------------------------- # TclTest flags #--------------------------------------------------------------------- !IF "$(TESTPAT)" != "" |
| ︙ | ︙ | |||
604 605 606 607 608 609 610 | #--------------------------------------------------------------------- # Special case object file targets #--------------------------------------------------------------------- $(TMP_DIR)\testMain.obj: $(WINDIR)\tclAppInit.c | < | < > | < | 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 | #--------------------------------------------------------------------- # Special case object file targets #--------------------------------------------------------------------- $(TMP_DIR)\testMain.obj: $(WINDIR)\tclAppInit.c $(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$@ $? $(TMP_DIR)\tclTestObj.obj: $(GENERICDIR)\tclTestObj.c $(cc32) $(TCL_CFLAGS) -Fo$@ $? |
| ︙ | ︙ | |||
634 635 636 637 638 639 640 | -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 | < | < > | < | 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 | -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 $(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) $(TCL_CFLAGS) -DTCL_THREADS=1 -DSTATIC_BUILD -Fo$@ $? |
| ︙ | ︙ | |||
721 722 723 724 725 726 727 |
{$(COMPATDIR)}.c{$(TMP_DIR)}.obj::
$(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<<
$<
<<
{$(WINDIR)}.rc{$(TMP_DIR)}.res:
| | < < < < | < < | < | | 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 |
{$(COMPATDIR)}.c{$(TMP_DIR)}.obj::
$(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<<
$<
<<
{$(WINDIR)}.rc{$(TMP_DIR)}.res:
$(rc32) -fo $@ -r -i "$(GENERICDIR)" \
-d DEBUG=$(DEBUG) -d TCL_THREADS=$(TCL_THREADS) \
-d STATIC_BUILD=$(STATIC_BUILD) \
$<
.SUFFIXES:
.SUFFIXES:.c .rc
#---------------------------------------------------------------------
# Installation.
|
| ︙ | ︙ | |||
769 770 771 772 773 774 775 | "$(SCRIPT_INSTALL_DIR)\http1.0\" @echo installing http2.4 @$(CPY) "$(ROOT)\library\http\*.tcl" \ "$(SCRIPT_INSTALL_DIR)\http2.4\" @echo installing opt0.4 @$(CPY) "$(ROOT)\library\opt\*.tcl" \ "$(SCRIPT_INSTALL_DIR)\opt0.4\" | | | | 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 | "$(SCRIPT_INSTALL_DIR)\http1.0\" @echo installing http2.4 @$(CPY) "$(ROOT)\library\http\*.tcl" \ "$(SCRIPT_INSTALL_DIR)\http2.4\" @echo installing opt0.4 @$(CPY) "$(ROOT)\library\opt\*.tcl" \ "$(SCRIPT_INSTALL_DIR)\opt0.4\" @echo installing msgcat1.4 @$(CPY) "$(ROOT)\library\msgcat\*.tcl" \ "$(SCRIPT_INSTALL_DIR)\msgcat1.4\" @echo installing tcltest2.2 @$(CPY) "$(ROOT)\library\tcltest\*.tcl" \ "$(SCRIPT_INSTALL_DIR)\tcltest2.2\" @echo installing $(TCLDDELIBNAME) !if $(STATIC_BUILD) @$(CPY) "$(TCLDDELIB)" "$(LIB_INSTALL_DIR)\" !else |
| ︙ | ︙ | |||
814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 | #--------------------------------------------------------------------- # Clean up #--------------------------------------------------------------------- tidy: @echo Removing $(TCLLIB) ... @if exist $(TCLLIB) del $(TCLLIB) @echo Removing $(TCLSH) ... @if exist $(TCLSH) del $(TCLSH) @echo Removing $(TCLTEST) ... @if exist $(TCLTEST) del $(TCLTEST) @echo Removing $(TCLDDELIB) ... @if exist $(TCLDDELIB) del $(TCLDDELIB) @echo Removing $(TCLREGLIB) ... | > > > > | 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 | #--------------------------------------------------------------------- # 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) ... @if exist $(TCLTEST) del $(TCLTEST) @echo Removing $(TCLDDELIB) ... @if exist $(TCLDDELIB) del $(TCLDDELIB) @echo Removing $(TCLREGLIB) ... |
| ︙ | ︙ |
Changes to win/nmakehlp.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ---------------------------------------------------------------------------- * nmakehlp.c -- * * This is used to fix limitations within nmake and the environment. * * Copyright (c) 2002 by David Gravereaux. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * ---------------------------------------------------------------------------- | | > > > > | > > > > > > > | 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 |
/* ----------------------------------------------------------------------------
* nmakehlp.c --
*
* This is used to fix limitations within nmake and the environment.
*
* Copyright (c) 2002 by David Gravereaux.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* ----------------------------------------------------------------------------
* RCS: @(#) $Id: nmakehlp.c,v 1.1.6.1 2004/02/07 05:48:12 dgp Exp $
* ----------------------------------------------------------------------------
*/
#include <windows.h>
#pragma comment (lib, "user32.lib")
#pragma comment (lib, "kernel32.lib")
#include <stdio.h>
/* protos */
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);
DWORD WINAPI ReadFromPipe (LPVOID args);
/* globals */
#define CHUNK 25
#define STATICBUFFERSIZE 1000
typedef struct {
HANDLE pipe;
char buffer[STATICBUFFERSIZE];
} pipeinfo;
pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'};
pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'};
/* exitcodes: 0 == no, 1 == yes, 2 == error */
int
main (int argc, char *argv[])
{
char msg[300];
DWORD dwWritten;
int chars;
/* make sure children (cl.exe and link.exe) are kept quiet. */
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
/* Make sure the compiler and linker aren't effected by the outside world. */
SetEnvironmentVariable("CL", "");
SetEnvironmentVariable("LINK", "");
if (argc > 1 && *argv[1] == '-') {
switch (*(argv[1]+1)) {
case 'c':
if (argc != 3) {
chars = wsprintf(msg, "usage: %s -c <compiler option>\n"
"Tests for whether cl.exe supports an option\n"
|
| ︙ | ︙ | |||
70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
return 2;
} else if (argc == 3) {
/* if the string is blank, there is no match */
return 0;
} else {
return IsIn(argv[2], argv[3]);
}
}
}
chars = wsprintf(msg, "usage: %s -c|-l|-f ...\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]);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
| > > > > > > > > > | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
return 2;
} else if (argc == 3) {
/* if the string is blank, there is no match */
return 0;
} else {
return IsIn(argv[2], argv[3]);
}
case 'g':
if (argc == 2) {
chars = wsprintf(msg, "usage: %s -g <file> <string>\n"
"grep for a #define\n"
"exitcodes: integer of the found string (no decimals)\n", argv[0]);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
return 2;
}
return GrepForDefine(argv[2], argv[3]);
}
}
chars = wsprintf(msg, "usage: %s -c|-l|-f ...\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]);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
|
| ︙ | ︙ | |||
118 119 120 121 122 123 124 |
/* Same as above, but for the error side. */
CreatePipe(&Err.pipe, &h, &sa, 0);
DuplicateHandle(hProcess, h, hProcess, &si.hStdError,
0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
/* base command line */
| | | | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
/* Same as above, but for the error side. */
CreatePipe(&Err.pipe, &h, &sa, 0);
DuplicateHandle(hProcess, h, hProcess, &si.hStdError,
0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
/* base command line */
strcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X ");
/* append our option for testing */
strcat(cmdline, option);
/* filename to compile, which exists, but is nothing and empty. */
strcat(cmdline, " .\\nul");
ok = CreateProcess(
NULL, /* Module name. */
cmdline, /* Command line. */
NULL, /* Process handle not inheritable. */
NULL, /* Thread handle not inheritable. */
TRUE, /* yes, inherit handles. */
|
| ︙ | ︙ | |||
162 163 164 165 166 167 168 |
pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
/* block waiting for the process to end. */
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
| < < < < | 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
/* block waiting for the process to end. */
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
/* wait for our pipe to get done reading, should it be a little slow. */
WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
CloseHandle(pipeThreads[0]);
CloseHandle(pipeThreads[1]);
/* look for the commandline warning code in both streams. */
return !(strstr(Out.buffer, "D4002") != NULL || strstr(Err.buffer, "D4002") != NULL);
|
| ︙ | ︙ | |||
216 217 218 219 220 221 222 |
DuplicateHandle(hProcess, h, hProcess, &si.hStdError,
0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
/* base command line */
strcpy(cmdline, "link.exe -nologo ");
/* append our option for testing */
strcat(cmdline, option);
| < < | 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
DuplicateHandle(hProcess, h, hProcess, &si.hStdError,
0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
/* base command line */
strcpy(cmdline, "link.exe -nologo ");
/* append our option for testing */
strcat(cmdline, option);
ok = CreateProcess(
NULL, /* Module name. */
cmdline, /* Command line. */
NULL, /* Process handle not inheritable. */
NULL, /* Thread handle not inheritable. */
TRUE, /* yes, inherit handles. */
|
| ︙ | ︙ | |||
275 276 277 278 279 280 281 |
{
pipeinfo *pi = (pipeinfo *) args;
char *lastBuf = pi->buffer;
DWORD dwRead;
BOOL ok;
again:
| > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 |
{
pipeinfo *pi = (pipeinfo *) args;
char *lastBuf = pi->buffer;
DWORD dwRead;
BOOL ok;
again:
if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) {
CloseHandle(pi->pipe);
return -1;
}
ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L);
if (!ok || dwRead == 0) {
CloseHandle(pi->pipe);
return 0;
}
lastBuf += dwRead;
goto again;
return 0; /* makes the compiler happy */
}
int
IsIn (const char *string, const char *substring)
{
return (strstr(string, substring) != NULL);
}
/*
* Find a specified #define by name.
*
* If the line is '#define TCL_VERSION "8.5"', it returns
* 85 as the result.
*/
int
GrepForDefine (const char *file, const char *string)
{
FILE *f;
char s1[51], s2[51], s3[51];
int r = 0;
double d1;
f = fopen(file, "rt");
if (f == NULL) {
return 0;
}
do {
r = fscanf(f, "%50s", s1);
if (r == 1 && !strcmp(s1, "#define")) {
/* get next two words */
r = fscanf(f, "%50s %50s", s2, s3);
if (r != 2) continue;
/* is the first word what we're looking for? */
if (!strcmp(s2, string)) {
fclose(f);
/* add 1 past first double quote char. "8.5" */
d1 = atof(s3 + 1); /* 8.5 */
return ((int) (d1 * 10) & 0xFF); /* 85 */
}
}
} while (!feof(f));
fclose(f);
return 0;
}
|
Changes to win/rules.vc.
1 2 3 4 5 6 7 8 9 | #------------------------------------------------------------------------------ # rules.vc -- # # Microsoft Visual C++ makefile include for decoding the commandline # macros. This file does not need editing to build Tcl. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #------------------------------------------------------------------------------ # rules.vc -- # # Microsoft Visual C++ makefile include for decoding the commandline # macros. This file does not need editing to build Tcl. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # Copyright (c) 2001-2003 David Gravereaux. # #------------------------------------------------------------------------------ # RCS: @(#) $Id: rules.vc,v 1.12.2.3 2004/02/07 05:48:12 dgp Exp $ #------------------------------------------------------------------------------ !ifndef _RULES_VC _RULES_VC = 1 cc32 = $(CC) # built-in default. link32 = link |
| ︙ | ︙ | |||
260 261 262 263 264 265 266 267 268 269 270 271 272 273 | !message *** Doing compdbg TCL_COMPILE_DEBUG = 1 !else TCL_COMPILE_DEBUG = 0 !endif !endif #---------------------------------------------------------- # Set our defines now armed with our options. #---------------------------------------------------------- OPTDEFINES = -DTCL_CFGVAL_ENCODING=$(CFG_ENCODING) | > > > > > > > > > > > > > > > > > > > > > > > | 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 | !message *** Doing compdbg TCL_COMPILE_DEBUG = 1 !else TCL_COMPILE_DEBUG = 0 !endif !endif #---------------------------------------------------------- # Decode the checks requested. #---------------------------------------------------------- !if "$(CHECKS)" == "" || [nmakehlp -f "$(CHECKS)" "none"] TCL_NO_DEPRECATED = 0 FULLWARNINGS = 0 !else !if [nmakehlp -f $(CHECKS) "nodep"] !message *** Doing nodep check TCL_NO_DEPRECATED = 1 !else TCL_NO_DEPRECATED = 0 !endif !if [nmakehlp -f $(CHECKS) "fullwarn"] !message *** Doing full warnings check FULLWARNINGS = 1 !else FULLWARNINGS = 0 !endif !endif #---------------------------------------------------------- # Set our defines now armed with our options. #---------------------------------------------------------- OPTDEFINES = -DTCL_CFGVAL_ENCODING=$(CFG_ENCODING) |
| ︙ | ︙ | |||
282 283 284 285 286 287 288 289 290 291 292 293 294 295 | !if $(USE_THREAD_ALLOC) OPTDEFINES = $(OPTDEFINES) -DUSE_THREAD_ALLOC=1 !endif !endif !if $(STATIC_BUILD) OPTDEFINES = $(OPTDEFINES) -DSTATIC_BUILD !endif !if $(DEBUG) OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_DEBUG !elseif $(OPTIMIZING) OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_OPTIMIZED !endif !if $(PROFILE) | > > > | 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 | !if $(USE_THREAD_ALLOC) OPTDEFINES = $(OPTDEFINES) -DUSE_THREAD_ALLOC=1 !endif !endif !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 !elseif $(OPTIMIZING) OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_OPTIMIZED !endif !if $(PROFILE) |
| ︙ | ︙ | |||
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 |
# Get common info used when building extensions.
#----------------------------------------------------------
!if "$(PROJECT)" != "tcl"
!if !defined(TCLDIR)
!if exist("$(_INSTALLDIR)\include\tcl.h")
TCLINSTALL = 1
_TCLDIR = $(_INSTALLDIR)
!else
MSG=^
Don't know where tcl.h is. Set the TCLDIR macro.
!error $(MSG)
!endif
!else
_TCLDIR = $(TCLDIR:/=\)
!if exist("$(_TCLDIR)\include\tcl.h")
TCLINSTALL = 1
!elseif exist("$(_TCLDIR)\generic\tcl.h")
TCLINSTALL = 0
!else
MSG =^
Don't know where tcl.h is. The TCLDIR macro doesn't appear correct.
!error $(MSG)
!endif
!endif
| > > > > | > > | < | > > > > | | | < > > > > > > > > > > > > > > | < > > > > > > | 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 |
# Get common info used when building extensions.
#----------------------------------------------------------
!if "$(PROJECT)" != "tcl"
!if !defined(TCLDIR)
!if exist("$(_INSTALLDIR)\include\tcl.h")
TCLH = "$(_INSTALLDIR)\include\tcl.h"
TCLINSTALL = 1
_TCLDIR = $(_INSTALLDIR)
!else
MSG=^
Don't know where tcl.h is. Set the TCLDIR macro.
!error $(MSG)
!endif
!else
_TCLDIR = $(TCLDIR:/=\)
!if exist("$(_TCLDIR)\include\tcl.h")
TCLH = "$(_TCLDIR)\include\tcl.h"
TCLINSTALL = 1
!elseif exist("$(_TCLDIR)\generic\tcl.h")
TCLH = "$(_TCLDIR)\generic\tcl.h"
TCLINSTALL = 0
!else
MSG =^
Don't know where tcl.h is. The TCLDIR macro doesn't appear correct.
!error $(MSG)
!endif
!endif
#----------------------------------------------------------
# Get the version from the header file. Try all possibles
# even though some aren't fully valid.
#----------------------------------------------------------
!if [nmakehlp -g $(TCLH) TCL_VERSION] == 76
TCL_DOTVERSION = 7.6
!elseif [nmakehlp -g $(TCLH) TCL_VERSION] == 80
TCL_DOTVERSION = 8.0
!elseif [nmakehlp -g $(TCLH) TCL_VERSION] == 81
TCL_DOTVERSION = 8.1
!elseif [nmakehlp -g $(TCLH) TCL_VERSION] == 82
TCL_DOTVERSION = 8.2
!elseif [nmakehlp -g $(TCLH) TCL_VERSION] == 83
TCL_DOTVERSION = 8.3
!elseif [nmakehlp -g $(TCLH) TCL_VERSION] == 84
TCL_DOTVERSION = 8.4
!elseif [nmakehlp -g $(TCLH) TCL_VERSION] == 85
TCL_DOTVERSION = 8.5
!elseif [nmakehlp -g $(TCLH) TCL_VERSION] == 86
TCL_DOTVERSION = 8.6
!elseif [nmakehlp -g $(TCLH) TCL_VERSION] == 90
TCL_DOTVERSION = 9.0
!elseif [nmakehlp -g $(TCLH) TCL_VERSION] == 0
MSG =^
Can't get version string from $(TCLH)
!error $(MSG)
!endif
TCL_VERSION = $(TCL_DOTVERSION:.=)
!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"
|
| ︙ | ︙ |
Changes to win/tcl.rc.
|
| | | | | | 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 | // RCS: @(#) $Id: tcl.rc,v 1.8.4.1 2004/02/07 05:48:12 dgp Exp $ // // Version Resource Script // #include <winver.h> #include <tcl.h> // // build-up the name suffix that defines the type of build this is. // #if TCL_THREADS #define SUFFIX_THREADS "t" #else #define SUFFIX_THREADS "" #endif #if DEBUG #define SUFFIX_DEBUG "g" #else #define SUFFIX_DEBUG "" #endif #define SUFFIX SUFFIX_THREADS SUFFIX_DEBUG |
| ︙ | ︙ | |||
40 41 42 43 44 45 46 |
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP */
BEGIN
VALUE "FileDescription", "Tcl DLL\0"
| | | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP */
BEGIN
VALUE "FileDescription", "Tcl DLL\0"
VALUE "OriginalFilename", "tcl" STRINGIFY(TCL_MAJOR_VERSION) STRINGIFY(TCL_MINOR_VERSION) SUFFIX ".dll\0"
VALUE "CompanyName", "ActiveState Corporation\0"
VALUE "FileVersion", TCL_PATCH_LEVEL
VALUE "LegalCopyright", "Copyright \251 2001 by ActiveState Corporation, et al\0"
VALUE "ProductName", "Tcl " TCL_VERSION " for Windows\0"
VALUE "ProductVersion", TCL_PATCH_LEVEL
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
|
Changes to win/tclAppInit.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* * tclAppInit.c -- * * Provides a default version of the main program and Tcl_AppInit * procedure for Tcl applications (without Tk). Note that this * program must be built in Win32 console mode to work properly. * * Copyright (c) 1996-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. * | | < | < | 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 | /* * tclAppInit.c -- * * Provides a default version of the main program and Tcl_AppInit * procedure for Tcl applications (without Tk). Note that this * program must be built in Win32 console mode to work properly. * * Copyright (c) 1996-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. * * RCS: @(#) $Id: tclAppInit.c,v 1.13.2.2 2004/02/07 05:48:12 dgp Exp $ */ #include "tcl.h" #include <windows.h> #include <locale.h> #ifdef TCL_TEST extern int Procbodytest_Init _ANSI_ARGS_((Tcl_Interp *interp)); extern int Procbodytest_SafeInit _ANSI_ARGS_((Tcl_Interp *interp)); extern int Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp)); extern int TclObjTest_Init _ANSI_ARGS_((Tcl_Interp *interp)); #ifdef TCL_THREADS extern int TclThread_Init _ANSI_ARGS_((Tcl_Interp *interp)); #endif #endif /* TCL_TEST */ static BOOL WINAPI sigHandler (DWORD fdwCtrlType); static Tcl_AsyncProc asyncExit; static void AppInitExitHandler(ClientData clientData); static Tcl_AsyncHandler exitToken = NULL; static DWORD exitErrorCode = 0; /* *---------------------------------------------------------------------- * |
| ︙ | ︙ | |||
52 53 54 55 56 57 58 | * Side effects: * Whatever the application does. * *---------------------------------------------------------------------- */ int | | < < | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
* Side effects:
* Whatever the application does.
*
*----------------------------------------------------------------------
*/
int
main (int argc, char *argv[])
{
/*
* 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.
*/
|
| ︙ | ︙ | |||
78 79 80 81 82 83 84 |
* etc., without needing to rewrite Tcl_Main()
*/
#ifdef TCL_LOCAL_MAIN_HOOK
extern int TCL_LOCAL_MAIN_HOOK _ANSI_ARGS_((int *argc, char ***argv));
#endif
| < > < < < < < < < | < < | < | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
* etc., without needing to rewrite Tcl_Main()
*/
#ifdef TCL_LOCAL_MAIN_HOOK
extern int TCL_LOCAL_MAIN_HOOK _ANSI_ARGS_((int *argc, char ***argv));
#endif
char *p;
/*
* Set up the default locale to be standard "C" locale so parsing
* is performed correctly.
*/
setlocale(LC_ALL, "C");
/*
* Forward slashes substituted for backslashes.
*/
for (p = argv[0]; *p != '\0'; p++) {
if (*p == '\\') {
*p = '/';
}
}
#ifdef TCL_LOCAL_MAIN_HOOK
TCL_LOCAL_MAIN_HOOK(&argc, &argv);
#endif
Tcl_Main(argc, argv, TCL_LOCAL_APPINIT);
return 0; /* Needed only to prevent compiler warning. */
}
/*
*----------------------------------------------------------------------
*
* Tcl_AppInit --
*
* This procedure performs application-specific initialization.
|
| ︙ | ︙ | |||
176 177 178 179 180 181 182 |
if (Procbodytest_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
Tcl_StaticPackage(interp, "procbodytest", Procbodytest_Init,
Procbodytest_SafeInit);
#endif /* TCL_TEST */
| | | 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
if (Procbodytest_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
Tcl_StaticPackage(interp, "procbodytest", Procbodytest_Init,
Procbodytest_SafeInit);
#endif /* TCL_TEST */
#if defined(STATIC_BUILD) && TCL_USE_STATIC_PACKAGES
{
extern Tcl_PackageInitProc Registry_Init;
extern Tcl_PackageInitProc Dde_Init;
if (Registry_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
|
| ︙ | ︙ | |||
239 240 241 242 243 244 245 | * Frees the saved argv and deletes the async exit handler. * *---------------------------------------------------------------------- */ static void AppInitExitHandler( | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | > > > | 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
* Frees the saved argv and deletes the async exit handler.
*
*----------------------------------------------------------------------
*/
static void
AppInitExitHandler(
ClientData clientData) /* Not Used. */
{
if (exitToken != NULL) {
/*
* This should be safe to do even if we
* are in an async exit right now.
*/
Tcl_AsyncDelete(exitToken);
exitToken = NULL;
}
}
/*
*----------------------------------------------------------------------
*
* asyncExit --
*
* The AsyncProc for the exitToken.
*
* Results:
* doesn't actually return.
*
* Side effects:
* tclsh cleanly exits.
*
*----------------------------------------------------------------------
*/
int
asyncExit (
ClientData clientData, /* Not Used. */
Tcl_Interp *interp, /* interp in context, if any. */
int code) /* result of last command, if any. */
{
Tcl_Exit((int)exitErrorCode);
/* NOTREACHED */
return code;
}
|
| ︙ | ︙ | |||
418 419 420 421 422 423 424 | * Effects the way the app exits from a signal. This is an * operating system supplied thread and unsafe to call ANY * Tcl commands except for Tcl_AsyncMark. * *---------------------------------------------------------------------- */ | | | > | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
* Effects the way the app exits from a signal. This is an
* operating system supplied thread and unsafe to call ANY
* Tcl commands except for Tcl_AsyncMark.
*
*----------------------------------------------------------------------
*/
BOOL WINAPI
sigHandler(
DWORD fdwCtrlType) /* One of the CTRL_*_EVENT constants. */
{
HANDLE hStdIn;
if (!exitToken) {
/* Async token must have been destroyed, punt gracefully. */
return FALSE;
}
|
| ︙ | ︙ | |||
446 447 448 449 450 451 452 |
* the attention of the interpreter.
*/
hStdIn = GetStdHandle(STD_INPUT_HANDLE);
if (hStdIn) {
CloseHandle(hStdIn);
}
| | | 314 315 316 317 318 319 320 321 322 323 |
* the attention of the interpreter.
*/
hStdIn = GetStdHandle(STD_INPUT_HANDLE);
if (hStdIn) {
CloseHandle(hStdIn);
}
/* indicate to the OS not to call the default terminator. */
return TRUE;
}
|
Changes to win/tclWin32Dll.c.
1 2 3 4 5 6 7 8 9 10 11 | /* * tclWin32Dll.c -- * * This file contains the DLL entry point. * * Copyright (c) 1995-1996 Sun Microsystems, Inc. * Copyright (c) 1998-2000 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * tclWin32Dll.c -- * * This file contains the DLL entry point. * * Copyright (c) 1995-1996 Sun Microsystems, Inc. * Copyright (c) 1998-2000 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclWin32Dll.c,v 1.25.2.3 2004/02/07 05:48:12 dgp Exp $ */ #include "tclWinInt.h" /* * The following data structures are used when loading the thunking * library for execing child processes under Win32s. |
| ︙ | ︙ | |||
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
* initializing various dynamically loaded libraries.
*
* Results:
* TRUE on sucess, FALSE on failure.
*
* Side effects:
* Establishes 32-to-16 bit thunk and initializes sockets library.
*
*----------------------------------------------------------------------
*/
BOOL APIENTRY
DllMain(hInst, reason, reserved)
HINSTANCE hInst; /* Library instance handle. */
DWORD reason; /* Reason this function is being called. */
LPVOID reserved; /* Not used. */
{
switch (reason) {
case DLL_PROCESS_ATTACH:
TclWinInit(hInst);
return TRUE;
case DLL_PROCESS_DETACH:
| > > > > > > > > > > > > > > > > > > | > > > > > > > > | > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 |
* initializing various dynamically loaded libraries.
*
* Results:
* TRUE on sucess, FALSE on failure.
*
* Side effects:
* Establishes 32-to-16 bit thunk and initializes sockets library.
* This might call some sycronization functions, but MSDN
* documentation states: "Waiting on synchronization objects in
* DllMain can cause a deadlock."
*
*----------------------------------------------------------------------
*/
BOOL APIENTRY
DllMain(hInst, reason, reserved)
HINSTANCE hInst; /* Library instance handle. */
DWORD reason; /* Reason this function is being called. */
LPVOID reserved; /* Not used. */
{
switch (reason) {
case DLL_PROCESS_ATTACH:
TclWinInit(hInst);
return TRUE;
case DLL_PROCESS_DETACH:
/*
* Protect the call to Tcl_Finalize. The OS could be unloading
* us from an exception handler and the state of the stack might
* be unstable.
*/
#ifdef HAVE_NO_SEH
# ifdef TCL_MEM_DEBUG
__asm__ __volatile__ (
"movl %%esp, %0" "\n\t"
"movl %%ebp, %1" "\n\t"
"movl %%fs:0, %2" "\n\t"
: "=m"(INITIAL_ESP),
"=m"(INITIAL_EBP),
"=r"(INITIAL_HANDLER) );
# endif /* TCL_MEM_DEBUG */
__asm__ __volatile__ (
"pushl %ebp" "\n\t"
"pushl $__except_dllmain_detach_handler" "\n\t"
"pushl %fs:0" "\n\t"
"movl %esp, %fs:0");
#else
__try {
#endif /* HAVE_NO_SEH */
Tcl_Finalize();
#ifdef HAVE_NO_SEH
__asm__ __volatile__ (
"jmp dllmain_detach_pop" "\n"
"dllmain_detach_reentry:" "\n\t"
"movl %%fs:0, %%eax" "\n\t"
"movl 0x8(%%eax), %%esp" "\n\t"
"movl 0x8(%%esp), %%ebp" "\n"
"dllmain_detach_pop:" "\n\t"
"movl (%%esp), %%eax" "\n\t"
"movl %%eax, %%fs:0" "\n\t"
"add $12, %%esp" "\n\t"
:
:
: "%eax");
# ifdef TCL_MEM_DEBUG
__asm__ __volatile__ (
"movl %%esp, %0" "\n\t"
"movl %%ebp, %1" "\n\t"
"movl %%fs:0, %2" "\n\t"
: "=m"(RESTORED_ESP),
"=m"(RESTORED_EBP),
"=r"(RESTORED_HANDLER) );
if (INITIAL_ESP != RESTORED_ESP)
Tcl_Panic("ESP restored incorrectly");
if (INITIAL_EBP != RESTORED_EBP)
Tcl_Panic("EBP restored incorrectly");
if (INITIAL_HANDLER != RESTORED_HANDLER)
Tcl_Panic("HANDLER restored incorrectly");
# endif /* TCL_MEM_DEBUG */
#else
} __except (EXCEPTION_EXECUTE_HANDLER) {
/* empty handler body. */
}
#endif /* HAVE_NO_SEH */
break;
}
return TRUE;
}
#ifdef HAVE_NO_SEH
static
__attribute__ ((cdecl))
EXCEPTION_DISPOSITION
_except_dllmain_detach_handler(
struct _EXCEPTION_RECORD *ExceptionRecord,
void *EstablisherFrame,
struct _CONTEXT *ContextRecord,
void *DispatcherContext)
{
__asm__ __volatile__ (
"jmp dllmain_detach_reentry");
/* Nuke compiler warning about unused static function */
_except_dllmain_detach_handler(NULL, NULL, NULL, NULL);
return 0; /* Function does not return */
}
#endif /* HAVE_NO_SEH */
#endif /* !STATIC_BUILD */
#endif /* __WIN32__ */
/*
*----------------------------------------------------------------------
*
* TclWinGetTclInstance --
|
| ︙ | ︙ | |||
310 311 312 313 314 315 316 |
/*
* We no longer support Win32s, so just in case someone manages to
* get a runtime there, make sure they know that.
*/
if (platformId == VER_PLATFORM_WIN32s) {
| | | 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 |
/*
* We no longer support Win32s, so just in case someone manages to
* get a runtime there, make sure they know that.
*/
if (platformId == VER_PLATFORM_WIN32s) {
Tcl_Panic("Win32s is not a supported platform");
}
tclWinProcs = &asciiProcs;
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
458 459 460 461 462 463 464 |
"movl %%ebp, %1" "\n\t"
"movl %%fs:0, %2" "\n\t"
: "=m"(RESTORED_ESP),
"=m"(RESTORED_EBP),
"=r"(RESTORED_HANDLER) );
if (INITIAL_ESP != RESTORED_ESP)
| | | | | 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 |
"movl %%ebp, %1" "\n\t"
"movl %%fs:0, %2" "\n\t"
: "=m"(RESTORED_ESP),
"=m"(RESTORED_EBP),
"=r"(RESTORED_HANDLER) );
if (INITIAL_ESP != RESTORED_ESP)
Tcl_Panic("ESP restored incorrectly");
if (INITIAL_EBP != RESTORED_EBP)
Tcl_Panic("EBP restored incorrectly");
if (INITIAL_HANDLER != RESTORED_HANDLER)
Tcl_Panic("HANDLER restored incorrectly");
# endif /* TCL_MEM_DEBUG */
#else
} __except (EXCEPTION_EXECUTE_HANDLER) {}
#endif /* HAVE_NO_SEH */
/*
* Avoid using control flow statements in the SEH guarded block!
|
| ︙ | ︙ | |||
565 566 567 568 569 570 571 572 573 574 575 576 577 578 |
(HANDLE (WINAPI *)(CONST TCHAR*, UINT,
LPVOID, UINT, LPVOID, DWORD)) GetProcAddress(hInstance,
"FindFirstFileExW");
tclWinProcs->getVolumeNameForVMPProc =
(BOOL (WINAPI *)(CONST TCHAR*, TCHAR*,
DWORD)) GetProcAddress(hInstance,
"GetVolumeNameForVolumeMountPointW");
FreeLibrary(hInstance);
}
hInstance = LoadLibraryA("advapi32");
if (hInstance != NULL) {
tclWinProcs->getFileSecurityProc = (BOOL (WINAPI *)(
LPCTSTR lpFileName,
SECURITY_INFORMATION RequestedInformation,
| > > > > | 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 |
(HANDLE (WINAPI *)(CONST TCHAR*, UINT,
LPVOID, UINT, LPVOID, DWORD)) GetProcAddress(hInstance,
"FindFirstFileExW");
tclWinProcs->getVolumeNameForVMPProc =
(BOOL (WINAPI *)(CONST TCHAR*, TCHAR*,
DWORD)) GetProcAddress(hInstance,
"GetVolumeNameForVolumeMountPointW");
tclWinProcs->getLongPathNameProc =
(DWORD (WINAPI *)(CONST TCHAR*, TCHAR*,
DWORD)) GetProcAddress(hInstance,
"GetLongPathNameW");
FreeLibrary(hInstance);
}
hInstance = LoadLibraryA("advapi32");
if (hInstance != NULL) {
tclWinProcs->getFileSecurityProc = (BOOL (WINAPI *)(
LPCTSTR lpFileName,
SECURITY_INFORMATION RequestedInformation,
|
| ︙ | ︙ | |||
613 614 615 616 617 618 619 620 621 622 623 624 625 626 | (BOOL (WINAPI *)(CONST TCHAR *, GET_FILEEX_INFO_LEVELS, LPVOID)) GetProcAddress(hInstance, "GetFileAttributesExA"); tclWinProcs->createHardLinkProc = (BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR*, LPSECURITY_ATTRIBUTES)) GetProcAddress(hInstance, "CreateHardLinkA"); tclWinProcs->findFirstFileExProc = NULL; /* * The 'findFirstFileExProc' function exists on some * of 95/98/ME, but it seems not to work as anticipated. * Therefore we don't set this function pointer. The * relevant code will fall back on a slower approach * using the normal findFirstFileProc. * | > | 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 | (BOOL (WINAPI *)(CONST TCHAR *, GET_FILEEX_INFO_LEVELS, LPVOID)) GetProcAddress(hInstance, "GetFileAttributesExA"); tclWinProcs->createHardLinkProc = (BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR*, LPSECURITY_ATTRIBUTES)) GetProcAddress(hInstance, "CreateHardLinkA"); tclWinProcs->findFirstFileExProc = NULL; tclWinProcs->getLongPathNameProc = NULL; /* * The 'findFirstFileExProc' function exists on some * of 95/98/ME, but it seems not to work as anticipated. * Therefore we don't set this function pointer. The * relevant code will fall back on a slower approach * using the normal findFirstFileProc. * |
| ︙ | ︙ |
Changes to win/tclWinChan.c.
1 2 3 4 5 6 7 8 9 10 11 | /* * tclWinChan.c * * Channel drivers for Windows channels based on files, command * pipes and TCP sockets. * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * tclWinChan.c * * Channel drivers for Windows channels based on files, command * pipes and TCP sockets. * * 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. * * RCS: @(#) $Id: tclWinChan.c,v 1.30.4.1 2004/02/07 05:48:12 dgp Exp $ */ #include "tclWinInt.h" #include "tclIO.h" /* * State flags used in the info structures below. |
| ︙ | ︙ | |||
441 442 443 444 445 446 447 |
ClientData instanceData; /* File state. */
long offset; /* Offset to seek to. */
int mode; /* Relative to where should we seek? */
int *errorCodePtr; /* To store error code. */
{
FileInfo *infoPtr = (FileInfo *) instanceData;
DWORD moveMethod;
| | | | | | | | | 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 |
ClientData instanceData; /* File state. */
long offset; /* Offset to seek to. */
int mode; /* Relative to where should we seek? */
int *errorCodePtr; /* To store error code. */
{
FileInfo *infoPtr = (FileInfo *) instanceData;
DWORD moveMethod;
LONG newPos, newPosHigh;
LONG oldPos, oldPosHigh;
*errorCodePtr = 0;
if (mode == SEEK_SET) {
moveMethod = FILE_BEGIN;
} else if (mode == SEEK_CUR) {
moveMethod = FILE_CURRENT;
} else {
moveMethod = FILE_END;
}
/*
* Save our current place in case we need to roll-back the seek.
*/
oldPosHigh = 0;
oldPos = SetFilePointer(infoPtr->handle, 0, &oldPosHigh,
FILE_CURRENT);
if (oldPos == INVALID_SET_FILE_POINTER) {
DWORD winError = GetLastError();
if (winError != NO_ERROR) {
TclWinConvertError(winError);
*errorCodePtr = errno;
return -1;
}
}
newPosHigh = (offset < 0 ? -1 : 0);
newPos = SetFilePointer(infoPtr->handle, offset, &newPosHigh,
moveMethod);
if (newPos == INVALID_SET_FILE_POINTER) {
DWORD winError = GetLastError();
if (winError != NO_ERROR) {
TclWinConvertError(winError);
*errorCodePtr = errno;
return -1;
}
}
/*
* Check for expressability in our return type, and roll-back otherwise.
*/
if (newPosHigh != 0) {
*errorCodePtr = EOVERFLOW;
SetFilePointer(infoPtr->handle, oldPos, &oldPosHigh, FILE_BEGIN);
return -1;
}
return (int) newPos;
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
518 519 520 521 522 523 524 |
ClientData instanceData; /* File state. */
Tcl_WideInt offset; /* Offset to seek to. */
int mode; /* Relative to where should we seek? */
int *errorCodePtr; /* To store error code. */
{
FileInfo *infoPtr = (FileInfo *) instanceData;
DWORD moveMethod;
| | | | | | | 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 |
ClientData instanceData; /* File state. */
Tcl_WideInt offset; /* Offset to seek to. */
int mode; /* Relative to where should we seek? */
int *errorCodePtr; /* To store error code. */
{
FileInfo *infoPtr = (FileInfo *) instanceData;
DWORD moveMethod;
LONG newPos, newPosHigh;
*errorCodePtr = 0;
if (mode == SEEK_SET) {
moveMethod = FILE_BEGIN;
} else if (mode == SEEK_CUR) {
moveMethod = FILE_CURRENT;
} else {
moveMethod = FILE_END;
}
newPosHigh = Tcl_WideAsLong(offset >> 32);
newPos = SetFilePointer(infoPtr->handle, Tcl_WideAsLong(offset),
&newPosHigh, moveMethod);
if (newPos == INVALID_SET_FILE_POINTER) {
DWORD winError = GetLastError();
if (winError != NO_ERROR) {
TclWinConvertError(winError);
*errorCodePtr = errno;
return -1;
}
}
return (Tcl_LongAsWide(newPos) | (Tcl_LongAsWide(newPosHigh) << 32));
}
/*
*----------------------------------------------------------------------
*
* FileInputProc --
*
|
| ︙ | ︙ | |||
775 776 777 778 779 780 781 | channelPermissions = TCL_WRITABLE; break; case O_RDWR: accessMode = (GENERIC_READ | GENERIC_WRITE); channelPermissions = (TCL_READABLE | TCL_WRITABLE); break; default: | | | 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 |
channelPermissions = TCL_WRITABLE;
break;
case O_RDWR:
accessMode = (GENERIC_READ | GENERIC_WRITE);
channelPermissions = (TCL_READABLE | TCL_WRITABLE);
break;
default:
Tcl_Panic("TclpOpenFileChannel: invalid mode value");
break;
}
/*
* Map the creation flags to the NT create mode.
*/
|
| ︙ | ︙ | |||
1089 1090 1091 1092 1093 1094 1095 |
"movl %%ebp, %1" "\n\t"
"movl %%fs:0, %2" "\n\t"
: "=m"(RESTORED_ESP),
"=m"(RESTORED_EBP),
"=r"(RESTORED_HANDLER) );
if (INITIAL_ESP != RESTORED_ESP)
| | | | | 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 |
"movl %%ebp, %1" "\n\t"
"movl %%fs:0, %2" "\n\t"
: "=m"(RESTORED_ESP),
"=m"(RESTORED_EBP),
"=r"(RESTORED_HANDLER) );
if (INITIAL_ESP != RESTORED_ESP)
Tcl_Panic("ESP restored incorrectly");
if (INITIAL_EBP != RESTORED_EBP)
Tcl_Panic("EBP restored incorrectly");
if (INITIAL_HANDLER != RESTORED_HANDLER)
Tcl_Panic("HANDLER restored incorrectly");
# endif /* TCL_MEM_DEBUG */
if (result)
return NULL;
#else
}
__except (EXCEPTION_EXECUTE_HANDLER) {
|
| ︙ | ︙ | |||
1185 1186 1187 1188 1189 1190 1191 | break; case TCL_STDERR: handleId = STD_ERROR_HANDLE; mode = TCL_WRITABLE; bufMode = "none"; break; default: | | | 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 |
break;
case TCL_STDERR:
handleId = STD_ERROR_HANDLE;
mode = TCL_WRITABLE;
bufMode = "none";
break;
default:
Tcl_Panic("TclGetDefaultStdChannel: Unexpected channel type");
break;
}
handle = GetStdHandle(handleId);
/*
* Note that we need to check for 0 because Windows may return 0 if this
|
| ︙ | ︙ | |||
1384 1385 1386 1387 1388 1389 1390 |
/*
* 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.
*/
| | | | | 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 |
/*
* 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) {
Tcl_Panic("file info ptr not on thread channel list");
}
}
/*
*----------------------------------------------------------------------
*
* TclpSpliceFileChannel --
*
|
| ︙ | ︙ |
Changes to win/tclWinDde.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* * tclWinDde.c -- * * This file provides procedures that implement the "send" * command, allowing commands to be passed from interpreter * to interpreter. * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* * tclWinDde.c -- * * This file provides procedures that implement the "send" * command, allowing commands to be passed from interpreter * to interpreter. * * 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. * * RCS: @(#) $Id: tclWinDde.c,v 1.15.2.2 2004/02/07 05:48:12 dgp Exp $ */ #include "tclPort.h" #include <dde.h> #include <ddeml.h> #include <tchar.h> /* |
| ︙ | ︙ | |||
67 68 69 70 71 72 73 | * The Mutex ddeMutex guards access to the ddeInstance. */ static HSZ ddeServiceGlobal = 0; static DWORD ddeInstance; /* The application instance handle given * to us by DdeInitialize. */ static int ddeIsServer = 0; | | | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | * The Mutex ddeMutex guards access to the ddeInstance. */ static HSZ ddeServiceGlobal = 0; static DWORD ddeInstance; /* The application instance handle given * to us by DdeInitialize. */ static int ddeIsServer = 0; #define TCL_DDE_VERSION "1.3" #define TCL_DDE_PACKAGE_NAME "dde" #define TCL_DDE_SERVICE_NAME "TclEval" TCL_DECLARE_MUTEX(ddeMutex) /* * Forward declarations for procedures defined later in this file. |
| ︙ | ︙ |
Changes to win/tclWinFCmd.c.
1 2 3 4 5 6 7 8 9 10 11 | /* * tclWinFCmd.c * * This file implements the Windows specific 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. * | | > | 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 | /* * tclWinFCmd.c * * This file implements the Windows specific 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. * * RCS: @(#) $Id: tclWinFCmd.c,v 1.35.4.3 2004/02/07 05:48:12 dgp Exp $ */ #include "tclWinInt.h" /* * The following constants specify the type of callback when * TraverseWinTree() 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_LINK 4 /* symbolic link */ /* * Callbacks for file attributes code. */ static int GetWinFileAttributes _ANSI_ARGS_((Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, |
| ︙ | ︙ | |||
233 234 235 236 237 238 239 |
"movl %%ebp, %1" "\n\t"
"movl %%fs:0, %2" "\n\t"
: "=m"(RESTORED_ESP),
"=m"(RESTORED_EBP),
"=r"(RESTORED_HANDLER) );
if (INITIAL_ESP != RESTORED_ESP)
| | | | | 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
"movl %%ebp, %1" "\n\t"
"movl %%fs:0, %2" "\n\t"
: "=m"(RESTORED_ESP),
"=m"(RESTORED_EBP),
"=r"(RESTORED_HANDLER) );
if (INITIAL_ESP != RESTORED_ESP)
Tcl_Panic("ESP restored incorrectly");
if (INITIAL_EBP != RESTORED_EBP)
Tcl_Panic("EBP restored incorrectly");
if (INITIAL_HANDLER != RESTORED_HANDLER)
Tcl_Panic("HANDLER restored incorrectly");
# endif /* TCL_MEM_DEBUG */
#else
} __except (EXCEPTION_EXECUTE_HANDLER) {}
#endif /* HAVE_NO_SEH */
/*
* Avoid using control flow statements in the SEH guarded block!
|
| ︙ | ︙ | |||
595 596 597 598 599 600 601 |
"movl %%ebp, %1" "\n\t"
"movl %%fs:0, %2" "\n\t"
: "=m"(RESTORED_ESP),
"=m"(RESTORED_EBP),
"=r"(RESTORED_HANDLER) );
if (INITIAL_ESP != RESTORED_ESP)
| | | | | 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 |
"movl %%ebp, %1" "\n\t"
"movl %%fs:0, %2" "\n\t"
: "=m"(RESTORED_ESP),
"=m"(RESTORED_EBP),
"=r"(RESTORED_HANDLER) );
if (INITIAL_ESP != RESTORED_ESP)
Tcl_Panic("ESP restored incorrectly");
if (INITIAL_EBP != RESTORED_EBP)
Tcl_Panic("EBP restored incorrectly");
if (INITIAL_HANDLER != RESTORED_HANDLER)
Tcl_Panic("HANDLER restored incorrectly");
# endif /* TCL_MEM_DEBUG */
#else
} __except (EXCEPTION_EXECUTE_HANDLER) {}
#endif /* HAVE_NO_SEH */
/*
* Avoid using control flow statements in the SEH guarded block!
|
| ︙ | ︙ | |||
965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 |
int ignoreError, /* If non-zero, don't initialize the
* errorPtr under some circumstances
* on return. */
Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free
* DString filled with UTF-8 name of file
* causing error. */
{
/*
* The RemoveDirectory API acts differently under Win95/98 and NT
* WRT NULL and "". Avoid passing these values.
*/
if (nativePath == NULL || nativePath[0] == '\0') {
Tcl_SetErrno(ENOENT);
goto end;
}
| > > > > > > > > > > | | | > > | | 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 |
int ignoreError, /* If non-zero, don't initialize the
* errorPtr under some circumstances
* on return. */
Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free
* DString filled with UTF-8 name of file
* causing error. */
{
DWORD attr;
/*
* The RemoveDirectory API acts differently under Win95/98 and NT
* WRT NULL and "". Avoid passing these values.
*/
if (nativePath == NULL || nativePath[0] == '\0') {
Tcl_SetErrno(ENOENT);
goto end;
}
attr = (*tclWinProcs->getFileAttributesProc)(nativePath);
if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
/* It is a symbolic link -- remove it */
if (TclWinSymLinkDelete(nativePath, 0) == 0) {
return TCL_OK;
}
} else {
/* Ordinary directory */
if ((*tclWinProcs->removeDirectoryProc)(nativePath) != FALSE) {
return TCL_OK;
}
}
TclWinConvertError(GetLastError());
if (Tcl_GetErrno() == EACCES) {
attr = (*tclWinProcs->getFileAttributesProc)(nativePath);
if (attr != 0xffffffff) {
if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
/*
* Windows 95 reports calling RemoveDirectory on a file as an
* EACCES, not an ENOTDIR.
*/
|
| ︙ | ︙ | |||
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 |
attr | FILE_ATTRIBUTE_READONLY);
}
/*
* Windows 95 and Win32s report removing a non-empty directory
* as EACCES, not EEXIST. If the directory is not empty,
* change errno so caller knows what's going on.
*/
if (TclWinGetPlatformId() != VER_PLATFORM_WIN32_NT) {
CONST char *path, *find;
HANDLE handle;
WIN32_FIND_DATAA data;
Tcl_DString buffer;
| > | 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 |
attr | FILE_ATTRIBUTE_READONLY);
}
/*
* Windows 95 and Win32s report removing a non-empty directory
* as EACCES, not EEXIST. If the directory is not empty,
* change errno so caller knows what's going on.
*/
if (TclWinGetPlatformId() != VER_PLATFORM_WIN32_NT) {
CONST char *path, *find;
HANDLE handle;
WIN32_FIND_DATAA data;
Tcl_DString buffer;
|
| ︙ | ︙ | |||
1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 |
oldSourceLen = Tcl_DStringLength(sourcePtr);
sourceAttr = (*tclWinProcs->getFileAttributesProc)(nativeSource);
if (sourceAttr == 0xffffffff) {
nativeErrfile = nativeSource;
goto end;
}
if ((sourceAttr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
/*
* Process the regular file
*/
return (*traverseProc)(nativeSource, nativeTarget, DOTREE_F, errorPtr);
}
| > > > > > > > > > > | 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 |
oldSourceLen = Tcl_DStringLength(sourcePtr);
sourceAttr = (*tclWinProcs->getFileAttributesProc)(nativeSource);
if (sourceAttr == 0xffffffff) {
nativeErrfile = nativeSource;
goto end;
}
if (sourceAttr & FILE_ATTRIBUTE_REPARSE_POINT) {
/*
* Process the symbolic link
*/
return (*traverseProc)(nativeSource, nativeTarget,
DOTREE_LINK, errorPtr);
}
if ((sourceAttr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
/*
* Process the regular file
*/
return (*traverseProc)(nativeSource, nativeTarget, DOTREE_F, errorPtr);
}
|
| ︙ | ︙ | |||
1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 |
{
switch (type) {
case DOTREE_F: {
if (DoCopyFile(nativeSrc, nativeDst) == TCL_OK) {
return TCL_OK;
}
break;
}
case DOTREE_PRED: {
if (DoCreateDirectory(nativeDst) == TCL_OK) {
DWORD attr = (*tclWinProcs->getFileAttributesProc)(nativeSrc);
| > > > > > > | > | 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 |
{
switch (type) {
case DOTREE_F: {
if (DoCopyFile(nativeSrc, nativeDst) == TCL_OK) {
return TCL_OK;
}
break;
}
case DOTREE_LINK: {
if (TclWinSymLinkCopyDirectory(nativeSrc, nativeDst) == TCL_OK) {
return TCL_OK;
}
break;
}
case DOTREE_PRED: {
if (DoCreateDirectory(nativeDst) == TCL_OK) {
DWORD attr = (*tclWinProcs->getFileAttributesProc)(nativeSrc);
if ((*tclWinProcs->setFileAttributesProc)(nativeDst, attr)
!= FALSE) {
return TCL_OK;
}
TclWinConvertError(GetLastError());
}
break;
}
case DOTREE_POSTD: {
|
| ︙ | ︙ | |||
1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 |
{
switch (type) {
case DOTREE_F: {
if (TclpDeleteFile(nativeSrc) == TCL_OK) {
return TCL_OK;
}
break;
}
case DOTREE_PRED: {
return TCL_OK;
}
case DOTREE_POSTD: {
if (DoRemoveJustDirectory(nativeSrc, 0, NULL) == TCL_OK) {
return TCL_OK;
| > > > > > > | 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 |
{
switch (type) {
case DOTREE_F: {
if (TclpDeleteFile(nativeSrc) == TCL_OK) {
return TCL_OK;
}
break;
}
case DOTREE_LINK: {
if (DoRemoveJustDirectory(nativeSrc, 0, NULL) == TCL_OK) {
return TCL_OK;
}
break;
}
case DOTREE_PRED: {
return TCL_OK;
}
case DOTREE_POSTD: {
if (DoRemoveJustDirectory(nativeSrc, 0, NULL) == TCL_OK) {
return TCL_OK;
|
| ︙ | ︙ | |||
1552 1553 1554 1555 1556 1557 1558 |
int objIndex, /* The index of the attribute. */
Tcl_Obj *fileName, /* The name of the file. */
int longShort, /* 0 to short name, 1 to long name. */
Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */
{
int pathc, i;
Tcl_Obj *splitPath;
| < | < > > > > > > > | 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 |
int objIndex, /* The index of the attribute. */
Tcl_Obj *fileName, /* The name of the file. */
int longShort, /* 0 to short name, 1 to long name. */
Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */
{
int pathc, i;
Tcl_Obj *splitPath;
splitPath = Tcl_FSSplitPath(fileName, &pathc);
if (splitPath == NULL || pathc == 0) {
if (interp != NULL) {
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
"could not read \"", Tcl_GetString(fileName),
"\": no such file or directory",
(char *) NULL);
}
goto cleanup;
}
/*
* We will decrement this again at the end. It is safer to
* do this in case any of the calls below retain a reference
* to splitPath.
*/
Tcl_IncrRefCount(splitPath);
for (i = 0; i < pathc; i++) {
Tcl_Obj *elt;
char *pathv;
int pathLen;
Tcl_ListObjIndex(NULL, splitPath, i, &elt);
pathv = Tcl_GetStringFromObj(elt, &pathLen);
|
| ︙ | ︙ | |||
1631 1632 1633 1634 1635 1636 1637 |
}
if (handle == INVALID_HANDLE_VALUE) {
Tcl_DStringFree(&ds);
if (interp != NULL) {
StatError(interp, fileName);
}
| < | 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 |
}
if (handle == INVALID_HANDLE_VALUE) {
Tcl_DStringFree(&ds);
if (interp != NULL) {
StatError(interp, fileName);
}
goto cleanup;
}
if (tclWinProcs->useWide) {
nativeName = (TCHAR *) data.w.cAlternateFileName;
if (longShort) {
if (data.w.cFileName[0] != '\0') {
nativeName = (TCHAR *) data.w.cFileName;
|
| ︙ | ︙ | |||
1689 1690 1691 1692 1693 1694 1695 |
Tcl_DStringFree(&ds);
Tcl_DStringFree(&dsTemp);
FindClose(handle);
}
}
*attributePtrPtr = Tcl_FSJoinPath(splitPath, -1);
| | > > > > > > > > > > > > > > | | | 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 |
Tcl_DStringFree(&ds);
Tcl_DStringFree(&dsTemp);
FindClose(handle);
}
}
*attributePtrPtr = Tcl_FSJoinPath(splitPath, -1);
if (splitPath != NULL) {
/*
* Unfortunately, the object we will return may have its only
* refCount as part of the list splitPath. This means if
* we free splitPath, the object will disappear. So, we
* have to be very careful here. Unfortunately this means
* we must manipulate the object's refCount directly.
*/
Tcl_IncrRefCount(*attributePtrPtr);
Tcl_DecrRefCount(splitPath);
--(*attributePtrPtr)->refCount;
}
return TCL_OK;
cleanup:
if (splitPath != NULL) {
Tcl_DecrRefCount(splitPath);
}
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
* GetWinFileLongName --
*
|
| ︙ | ︙ |
Changes to win/tclWinFile.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* * tclWinFile.c -- * * This file contains temporary wrappers around UNIX file handling * functions. These wrappers map the UNIX functions to Win32 HANDLE-style * files, which can be manipulated through the Win32 console redirection * interfaces. * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* * tclWinFile.c -- * * This file contains temporary wrappers around UNIX file handling * functions. These wrappers map the UNIX functions to Win32 HANDLE-style * files, which can be manipulated through the Win32 console redirection * interfaces. * * 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. * * RCS: @(#) $Id: tclWinFile.c,v 1.50.2.5 2004/02/07 05:48:12 dgp Exp $ */ //#define _WIN32_WINNT 0x0500 #include "tclWinInt.h" #include <winioctl.h> #include <sys/stat.h> |
| ︙ | ︙ | |||
214 215 216 217 218 219 220 |
/* Make sure source file doesn't exist */
attr = (*tclWinProcs->getFileAttributesProc)(LinkSource);
if (attr != 0xffffffff) {
Tcl_SetErrno(EEXIST);
return -1;
}
| | | 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
/* Make sure source file doesn't exist */
attr = (*tclWinProcs->getFileAttributesProc)(LinkSource);
if (attr != 0xffffffff) {
Tcl_SetErrno(EEXIST);
return -1;
}
/* Get the full path referenced by the source file/directory */
if (!(*tclWinProcs->getFullPathNameProc)(LinkSource,
MAX_PATH, tempFileName, &tempFilePart)) {
/* Invalid file */
TclWinConvertError(GetLastError());
return -1;
}
/* Check the target */
|
| ︙ | ︙ | |||
738 739 740 741 742 743 744 745 746 747 748 749 750 751 |
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 TCHAR *native;
if (pattern == NULL || (*pattern == '\0')) {
Tcl_Obj *norm = Tcl_FSGetNormalizedPath(NULL, pathPtr);
if (norm != NULL) {
/* Match a single file directly */
int len;
DWORD attr;
| > > > > > | 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 |
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 TCHAR *native;
if (types != NULL && types->type == TCL_GLOB_TYPE_MOUNT) {
/* The native filesystem never adds mounts */
return TCL_OK;
}
if (pattern == NULL || (*pattern == '\0')) {
Tcl_Obj *norm = Tcl_FSGetNormalizedPath(NULL, pathPtr);
if (norm != NULL) {
/* Match a single file directly */
int len;
DWORD attr;
|
| ︙ | ︙ | |||
1409 1410 1411 1412 1413 1414 1415 1416 1417 |
TOKEN_DUPLICATE | TOKEN_QUERY, FALSE, &hToken)) {
/*
* Unable to get current thread's token.
*/
goto accessError;
}
(*tclWinProcs->revertToSelfProc)();
memset (&genMap, 0x00, sizeof (GENERIC_MAPPING));
/*
| > > | | | | | | | 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 |
TOKEN_DUPLICATE | TOKEN_QUERY, FALSE, &hToken)) {
/*
* Unable to get current thread's token.
*/
goto accessError;
}
(*tclWinProcs->revertToSelfProc)();
memset (&genMap, 0x00, sizeof (GENERIC_MAPPING));
/*
* Setup desiredAccess according to the access priveleges we
* are checking.
*/
genMap.GenericAll = 0;
if (mode & R_OK) {
desiredAccess |= FILE_GENERIC_READ;
}
if (mode & W_OK) {
desiredAccess |= FILE_GENERIC_WRITE;
}
if (mode & X_OK) {
desiredAccess |= FILE_GENERIC_EXECUTE;
}
/*
* Perform access check using the token.
*/
if (!(*tclWinProcs->accessCheckProc )(sdPtr, hToken, desiredAccess,
&genMap, &privSet, &privSetSize, &grantedAccess,
&accessYesNo)) {
/*
|
| ︙ | ︙ | |||
1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 | /* *---------------------------------------------------------------------- * * TclpGetCwd -- * * 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 | > > | 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 | /* *---------------------------------------------------------------------- * * 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 |
| ︙ | ︙ | |||
2084 2085 2086 2087 2088 2089 2090 |
Tcl_DStringAppend(bufferPtr, realFileName, -1);
return 1;
}
return 0;
}
#endif
| > > > | > > > > > > > > > > > > > > > > > | | > > > | > > | > | < < > > > > > | > | > > > | | > > > > | 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 |
Tcl_DStringAppend(bufferPtr, realFileName, -1);
return 1;
}
return 0;
}
#endif
/*
*---------------------------------------------------------------------------
*
* TclpGetNativeCwd --
*
* This function replaces the library version of getcwd().
*
* Results:
* 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.
*
*----------------------------------------------------------------------
*/
ClientData
TclpGetNativeCwd(clientData)
ClientData clientData;
{
WCHAR buffer[MAX_PATH];
if ((*tclWinProcs->getCurrentDirectoryProc)(MAX_PATH, buffer) == 0) {
TclWinConvertError(GetLastError());
return NULL;
}
if (clientData != NULL) {
if (tclWinProcs->useWide) {
/* unicode representation when running on NT/2K/XP */
if (wcscmp((CONST WCHAR*)clientData,
(CONST WCHAR*)buffer) == 0) {
return clientData;
}
} else {
/* ansi representation when running on 95/98/ME */
if (strcmp((CONST char*)clientData,
(CONST char*)buffer) == 0) {
return clientData;
}
}
}
return TclNativeDupInternalRep((ClientData)buffer);
}
int
TclpObjAccess(pathPtr, mode)
Tcl_Obj *pathPtr;
int mode;
{
|
| ︙ | ︙ | |||
2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 |
TclpObjLink(pathPtr, toPtr, linkAction)
Tcl_Obj *pathPtr;
Tcl_Obj *toPtr;
int linkAction;
{
if (toPtr != NULL) {
int res;
TCHAR* LinkTarget = (TCHAR*)Tcl_FSGetNativePath(toPtr);
TCHAR* LinkSource = (TCHAR*)Tcl_FSGetNativePath(pathPtr);
if (LinkSource == NULL || LinkTarget == NULL) {
return NULL;
}
res = WinLink(LinkSource, LinkTarget, linkAction);
if (res == 0) {
return toPtr;
| > > > > | 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 |
TclpObjLink(pathPtr, toPtr, linkAction)
Tcl_Obj *pathPtr;
Tcl_Obj *toPtr;
int linkAction;
{
if (toPtr != NULL) {
int res;
#if 0
TCHAR* LinkTarget = (TCHAR*)Tcl_FSGetNativePath(toPtr);
#else
TCHAR* LinkTarget = (TCHAR*)Tcl_FSGetNativePath(Tcl_FSGetNormalizedPath(NULL,toPtr));
#endif
TCHAR* LinkSource = (TCHAR*)Tcl_FSGetNativePath(pathPtr);
if (LinkSource == NULL || LinkTarget == NULL) {
return NULL;
}
res = WinLink(LinkSource, LinkTarget, linkAction);
if (res == 0) {
return toPtr;
|
| ︙ | ︙ | |||
2174 2175 2176 2177 2178 2179 2180 | * * Side effects: * None. * *--------------------------------------------------------------------------- */ Tcl_Obj* | | | | | | 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 |
*
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
Tcl_Obj*
TclpFilesystemPathType(pathPtr)
Tcl_Obj* pathPtr;
{
#define VOL_BUF_SIZE 32
int found;
char volType[VOL_BUF_SIZE];
char* firstSeparator;
CONST char *path;
Tcl_Obj *normPath = Tcl_FSGetNormalizedPath(NULL, pathPtr);
if (normPath == NULL) return NULL;
path = Tcl_GetString(normPath);
if (path == NULL) return NULL;
firstSeparator = strchr(path, '/');
if (firstSeparator == NULL) {
found = tclWinProcs->getVolumeInformationProc(
Tcl_FSGetNativePath(pathPtr), NULL, 0, NULL, NULL,
NULL, (WCHAR *)volType, VOL_BUF_SIZE);
} else {
Tcl_Obj *driveName = Tcl_NewStringObj(path, firstSeparator - path+1);
Tcl_IncrRefCount(driveName);
found = tclWinProcs->getVolumeInformationProc(
Tcl_FSGetNativePath(driveName), NULL, 0, NULL, NULL,
NULL, (WCHAR *)volType, VOL_BUF_SIZE);
|
| ︙ | ︙ | |||
2215 2216 2217 2218 2219 2220 2221 |
Tcl_WinTCharToUtf(volType, -1, &ds);
objPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds),Tcl_DStringLength(&ds));
Tcl_DStringFree(&ds);
return objPtr;
}
#undef VOL_BUF_SIZE
}
| > > > > > > > > | > > > > > | 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 |
Tcl_WinTCharToUtf(volType, -1, &ds);
objPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds),Tcl_DStringLength(&ds));
Tcl_DStringFree(&ds);
return objPtr;
}
#undef VOL_BUF_SIZE
}
/*
* This define can be turned on to experiment with a different way of
* normalizing paths (using a different Windows API). Unfortunately the
* new path seems to take almost exactly the same amount of time as the
* old path! The primary time taken by normalization is in
* GetFileAttributesEx/FindFirstFile or
* GetFileAttributesEx/GetLongPathName. Conversion to/from native is
* not a significant factor at all.
*
* Also, since we have to check for symbolic links (reparse points)
* then we have to call GetFileAttributes on each path segment anyway,
* so there's no benefit to doing anything clever there.
*/
/* #define TclNORM_LONG_PATH */
/*
*---------------------------------------------------------------------------
*
* TclpObjNormalizePath --
*
* This function scans through a path specification and replaces it,
|
| ︙ | ︙ | |||
2237 2238 2239 2240 2241 2242 2243 | * * Side effects: * The pathPtr string, which must contain a valid path, is * possibly modified in place. * *--------------------------------------------------------------------------- */ | < | 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 |
*
* 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;
{
char *lastValidPathEnd = NULL;
|
| ︙ | ︙ | |||
2335 2336 2337 2338 2339 2340 2341 |
currentPathEndPosition++;
}
} else {
/* We're on WinNT or 2000 or XP */
Tcl_Obj *temp = NULL;
int isDrive = 1;
Tcl_DString ds;
| | | 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 |
currentPathEndPosition++;
}
} else {
/* We're on WinNT or 2000 or XP */
Tcl_Obj *temp = NULL;
int isDrive = 1;
Tcl_DString ds;
currentPathEndPosition = path + nextCheckpoint;
if (*currentPathEndPosition == '/') {
currentPathEndPosition++;
}
while (1) {
char cur = *currentPathEndPosition;
if ((cur == '/' || cur == 0) && (path != currentPathEndPosition)) {
|
| ︙ | ︙ | |||
2368 2369 2370 2371 2372 2373 2374 | * Check for symlinks, except at last component * of path (we don't follow final symlinks). Also * a drive (C:/) for example, may sometimes have * the reparse flag set for some reason I don't * understand. We therefore don't perform this * check for drives. */ | | | > | > > > | > > > > > | > | 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 |
* Check for symlinks, except at last component
* of path (we don't follow final symlinks). Also
* a drive (C:/) for example, may sometimes have
* the reparse flag set for some reason I don't
* understand. We therefore don't perform this
* check for drives.
*/
if (cur != 0 && !isDrive
&& (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
Tcl_Obj *to = WinReadLinkDirectory(nativePath);
if (to != NULL) {
/*
* Read the reparse point ok. Now, reparse
* points need not be normalized, otherwise
* we could use:
*
* Tcl_GetStringFromObj(to, &pathLen);
* nextCheckpoint = pathLen
*
* So, instead we have to start from the
* beginning.
*/
nextCheckpoint = 0;
Tcl_AppendToObj(to, currentPathEndPosition, -1);
/* Convert link to forward slashes */
for (path = Tcl_GetString(to); *path != 0; path++) {
if (*path == '\\') *path = '/';
}
path = Tcl_GetString(to);
currentPathEndPosition = path + nextCheckpoint;
if (temp != NULL) {
Tcl_DecrRefCount(temp);
}
temp = to;
/* Reset variables so we can restart normalization */
isDrive = 1;
Tcl_DStringFree(&dsNorm);
Tcl_DStringInit(&dsNorm);
Tcl_DStringFree(&ds);
continue;
}
}
#ifndef TclNORM_LONG_PATH
/*
* Now we convert the tail of the current path to its
* 'long form', and append it to 'dsNorm' which holds
* the current normalized path
*/
if (isDrive) {
WCHAR drive = ((WCHAR*)nativePath)[0];
|
| ︙ | ︙ | |||
2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 |
FindClose(handle);
Tcl_DStringAppend(&dsNorm,(CONST char*)L"/",
sizeof(WCHAR));
Tcl_DStringAppend(&dsNorm,(TCHAR*)nativeName,
(int) (wcslen(nativeName)*sizeof(WCHAR)));
}
}
Tcl_DStringFree(&ds);
lastValidPathEnd = currentPathEndPosition;
if (cur == 0) {
break;
}
/*
* If we get here, we've got past one directory
* delimiter, so we know it is no longer a drive
*/
isDrive = 0;
}
currentPathEndPosition++;
}
}
/* Common code path for all Windows platforms */
nextCheckpoint = currentPathEndPosition - path;
if (lastValidPathEnd != NULL) {
/*
* Concatenate the normalized string in dsNorm with the
* tail of the path which we didn't recognise. The
| > > > > > > > > > > > > > > > > > > > > > | 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 |
FindClose(handle);
Tcl_DStringAppend(&dsNorm,(CONST char*)L"/",
sizeof(WCHAR));
Tcl_DStringAppend(&dsNorm,(TCHAR*)nativeName,
(int) (wcslen(nativeName)*sizeof(WCHAR)));
}
}
#endif
Tcl_DStringFree(&ds);
lastValidPathEnd = currentPathEndPosition;
if (cur == 0) {
break;
}
/*
* If we get here, we've got past one directory
* delimiter, so we know it is no longer a drive
*/
isDrive = 0;
}
currentPathEndPosition++;
}
#ifdef TclNORM_LONG_PATH
/*
* Convert the entire known path to long form.
*/
if (1) {
WCHAR wpath[MAX_PATH];
DWORD wpathlen;
CONST char *nativePath = Tcl_WinUtfToTChar(path,
lastValidPathEnd - path, &ds);
wpathlen = (*tclWinProcs->getLongPathNameProc)(nativePath,
(TCHAR*)wpath,
MAX_PATH);
/* We have to make the drive letter uppercase */
if (wpath[0] >= L'a') {
wpath[0] -= (L'a' - L'A');
}
Tcl_DStringAppend(&dsNorm, (TCHAR*)wpath, wpathlen*sizeof(WCHAR));
Tcl_DStringFree(&ds);
}
#endif
}
/* Common code path for all Windows platforms */
nextCheckpoint = currentPathEndPosition - path;
if (lastValidPathEnd != NULL) {
/*
* Concatenate the normalized string in dsNorm with the
* tail of the path which we didn't recognise. The
|
| ︙ | ︙ | |||
2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 |
*/
int
TclpUtime(pathPtr, tval)
Tcl_Obj *pathPtr; /* File to modify */
struct utimbuf *tval; /* New modification date structure */
{
int res;
/*
* Windows uses a slightly different structure name and, possibly,
* contents, so we have to copy the information over
*/
struct _utimbuf buf;
| > > > > > > > > | | 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 |
*/
int
TclpUtime(pathPtr, tval)
Tcl_Obj *pathPtr; /* File to modify */
struct utimbuf *tval; /* New modification date structure */
{
int res;
#ifndef __BORLANDC__
/*
* Windows uses a slightly different structure name and, possibly,
* contents, so we have to copy the information over
*/
struct _utimbuf buf;
#else
/*
* Borland's compiler does not, but we still copy the content into a
* local variable using the 'generic' name
*/
struct utimbuf buf;
#endif
buf.actime = tval->actime;
buf.modtime = tval->modtime;
res = (*tclWinProcs->utimeProc)(Tcl_FSGetNativePath(pathPtr),&buf);
return res;
}
|
Changes to win/tclWinInit.c.
1 2 3 4 5 6 7 8 9 | /* * tclWinInit.c -- * * Contains the Windows-specific interpreter initialization functions. * * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * All rights reserved. * | | > > > > > > > | 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 | /* * tclWinInit.c -- * * Contains the Windows-specific interpreter initialization functions. * * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * All rights reserved. * * RCS: @(#) $Id: tclWinInit.c,v 1.41.2.2 2004/02/07 05:48:12 dgp Exp $ */ #include "tclWinInt.h" #include <winnt.h> #include <winbase.h> #include <lmcons.h> /* * GetUserName() is found in advapi32.dll */ #ifdef _MSC_VER # pragma comment(lib, "advapi32.lib") #endif /* * The following declaration is a workaround for some Microsoft brain damage. * The SYSTEM_INFO structure is different in various releases, even though the * layout is the same. So we overlay our own structure on top of it so we * can access the interesting slots in a uniform way. */ |
| ︙ | ︙ | |||
193 194 195 196 197 198 199 |
* 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);
| | | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
* 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')) {
|
| ︙ | ︙ | |||
248 249 250 251 252 253 254 |
/*
* The variable path holds an absolute path. Take care not to
* overwrite pathv[0] since that might produce a relative path.
*/
if (path != NULL) {
| > > > | > > > > > > > > > > > > > > > | 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
/*
* 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);
|
| ︙ | ︙ | |||
303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
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 *) pathv);
}
TclSetLibraryPath(pathPtr);
}
/*
| > | 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 |
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);
}
TclSetLibraryPath(pathPtr);
}
/*
|
| ︙ | ︙ |
Changes to win/tclWinInt.h.
1 2 3 4 5 6 7 8 9 10 | /* * tclWinInt.h -- * * Declarations of Windows-specific shared variables and procedures. * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /* * tclWinInt.h -- * * Declarations of Windows-specific shared variables and procedures. * * 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. * * RCS: @(#) $Id: tclWinInt.h,v 1.22.2.2 2004/02/07 05:48:12 dgp Exp $ */ #ifndef _TCLWININT #define _TCLWININT #ifndef _TCLINT #include "tclInt.h" |
| ︙ | ︙ | |||
107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
INT (__cdecl *utimeProc)(CONST TCHAR*, struct _utimbuf *);
/* These two are also NULL at start; see comment above */
HANDLE (WINAPI *findFirstFileExProc)(CONST TCHAR*, UINT,
LPVOID, UINT,
LPVOID, DWORD);
BOOL (WINAPI *getVolumeNameForVMPProc)(CONST TCHAR*, TCHAR*, DWORD);
/*
* These six are for the security sdk to get correct file
* permissions on NT, 2000, XP, etc. On 95,98,ME they are
* always null.
*/
BOOL (WINAPI *getFileSecurityProc)(LPCTSTR lpFileName,
SECURITY_INFORMATION RequestedInformation,
| > | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
INT (__cdecl *utimeProc)(CONST TCHAR*, struct _utimbuf *);
/* These two are also NULL at start; see comment above */
HANDLE (WINAPI *findFirstFileExProc)(CONST TCHAR*, UINT,
LPVOID, UINT,
LPVOID, DWORD);
BOOL (WINAPI *getVolumeNameForVMPProc)(CONST TCHAR*, TCHAR*, DWORD);
DWORD (WINAPI *getLongPathNameProc)(CONST TCHAR*, TCHAR*, DWORD);
/*
* These six are for the security sdk to get correct file
* permissions on NT, 2000, XP, etc. On 95,98,ME they are
* always null.
*/
BOOL (WINAPI *getFileSecurityProc)(LPCTSTR lpFileName,
SECURITY_INFORMATION RequestedInformation,
|
| ︙ | ︙ |
Changes to win/tclWinNotify.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* * tclWinNotify.c -- * * This file contains Windows-specific procedures for the 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* * tclWinNotify.c -- * * This file contains Windows-specific procedures for the 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. * * RCS: @(#) $Id: tclWinNotify.c,v 1.12.2.1 2004/02/07 05:48:12 dgp Exp $ */ #include "tclWinInt.h" /* * The follwing static indicates whether this module has been initialized. */ |
| ︙ | ︙ | |||
103 104 105 106 107 108 109 |
class.lpszMenuName = NULL;
class.lpszClassName = "TclNotifier";
class.lpfnWndProc = NotifierProc;
class.hIcon = NULL;
class.hCursor = NULL;
if (!RegisterClassA(&class)) {
| | | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
class.lpszMenuName = NULL;
class.lpszClassName = "TclNotifier";
class.lpfnWndProc = NotifierProc;
class.hIcon = NULL;
class.hCursor = NULL;
if (!RegisterClassA(&class)) {
Tcl_Panic("Unable to register TclNotifier window class");
}
}
notifierCount++;
Tcl_MutexUnlock(¬ifierMutex);
tsdPtr->pending = 0;
tsdPtr->timerActive = 0;
|
| ︙ | ︙ |
Changes to win/tclWinPipe.c.
1 2 3 4 5 6 7 8 9 10 11 | /* * tclWinPipe.c -- * * This file implements the Windows-specific exec pipeline functions, * the "pipe" channel driver, and the "pid" Tcl command. * * Copyright (c) 1996-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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * tclWinPipe.c -- * * This file implements the Windows-specific exec pipeline functions, * the "pipe" channel driver, and the "pid" Tcl command. * * Copyright (c) 1996-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. * * RCS: @(#) $Id: tclWinPipe.c,v 1.35.2.3 2004/02/07 05:48:12 dgp Exp $ */ #include "tclWinInt.h" #include <fcntl.h> #include <io.h> #include <sys/stat.h> |
| ︙ | ︙ | |||
870 871 872 873 874 875 876 | ckfree((char *) filePtr); return -1; } } break; default: | | | 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 |
ckfree((char *) filePtr);
return -1;
}
}
break;
default:
Tcl_Panic("TclpCloseFile: unexpected file type");
}
ckfree((char *) filePtr);
return 0;
}
/*
|
| ︙ | ︙ | |||
901 902 903 904 905 906 907 908 909 910 911 912 913 914 |
*/
unsigned long
TclpGetPid(
Tcl_Pid pid) /* The HANDLE of the child process. */
{
ProcInfo *infoPtr;
Tcl_MutexLock(&pipeMutex);
for (infoPtr = procList; infoPtr != NULL; infoPtr = infoPtr->nextPtr) {
if (infoPtr->hProcess == (HANDLE) pid) {
Tcl_MutexUnlock(&pipeMutex);
return infoPtr->dwProcessId;
}
| > > | 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 |
*/
unsigned long
TclpGetPid(
Tcl_Pid pid) /* The HANDLE of the child process. */
{
ProcInfo *infoPtr;
PipeInit();
Tcl_MutexLock(&pipeMutex);
for (infoPtr = procList; infoPtr != NULL; infoPtr = infoPtr->nextPtr) {
if (infoPtr->hProcess == (HANDLE) pid) {
Tcl_MutexUnlock(&pipeMutex);
return infoPtr->dwProcessId;
}
|
| ︙ | ︙ | |||
1211 1212 1213 1214 1215 1216 1217 |
Tcl_DStringAppend(&pipeDll, TCL_PIPE_DLL, -1);
tclExePtr = Tcl_NewStringObj(TclpFindExecutable(""), -1);
start = Tcl_GetStringFromObj(tclExePtr, &i);
for (end = start + (i-1); end > start; end--) {
if (*end == '/')
break;
}
| | | > | | > | | 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 |
Tcl_DStringAppend(&pipeDll, TCL_PIPE_DLL, -1);
tclExePtr = Tcl_NewStringObj(TclpFindExecutable(""), -1);
start = Tcl_GetStringFromObj(tclExePtr, &i);
for (end = start + (i-1); end > start; end--) {
if (*end == '/')
break;
}
if (*end != '/') {
Tcl_Panic("no / in executable path name");
}
i = (end - start) + 1;
pipeDllPtr = Tcl_NewStringObj(start, i);
Tcl_AppendToObj(pipeDllPtr, Tcl_DStringValue(&pipeDll), -1);
Tcl_IncrRefCount(pipeDllPtr);
if (Tcl_FSConvertToPathType(interp, pipeDllPtr) != TCL_OK) {
Tcl_Panic("Tcl_FSConvertToPathType failed");
}
fileExists = (Tcl_FSAccess(pipeDllPtr, F_OK) == 0);
if (!fileExists) {
Tcl_Panic("Tcl pipe dll \"%s\" not found",
Tcl_DStringValue(&pipeDll));
}
Tcl_DStringAppend(&cmdLine, Tcl_DStringValue(&pipeDll), -1);
Tcl_DecrRefCount(tclExePtr);
Tcl_DecrRefCount(pipeDllPtr);
Tcl_DStringFree(&pipeDll);
}
|
| ︙ | ︙ | |||
1573 1574 1575 1576 1577 1578 1579 1580 1581 |
Tcl_DStringAppend(&ds, Tcl_DStringValue(linePtr), -1);
for (i = 0; i < argc; i++) {
if (i == 0) {
arg = executable;
} else {
arg = argv[i];
}
| > < < > > | > | < | | | | > | | < < < < < | | 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 |
Tcl_DStringAppend(&ds, Tcl_DStringValue(linePtr), -1);
for (i = 0; i < argc; i++) {
if (i == 0) {
arg = executable;
} else {
arg = argv[i];
Tcl_DStringAppend(&ds, " ", 1);
}
quote = 0;
if (arg[0] == '\0') {
quote = 1;
} else {
int count;
Tcl_UniChar ch;
for (start = arg; *start != '\0'; start += count) {
count = Tcl_UtfToUniChar(start, &ch);
if (Tcl_UniCharIsSpace(ch)) { /* INTL: ISO space. */
quote = 1;
break;
}
}
}
if (quote) {
Tcl_DStringAppend(&ds, "\"", 1);
}
start = arg;
for (special = arg; ; ) {
if ((*special == '\\') &&
(special[1] == '\\' || special[1] == '"' || (quote && special[1] == '\0'))) {
Tcl_DStringAppend(&ds, start, (int) (special - start));
start = special;
while (1) {
special++;
if (*special == '"' || (quote && *special == '\0')) {
/*
* N backslashes followed a quote -> insert
* N * 2 + 1 backslashes then a quote.
*/
Tcl_DStringAppend(&ds, start,
(int) (special - start));
break;
}
if (*special != '\\') {
break;
}
}
Tcl_DStringAppend(&ds, start, (int) (special - start));
start = special;
}
if (*special == '"') {
Tcl_DStringAppend(&ds, start, (int) (special - start));
Tcl_DStringAppend(&ds, "\\\"", 2);
start = special + 1;
}
if (*special == '\0') {
break;
}
special++;
}
Tcl_DStringAppend(&ds, start, (int) (special - start));
if (quote) {
Tcl_DStringAppend(&ds, "\"", 1);
}
}
Tcl_DStringFree(linePtr);
Tcl_WinUtfToTChar(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds), linePtr);
Tcl_DStringFree(&ds);
|
| ︙ | ︙ | |||
2476 2477 2478 2479 2480 2481 2482 |
Tcl_Pid
Tcl_WaitPid(
Tcl_Pid pid,
int *statPtr,
int options)
{
| | | > | 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 |
Tcl_Pid
Tcl_WaitPid(
Tcl_Pid pid,
int *statPtr,
int options)
{
ProcInfo *infoPtr = NULL, **prevPtrPtr;
DWORD flags;
Tcl_Pid result;
DWORD ret, exitCode;
PipeInit();
/*
* If no pid is specified, do nothing.
*/
if (pid == 0) {
*statPtr = 0;
return 0;
}
/*
* Find the process and cut it from the process list.
*/
Tcl_MutexLock(&pipeMutex);
prevPtrPtr = &procList;
for (infoPtr = procList; infoPtr != NULL;
prevPtrPtr = &infoPtr->nextPtr, infoPtr = infoPtr->nextPtr) {
if (infoPtr->hProcess == (HANDLE) pid) {
*prevPtrPtr = infoPtr->nextPtr;
break;
}
}
Tcl_MutexUnlock(&pipeMutex);
/*
* If the pid is not one of the processes we know about (we started it)
|
| ︙ | ︙ | |||
2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 |
} else {
flags = INFINITE;
}
ret = WaitForSingleObject(infoPtr->hProcess, flags);
if (ret == WAIT_TIMEOUT) {
*statPtr = 0;
if (options & WNOHANG) {
return 0;
} else {
result = 0;
}
} else if (ret == WAIT_OBJECT_0) {
GetExitCodeProcess(infoPtr->hProcess, &exitCode);
if (exitCode & 0xC0000000) {
| > > > > > > > | 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 |
} else {
flags = INFINITE;
}
ret = WaitForSingleObject(infoPtr->hProcess, flags);
if (ret == WAIT_TIMEOUT) {
*statPtr = 0;
if (options & WNOHANG) {
/*
* Re-insert this infoPtr back on the list.
*/
Tcl_MutexLock(&pipeMutex);
infoPtr->nextPtr = procList;
procList = infoPtr;
Tcl_MutexUnlock(&pipeMutex);
return 0;
} else {
result = 0;
}
} else if (ret == WAIT_OBJECT_0) {
GetExitCodeProcess(infoPtr->hProcess, &exitCode);
if (exitCode & 0xC0000000) {
|
| ︙ | ︙ | |||
2592 2593 2594 2595 2596 2597 2598 |
} else {
errno = ECHILD;
*statPtr = ECHILD;
result = (Tcl_Pid) -1;
}
/*
| | < | 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 |
} else {
errno = ECHILD;
*statPtr = ECHILD;
result = (Tcl_Pid) -1;
}
/*
* Officially close the process handle.
*/
CloseHandle(infoPtr->hProcess);
ckfree((char*)infoPtr);
return result;
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ |
Changes to win/tclWinReg.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* * tclWinReg.c -- * * This file contains the implementation of the "registry" Tcl * built-in command. This command is built as a dynamically * loadable extension in a separate DLL. * * 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. * | | > > > | 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 | /* * tclWinReg.c -- * * This file contains the implementation of the "registry" Tcl * built-in command. This command is built as a dynamically * loadable extension in a separate DLL. * * 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. * * RCS: @(#) $Id: tclWinReg.c,v 1.21.4.2 2004/02/07 05:48:12 dgp Exp $ */ #include <tclPort.h> #ifdef _MSC_VER # pragma comment (lib, "advapi32.lib") #endif #include <stdlib.h> /* * TCL_STORAGE_CLASS is set unconditionally to DLLEXPORT because the * Registry_Init declaration is in the source file itself, which is only * accessed when we are building a library. */ |
| ︙ | ︙ | |||
208 209 210 211 212 213 214 |
*----------------------------------------------------------------------
*/
int
Registry_Init(
Tcl_Interp *interp)
{
| | | | 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
*----------------------------------------------------------------------
*/
int
Registry_Init(
Tcl_Interp *interp)
{
if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
return TCL_ERROR;
}
/*
* Determine if the unicode interfaces are available and select the
* appropriate registry function table.
*/
if (TclWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
regWinProcs = &unicodeProcs;
} else {
regWinProcs = &asciiProcs;
}
Tcl_CreateObjCommand(interp, "registry", RegistryObjCmd, NULL, NULL);
return Tcl_PkgProvide(interp, "registry", "1.1.3");
}
/*
*----------------------------------------------------------------------
*
* RegistryObjCmd --
*
|
| ︙ | ︙ |
Changes to win/tclWinSock.c.
1 2 3 4 5 6 7 8 9 10 | /* * tclWinSock.c -- * * This file contains Windows-specific socket related code. * * 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /* * tclWinSock.c -- * * This file contains Windows-specific socket related code. * * 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. * * RCS: @(#) $Id: tclWinSock.c,v 1.37.2.2 2004/02/07 05:48:12 dgp Exp $ */ #include "tclWinInt.h" /* * Make sure to remove the redirection defines set in tclWinPort.h * that is in use in other sections of the core, except for us. |
| ︙ | ︙ | |||
622 623 624 625 626 627 628 629 630 631 632 633 634 635 |
(ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
if (tsdPtr != NULL && tsdPtr->socketThread != NULL) {
DWORD exitCode;
GetExitCodeThread(tsdPtr->socketThread, &exitCode);
if (exitCode == STILL_ACTIVE) {
PostMessage(tsdPtr->hwnd, SOCKET_TERMINATE, 0, 0);
/*
* Wait for the thread to close. This ensures that we are
* completely cleaned up before we leave this function.
*/
| > | > > > > > > > > > | 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 |
(ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
if (tsdPtr != NULL && tsdPtr->socketThread != NULL) {
DWORD exitCode;
GetExitCodeThread(tsdPtr->socketThread, &exitCode);
if (exitCode == STILL_ACTIVE) {
DWORD dwWait;
PostMessage(tsdPtr->hwnd, SOCKET_TERMINATE, 0, 0);
/*
* Wait for the thread to close. This ensures that we are
* completely cleaned up before we leave this function.
*/
dwWait = WaitForSingleObject(tsdPtr->socketThread, 100);
if (dwWait == WAIT_TIMEOUT) {
/*
* Avoids a lock-up, just in case it is needed from an
* unclean exit condition when the thread appears
* running, but isn't.
*/
TerminateThread(tsdPtr->socketThread, EXIT_FAILURE);
}
}
CloseHandle(tsdPtr->socketThread);
tsdPtr->socketThread = NULL;
CloseHandle(tsdPtr->readyEvent);
CloseHandle(tsdPtr->socketListLock);
Tcl_DeleteThreadExitHandler(SocketThreadExitHandler, NULL);
|
| ︙ | ︙ | |||
865 866 867 868 869 870 871 |
* have to watch out for the channel being deleted out from under
* us. This may cause a redundant trip through the event loop, but
* it's simpler than trying to do unwind protection.
*/
Tcl_Time blockTime = { 0, 0 };
Tcl_SetMaxBlockTime(&blockTime);
| | | 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 |
* have to watch out for the channel being deleted out from under
* us. This may cause a redundant trip through the event loop, but
* it's simpler than trying to do unwind protection.
*/
Tcl_Time blockTime = { 0, 0 };
Tcl_SetMaxBlockTime(&blockTime);
mask |= TCL_READABLE|TCL_WRITABLE;
} else if (events & FD_READ) {
fd_set readFds;
struct timeval timeout;
/*
* We must check to see if data is really available, since someone
* could have consumed the data in the meantime. Turn off async
|
| ︙ | ︙ | |||
2252 2253 2254 2255 2256 2257 2258 |
if (!infoPtr->acceptProc) {
infoPtr->watchEvents = 0;
if (mask & TCL_READABLE) {
infoPtr->watchEvents |= (FD_READ|FD_CLOSE|FD_ACCEPT);
}
if (mask & TCL_WRITABLE) {
| | | 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 |
if (!infoPtr->acceptProc) {
infoPtr->watchEvents = 0;
if (mask & TCL_READABLE) {
infoPtr->watchEvents |= (FD_READ|FD_CLOSE|FD_ACCEPT);
}
if (mask & TCL_WRITABLE) {
infoPtr->watchEvents |= (FD_WRITE|FD_CLOSE|FD_CONNECT);
}
/*
* If there are any conditions already set, then tell the notifier to poll
* rather than block.
*/
|
| ︙ | ︙ | |||
2712 2713 2714 2715 2716 2717 2718 |
/*
* 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) {
| | | 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 |
/*
* 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) {
Tcl_Panic("file info ptr not on thread channel list");
}
/*
* Stop notifications for the socket to occur in this thread.
*/
SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
|
| ︙ | ︙ |
Changes to win/tclWinThrd.c.
1 2 3 4 5 6 7 8 9 10 11 | /* * tclWinThread.c -- * * This file implements the Windows-specific thread operations. * * Copyright (c) 1998 by 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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * tclWinThread.c -- * * This file implements the Windows-specific thread operations. * * Copyright (c) 1998 by 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. * * RCS: @(#) $Id: tclWinThrd.c,v 1.26.2.1 2004/02/07 05:48:12 dgp Exp $ */ #include "tclWinInt.h" #include <fcntl.h> #include <io.h> #include <sys/stat.h> |
| ︙ | ︙ | |||
544 545 546 547 548 549 550 |
MASTER_LOCK;
if (*keyPtr == NULL) {
indexPtr = (DWORD *)ckalloc(sizeof(DWORD));
newKey = TlsAlloc();
if (newKey != TLS_OUT_OF_INDEXES) {
*indexPtr = newKey;
} else {
| | | 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 |
MASTER_LOCK;
if (*keyPtr == NULL) {
indexPtr = (DWORD *)ckalloc(sizeof(DWORD));
newKey = TlsAlloc();
if (newKey != TLS_OUT_OF_INDEXES) {
*indexPtr = newKey;
} else {
Tcl_Panic("TlsAlloc failed from TclpThreadDataKeyInit!"); /* this should be a fatal error */
}
*keyPtr = (Tcl_ThreadDataKey)indexPtr;
TclRememberDataKey(keyPtr);
}
MASTER_UNLOCK;
}
|
| ︙ | ︙ | |||
581 582 583 584 585 586 587 |
DWORD *indexPtr = *(DWORD **)keyPtr;
LPVOID result;
if (indexPtr == NULL) {
return NULL;
} else {
result = TlsGetValue(*indexPtr);
if ((result == NULL) && (GetLastError() != NO_ERROR)) {
| | | 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 |
DWORD *indexPtr = *(DWORD **)keyPtr;
LPVOID result;
if (indexPtr == NULL) {
return NULL;
} else {
result = TlsGetValue(*indexPtr);
if ((result == NULL) && (GetLastError() != NO_ERROR)) {
Tcl_Panic("TlsGetValue failed from TclpThreadDataKeyGet!");
}
return result;
}
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
614 615 616 617 618 619 620 |
* really (pthread_key_t **) */
VOID *data; /* Thread local storage */
{
DWORD *indexPtr = *(DWORD **)keyPtr;
BOOL success;
success = TlsSetValue(*indexPtr, (void *)data);
if (!success) {
| | | 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 |
* really (pthread_key_t **) */
VOID *data; /* Thread local storage */
{
DWORD *indexPtr = *(DWORD **)keyPtr;
BOOL success;
success = TlsSetValue(*indexPtr, (void *)data);
if (!success) {
Tcl_Panic("TlsSetValue failed from TclpThreadDataKeySet!");
}
}
/*
*----------------------------------------------------------------------
*
* TclpFinalizeThreadData --
|
| ︙ | ︙ | |||
653 654 655 656 657 658 659 |
if (*keyPtr != NULL) {
indexPtr = *(DWORD **)keyPtr;
result = (VOID *)TlsGetValue(*indexPtr);
if (result != NULL) {
ckfree((char *)result);
success = TlsSetValue(*indexPtr, (void *)NULL);
if (!success) {
| | | | 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 |
if (*keyPtr != NULL) {
indexPtr = *(DWORD **)keyPtr;
result = (VOID *)TlsGetValue(*indexPtr);
if (result != NULL) {
ckfree((char *)result);
success = TlsSetValue(*indexPtr, (void *)NULL);
if (!success) {
Tcl_Panic("TlsSetValue failed from TclpFinalizeThreadData!");
}
} else {
if (GetLastError() != NO_ERROR) {
Tcl_Panic("TlsGetValue failed from TclpFinalizeThreadData!");
}
}
}
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
693 694 695 696 697 698 699 |
{
DWORD *indexPtr;
BOOL success;
if (*keyPtr != NULL) {
indexPtr = *(DWORD **)keyPtr;
success = TlsFree(*indexPtr);
if (!success) {
| | | 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 |
{
DWORD *indexPtr;
BOOL success;
if (*keyPtr != NULL) {
indexPtr = *(DWORD **)keyPtr;
success = TlsFree(*indexPtr);
if (!success) {
Tcl_Panic("TlsFree failed from TclpFinalizeThreadDataKey!");
}
ckfree((char *)indexPtr);
*keyPtr = NULL;
}
}
/*
|
| ︙ | ︙ | |||
902 903 904 905 906 907 908 |
void
Tcl_ConditionNotify(condPtr)
Tcl_Condition *condPtr;
{
WinCondition *winCondPtr;
ThreadSpecificData *tsdPtr;
| | | 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 |
void
Tcl_ConditionNotify(condPtr)
Tcl_Condition *condPtr;
{
WinCondition *winCondPtr;
ThreadSpecificData *tsdPtr;
if (*condPtr != NULL) {
winCondPtr = *((WinCondition **)condPtr);
/*
* Loop through all the threads waiting on the condition
* and notify them (i.e., broadcast semantics). The queue
* manipulation is guarded by the per-condition coordinating mutex.
*/
|
| ︙ | ︙ | |||
1013 1014 1015 1016 1017 1018 1019 |
struct lock {
Tcl_Mutex tlock;
CRITICAL_SECTION wlock;
} *lockPtr;
lockPtr = malloc(sizeof(struct lock));
if (lockPtr == NULL) {
| | | 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 |
struct lock {
Tcl_Mutex tlock;
CRITICAL_SECTION wlock;
} *lockPtr;
lockPtr = malloc(sizeof(struct lock));
if (lockPtr == NULL) {
Tcl_Panic("could not allocate lock");
}
lockPtr->tlock = (Tcl_Mutex) &lockPtr->wlock;
InitializeCriticalSection(&lockPtr->wlock);
return &lockPtr->tlock;
}
void *
|
| ︙ | ︙ | |||
1035 1036 1037 1038 1039 1040 1041 |
* We need to make sure that TclWinFreeAllocCache is called
* on each thread that calls this, but only on threads that
* call this.
*/
key = TlsAlloc();
once = 1;
if (key == TLS_OUT_OF_INDEXES) {
| | | | | | | 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 |
* We need to make sure that TclWinFreeAllocCache is called
* on each thread that calls this, but only on threads that
* call this.
*/
key = TlsAlloc();
once = 1;
if (key == TLS_OUT_OF_INDEXES) {
Tcl_Panic("could not allocate thread local storage");
}
}
result = TlsGetValue(key);
if ((result == NULL) && (GetLastError() != NO_ERROR)) {
Tcl_Panic("TlsGetValue failed from TclpGetAllocCache!");
}
return result;
}
void
TclpSetAllocCache(void *ptr)
{
BOOL success;
success = TlsSetValue(key, ptr);
if (!success) {
Tcl_Panic("TlsSetValue failed from TclpSetAllocCache!");
}
}
void
TclWinFreeAllocCache(void)
{
void *ptr;
BOOL success;
ptr = TlsGetValue(key);
if (ptr != NULL) {
success = TlsSetValue(key, NULL);
if (!success) {
Tcl_Panic("TlsSetValue failed from TclWinFreeAllocCache!");
}
TclFreeAllocCache(ptr);
} else {
if (GetLastError() != NO_ERROR) {
Tcl_Panic("TlsGetValue failed from TclWinFreeAllocCache!");
}
}
}
#endif /* USE_THREAD_ALLOC */
#endif /* TCL_THREADS */
|
Changes to win/tclWinTime.c.
1 2 3 4 5 6 7 8 9 10 11 | /* * tclWinTime.c -- * * Contains Windows specific versions of Tcl functions that * obtain time values from the operating system. * * Copyright 1995-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. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * tclWinTime.c -- * * Contains Windows specific versions of Tcl functions that * obtain time values from the operating system. * * Copyright 1995-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. * * RCS: @(#) $Id: tclWinTime.c,v 1.18.2.3 2004/02/07 05:48:12 dgp Exp $ */ #include "tclWinInt.h" #define SECSPERDAY (60L * 60L * 24L) #define SECSPERYEAR (SECSPERDAY * 365L) #define SECSPER4YEAR (SECSPERYEAR * 4L + SECSPERDAY) |
| ︙ | ︙ | |||
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 |
/*
* If we are in the valid range, let the C run-time library
* handle it. Otherwise we need to fake it. Note that this
* algorithm ignores daylight savings time before the epoch.
*/
if (*tp >= 0) {
return localtime(tp);
}
time = *tp - timezone;
/*
* If we aren't near to overflowing the long, just add the bias and
| > > > > > > > > > > > > > | 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 |
/*
* If we are in the valid range, let the C run-time library
* handle it. Otherwise we need to fake it. Note that this
* algorithm ignores daylight savings time before the epoch.
*/
/*
Hm, Borland's localtime manages to return NULL under certain
circumstances (e.g. wintime.test, test 1.2). Nobody tests for this,
since 'localtime' isn't supposed to do this, possibly leading to
crashes.
Patch: We only call this function if we are at least one day into
the epoch, else we handle it ourselves (like we do for times < 0).
H. Giese, June 2003
*/
#ifdef __BORLANDC__
if (*tp >= SECSPERDAY) {
#else
if (*tp >= 0) {
#endif
return localtime(tp);
}
time = *tp - timezone;
/*
* If we aren't near to overflowing the long, just add the bias and
|
| ︙ | ︙ |
Changes to win/tclsh.rc.
|
| | | | | | | 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 | // RCS: @(#) $Id: tclsh.rc,v 1.8.4.1 2004/02/07 05:48:12 dgp Exp $ // // Version Resource Script // #include <winver.h> #include <tcl.h> // // build-up the name suffix that defines the type of build this is. // #if TCL_THREADS #define SUFFIX_THREADS "t" #else #define SUFFIX_THREADS "" #endif #if STATIC_BUILD #define SUFFIX_STATIC "s" #else #define SUFFIX_STATIC "" #endif #if DEBUG #define SUFFIX_DEBUG "g" #else #define SUFFIX_DEBUG "" #endif #define SUFFIX SUFFIX_THREADS SUFFIX_STATIC SUFFIX_DEBUG |
| ︙ | ︙ | |||
46 47 48 49 50 51 52 |
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "FileDescription", "Tclsh Application\0"
| | | 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "FileDescription", "Tclsh Application\0"
VALUE "OriginalFilename", "tclsh" STRINGIFY(TCL_MAJOR_VERSION) STRINGIFY(TCL_MINOR_VERSION) SUFFIX ".exe\0"
VALUE "CompanyName", "ActiveState Corporation\0"
VALUE "FileVersion", TCL_PATCH_LEVEL
VALUE "LegalCopyright", "Copyright \251 2000 by ActiveState Corporation, et al\0"
VALUE "ProductName", "Tcl " TCL_VERSION " for Windows\0"
VALUE "ProductVersion", TCL_PATCH_LEVEL
END
END
|
| ︙ | ︙ |