├── tea.pdf ├── .cvsignore ├── pkgIndex.tcl.in ├── aclocal.m4 ├── tea ├── toman.tcl ├── codingstyle.txt ├── introduction.txt ├── app_config_options.txt ├── stubs.txt ├── app_makefiles.txt ├── writingdocs.txt ├── writingtests.txt ├── packages.txt ├── makefiles.txt └── design.txt ├── tests ├── sample.test ├── tclsample.test └── all.tcl ├── win ├── sample.rc ├── makefile.vc ├── rules.vc └── nmakehlp.c ├── generic ├── sample.h ├── sample.c └── tclsample.c ├── license.terms ├── doc ├── sha1.n └── man.macros ├── README.sha ├── README ├── configure.in ├── Makefile.in └── ChangeLog /tea.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcltk/sampleextension-deprecated/master/tea.pdf -------------------------------------------------------------------------------- /.cvsignore: -------------------------------------------------------------------------------- 1 | autom4te.cache 2 | Makefile 3 | pkgIndex.tcl 4 | *.dll 5 | *.so 6 | config.status 7 | -------------------------------------------------------------------------------- /pkgIndex.tcl.in: -------------------------------------------------------------------------------- 1 | # 2 | # Tcl package index file 3 | # 4 | package ifneeded @PACKAGE_NAME@ @PACKAGE_VERSION@ \ 5 | [list load [file join $dir @PKG_LIB_FILE@] @PACKAGE_NAME@] 6 | -------------------------------------------------------------------------------- /aclocal.m4: -------------------------------------------------------------------------------- 1 | # 2 | # Include the TEA standard macro set 3 | # 4 | 5 | builtin(include,tclconfig/tcl.m4) 6 | 7 | # 8 | # Add here whatever m4 macros you want to define for your package 9 | # 10 | -------------------------------------------------------------------------------- /tea/toman.tcl: -------------------------------------------------------------------------------- 1 | # Small script to assemble the separate chapters to a single file 2 | # 3 | proc putfile {filename} { 4 | set infile [open $filename] 5 | puts $::outfile [read $infile] 6 | close $infile 7 | } 8 | 9 | set outfile [open "teadoc.man" "w"] 10 | 11 | puts $outfile \ 12 | {[manpage_begin {TEA documentation} n 0.2] 13 | [moddesc TEA] 14 | [titledesc {TEA documentation}]} 15 | 16 | putfile introduction.txt 17 | putfile design.txt 18 | putfile codingstyle.txt 19 | putfile packages.txt 20 | putfile stubs.txt 21 | putfile makefiles.txt 22 | putfile writingtests.txt 23 | putfile writingdocs.txt 24 | putfile app_makefiles.txt 25 | putfile app_config_options.txt 26 | 27 | puts $outfile {[manpage_end]} 28 | close $outfile 29 | 30 | -------------------------------------------------------------------------------- /tests/sample.test: -------------------------------------------------------------------------------- 1 | # Commands covered: sha1 2 | # 3 | # This file contains a collection of tests for one or more of the Tcl 4 | # built-in commands. Sourcing this file into Tcl runs the tests and 5 | # generates output for errors. No output means no errors were found. 6 | # 7 | # Copyright (c) 2000 by Scriptics Corporation. 8 | # 9 | # See the file "license.terms" for information on usage and redistribution 10 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. 11 | # 12 | # RCS: @(#) $Id$ 13 | 14 | if {[lsearch [namespace children] ::tcltest] == -1} { 15 | package require tcltest 16 | namespace import ::tcltest::* 17 | } 18 | 19 | package require sample 20 | 21 | test sha-1.1 {Use of -string operand} { 22 | set result [sha1 -string foo] 23 | } {0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33} 24 | 25 | test sha-1.2 {Use of -init operand} { 26 | set result [catch {sha1 -init}] 27 | } {0} 28 | 29 | 30 | # cleanup 31 | ::tcltest::cleanupTests 32 | return 33 | -------------------------------------------------------------------------------- /win/sample.rc: -------------------------------------------------------------------------------- 1 | // sample.rc - Copyright (C) 2006 Pat Thoyts 2 | // 3 | // There is no need to modify this file. 4 | // 5 | 6 | #include 7 | 8 | VS_VERSION_INFO VERSIONINFO 9 | FILEVERSION COMMAVERSION 10 | PRODUCTVERSION COMMAVERSION 11 | FILEFLAGSMASK 0x3fL 12 | #ifdef DEBUG 13 | FILEFLAGS VS_FF_DEBUG 14 | #else 15 | FILEFLAGS 0x0L 16 | #endif 17 | FILEOS VOS__WINDOWS32 18 | FILETYPE VFT_DLL 19 | FILESUBTYPE 0x0L 20 | BEGIN 21 | BLOCK "StringFileInfo" 22 | BEGIN 23 | BLOCK "040904b0" 24 | BEGIN 25 | VALUE "FileDescription", "Tcl Sample Extension " DOTVERSION "\0" 26 | VALUE "OriginalFilename", "sample" VERSION ".dll\0" 27 | VALUE "CompanyName", "The Tcl Development Community\0" 28 | VALUE "FileVersion", DOTVERSION "\0" 29 | VALUE "LegalCopyright", "Copyright \251 1999 Scriptics Corp.\0" 30 | VALUE "ProductName", "Tcl Sample Extension " DOTVERSION "\0" 31 | VALUE "ProductVersion", DOTVERSION "\0" 32 | END 33 | END 34 | BLOCK "VarFileInfo" 35 | BEGIN 36 | VALUE "Translation", 0x409, 1200 37 | END 38 | END 39 | -------------------------------------------------------------------------------- /generic/sample.h: -------------------------------------------------------------------------------- 1 | /* 2 | * sample.h -- 3 | * 4 | * This header file contains the function declarations needed for 5 | * all of the source files in this package. 6 | * 7 | * Copyright (c) 1998-1999 Scriptics Corporation. 8 | * Copyright (c) 2003 ActiveState Corporation. 9 | * 10 | * See the file "license.terms" for information on usage and redistribution 11 | * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 12 | * 13 | */ 14 | 15 | #ifndef _SAMPLE 16 | #define _SAMPLE 17 | 18 | #include 19 | 20 | /* 21 | * Windows needs to know which symbols to export. 22 | */ 23 | 24 | #ifdef BUILD_sample 25 | #undef TCL_STORAGE_CLASS 26 | #define TCL_STORAGE_CLASS DLLEXPORT 27 | #endif /* BUILD_sample */ 28 | 29 | #ifdef HAVE_INTTYPES_H 30 | # include 31 | typedef uint32_t sha_uint32_t; 32 | #else 33 | # if ((1<<31)<0) 34 | typedef unsigned long sha_uint32_t; 35 | # else 36 | typedef unsigned int sha_uint32_t; 37 | # endif 38 | #endif 39 | 40 | typedef struct { 41 | sha_uint32_t state[5]; 42 | sha_uint32_t count[2]; 43 | unsigned char buffer[64]; 44 | } SHA1_CTX; 45 | 46 | void SHA1Init (SHA1_CTX* context); 47 | void SHA1Update (SHA1_CTX* context, unsigned char* data, unsigned int len); 48 | void SHA1Final (SHA1_CTX* context, unsigned char digest[20]); 49 | 50 | /* 51 | * Only the _Init function is exported. 52 | */ 53 | 54 | EXTERN int Sample_Init(Tcl_Interp * interp); 55 | 56 | #endif /* _SAMPLE */ 57 | -------------------------------------------------------------------------------- /tests/tclsample.test: -------------------------------------------------------------------------------- 1 | # Commands covered: sha1 2 | # 3 | # This file contains a collection of tests for one or more of the Tcl 4 | # built-in commands. Sourcing this file into Tcl runs the tests and 5 | # generates output for errors. No output means no errors were found. 6 | # 7 | # Copyright (c) 2000 by Scriptics Corporation. 8 | # 9 | # See the file "license.terms" for information on usage and redistribution 10 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. 11 | # 12 | # RCS: @(#) $Id$ 13 | 14 | if {[lsearch [namespace children] ::tcltest] == -1} { 15 | package require tcltest 16 | namespace import ::tcltest::* 17 | } 18 | 19 | package require sample 20 | 21 | test sha-1.1 {incorrect command usage} { 22 | list [catch {sha1} errMsg] $errMsg 23 | } {1 {wrong # args: should be either: 24 | sha1 ?-log2base log2base? -string string 25 | or 26 | sha1 ?-log2base log2base? ?-copychan chanID? -chan chanID 27 | or 28 | sha1 -init (returns descriptor) 29 | sha1 -update descriptor ?-maxbytes n? ?-copychan chanID? -chan chanID 30 | (any number of -update calls, returns number of bytes read) 31 | sha1 ?-log2base log2base? -final descriptor 32 | The default log2base is 4 (hex)}} 33 | 34 | test sha-1.2 {incorrect usage of -log2base option} { 35 | list [catch {sha1 -log2base 0 -string foo} errMsg] $errMsg 36 | } {1 {parameter to -log2base "0" must be integer in range 1...6}} 37 | 38 | # cleanup 39 | ::tcltest::cleanupTests 40 | return 41 | -------------------------------------------------------------------------------- /tea/codingstyle.txt: -------------------------------------------------------------------------------- 1 | [section {Chapter 3. RECOMMENDED CODING STYLE}] 2 | 3 | We do not want to say too much about coding style, and certainly we do 4 | not want to prescribe any particular style. Just make sure for yourself 5 | that: 6 | [list_begin bullet] 7 | 8 | [bullet] 9 | you have added appropriate and clear comments to the code 10 | 11 | [bullet] 12 | you have used well-defined and clear constructs, not too many C macros 13 | and such, which can make it difficult to understand the code 14 | 15 | [bullet] 16 | you do not rely on compiler-specific features (extensions to the 17 | standard language that are very uncommon for instance) 18 | 19 | [bullet] 20 | you dare show it to other people, as other people will definitely see 21 | it and read your code. 22 | 23 | [list_end] 24 | 25 | A very good example of coding style is Tcl itself: the code is 26 | well-documented, the layout is clean, with a bit of study you can really 27 | understand what is going on. More textual descriptions of a 28 | recommended coding style for C and for Tcl can be found in: 29 | .... 30 | 31 | [para] 32 | We can add a few conventions here, almost trivial, perhaps, but since 33 | they are very often used, it will help people to understand your code 34 | better: 35 | 36 | [list_begin bullet] 37 | 38 | [bullet] 39 | For the use of namespaces (highly recommended to avoid name clashes), 40 | read the tutorial by Will Duquette. 41 | 42 | [bullet] 43 | Avoid the use of global variables, use namespace variables instead. 44 | 45 | [bullet] 46 | For "public" routines use names that start with a lowercase letter 47 | and add these to a [namespace export] command 48 | 49 | [bullet] 50 | For "private" routines use names that start with an uppercase letter 51 | 52 | [list_end] 53 | 54 | If you implement your extension in C, remember to use the Tcl_Obj 55 | interface: it is much faster than the old pre-8.0 interface that used 56 | strings. This means that you may need to pay quite some attention to 57 | issues like reference counts, but it is certainly worth the effort. 58 | -------------------------------------------------------------------------------- /tests/all.tcl: -------------------------------------------------------------------------------- 1 | # all.tcl -- 2 | # 3 | # This file contains a top-level script to run all of the Tcl 4 | # tests. Execute it by invoking "source all.test" when running tcltest 5 | # in this directory. 6 | # 7 | # Copyright (c) 1998-2000 by Scriptics Corporation. 8 | # All rights reserved. 9 | # 10 | # RCS: @(#) $Id$ 11 | 12 | if {[lsearch [namespace children] ::tcltest] == -1} { 13 | package require tcltest 14 | namespace import ::tcltest::* 15 | } 16 | 17 | set ::tcltest::testSingleFile false 18 | set ::tcltest::testsDirectory [file dir [info script]] 19 | 20 | # We need to ensure that the testsDirectory is absolute 21 | if {[catch {::tcltest::normalizePath ::tcltest::testsDirectory}]} { 22 | # The version of tcltest we have here does not support 23 | # 'normalizePath', so we have to do this on our own. 24 | 25 | set oldpwd [pwd] 26 | catch {cd $::tcltest::testsDirectory} 27 | set ::tcltest::testsDirectory [pwd] 28 | cd $oldpwd 29 | } 30 | 31 | set chan $::tcltest::outputChannel 32 | 33 | puts $chan "Tests running in interp: [info nameofexecutable]" 34 | puts $chan "Tests running with pwd: [pwd]" 35 | puts $chan "Tests running in working dir: $::tcltest::testsDirectory" 36 | if {[llength $::tcltest::skip] > 0} { 37 | puts $chan "Skipping tests that match: $::tcltest::skip" 38 | } 39 | if {[llength $::tcltest::match] > 0} { 40 | puts $chan "Only running tests that match: $::tcltest::match" 41 | } 42 | 43 | if {[llength $::tcltest::skipFiles] > 0} { 44 | puts $chan "Skipping test files that match: $::tcltest::skipFiles" 45 | } 46 | if {[llength $::tcltest::matchFiles] > 0} { 47 | puts $chan "Only sourcing test files that match: $::tcltest::matchFiles" 48 | } 49 | 50 | set timeCmd {clock format [clock seconds]} 51 | puts $chan "Tests began at [eval $timeCmd]" 52 | 53 | # source each of the specified tests 54 | foreach file [lsort [::tcltest::getMatchingFiles]] { 55 | set tail [file tail $file] 56 | puts $chan $tail 57 | if {[catch {source $file} msg]} { 58 | puts $chan $msg 59 | } 60 | } 61 | 62 | # cleanup 63 | puts $chan "\nTests ended at [eval $timeCmd]" 64 | ::tcltest::cleanupTests 1 65 | return 66 | 67 | -------------------------------------------------------------------------------- /tea/introduction.txt: -------------------------------------------------------------------------------- 1 | [comment { 2 | Remarks: 3 | - The sample extension uses the string interface 4 | - Is the sample extension in CVS up to date? 5 | - What makes tkimg special - its own stubs - why? 6 | }] 7 | 8 | [description] 9 | The Tcl Extension Architecture is meant to help developers set up a 10 | standardised environment so that any user can compile the extension 11 | without any knowledge of the extension. This way a lot of work can be 12 | saved. 13 | 14 | This document describes the various aspects of TEA in detail. 15 | 16 | [section {Chapter 1. OVERVIEW}] 17 | 18 | TEA relies heavily on the GNU tool [emph autoconf]. An intimate 19 | knowledge of this tool is, fortunately, not required, but for complicated 20 | extensions that rely on many things specific to a particular platform, 21 | it may be necessary to add your own checks and procedures to the 22 | existing TEA macro library. 23 | 24 | The structure of this document is as follows: 25 | [sectref {Chapter 2. DESIGN AND CODING}] describes the typical 26 | organisation in files and directories of an extension. 27 | 28 | [para] 29 | [sectref {Chapter 3. RECOMMENDED CODING STYLE}] holds information 30 | about what you should and should not do when coding an extension. 31 | 32 | [para] 33 | [sectref {Chapter 4. TCL PACKAGES}] highlights the package mechanism 34 | that is used by Tcl, whereas [sectref {Chapter 5. TCL STUBS}] explains 35 | the stubs mechanism, important for creating compiled extensions that are 36 | independent of the particular Tcl version. 37 | 38 | [para] 39 | [sectref {Chapter 6. CONFIGURE AND MAKE FILES}] is perhaps the most 40 | important chapter, as this describes how to create the input for the 41 | [emph autoconf] tool. 42 | 43 | [para] 44 | The subjects of [sectref {Chapter 7. WRITING AND RUNNING TESTS}] and 45 | [sectref {Chapter 8. DOCUMENTATION}] may not among most programmers' 46 | favourites, but they are very important to users. And everybody at some 47 | point is a user! 48 | 49 | [para] 50 | [sectref {Appendix A. Explanation of make files and the make utility}] 51 | is meant especially for those programmers not familiar to 52 | make files, because their development environment shields the 53 | complexities from them. 54 | -------------------------------------------------------------------------------- /license.terms: -------------------------------------------------------------------------------- 1 | This software is copyrighted by the Scriptics Corporation, and other 2 | parties. The following terms apply to all files associated with the 3 | software unless explicitly disclaimed in individual files. 4 | 5 | The authors hereby grant permission to use, copy, modify, distribute, 6 | and license this software and its documentation for any purpose, provided 7 | that existing copyright notices are retained in all copies and that this 8 | notice is included verbatim in any distributions. No written agreement, 9 | license, or royalty fee is required for any of the authorized uses. 10 | Modifications to this software may be copyrighted by their authors 11 | and need not follow the licensing terms described here, provided that 12 | the new terms are clearly indicated on the first page of each file where 13 | they apply. 14 | 15 | IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY 16 | FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 17 | ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY 18 | DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE 19 | POSSIBILITY OF SUCH DAMAGE. 20 | 21 | THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, 22 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE 24 | IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE 25 | NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 26 | MODIFICATIONS. 27 | 28 | GOVERNMENT USE: If you are acquiring this software on behalf of the 29 | U.S. government, the Government shall have only "Restricted Rights" 30 | in the software and related documentation as defined in the Federal 31 | Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you 32 | are acquiring the software on behalf of the Department of Defense, the 33 | software shall be classified as "Commercial Computer Software" and the 34 | Government shall have only "Restricted Rights" as defined in Clause 35 | 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the 36 | authors grant the U.S. Government and others acting in its behalf 37 | permission to use and distribute the software in accordance with the 38 | terms specified in this license. 39 | -------------------------------------------------------------------------------- /doc/sha1.n: -------------------------------------------------------------------------------- 1 | '\" 2 | .so man.macros 3 | .TH sha1 n 4.1 "Tcl-Extensions" 4 | .HS sha1 tcl 5 | .BS 6 | '\" Note: do not modify the .SH NAME line immediately below! 7 | .SH NAME 8 | sha1 \- manipulate sha1 message digests 9 | .SH SYNOPSIS 10 | \fBpackage require sample\fR ?\fB0.5\fR? 11 | .sp 12 | \fBsha1\fR ?\fB\-log2base \fIlog2base\fR? \fB\-string \fIstring\fR 13 | .br 14 | or 15 | .br 16 | \fBsha1\fR ?\fB\-log2base \fIlog2base\fR? ?\fB\-copychan \fIcopyChanID\fR? \fB\-chan \fIchanID\fR 17 | .br 18 | or 19 | .br 20 | \fBsha1 \-init\fR (returns descriptor) 21 | .br 22 | \fBsha1 \-update \fIdescriptor\fR ?\fB\-maxbytes \fIn\fR? ?\fB\-copychan \fIchanID\fR? \fB\-chan \fIchanID\fR 23 | .br 24 | \fBsha1\fR ?\fB\-log2base \fIlog2base\fR? \fB\-final \fIdescriptor\fR 25 | .BE 26 | .SH DESCRIPTION 27 | .PP 28 | SHA1 is NIST's Secure Hashing Algorithm (also known as Secure Hashing 29 | Standard) with the minor modification that they proposed on 7/11/94. 30 | .PP 31 | Switches can be in any order. 32 | .PP 33 | Returns a sha1 digest in base 2 ** log2base ascii representation. 34 | log2base defaults to 4, i.e., hex representation. 35 | .PP 36 | .nf 37 | \fBlog2base length chars\fR 38 | 1 160 01 \fI(binary)\fR 39 | 2 80 0..3 40 | 3 54 0...7 \fI(octal)\fR 41 | 4 40 0..9a..f \fI(hex)\fR 42 | 5 32 0..9a..v 43 | 6 27 0..9a..zA..Z_, 44 | .fi 45 | .PP 46 | (The characters in the digest string have been chosen to be usable in 47 | filenames so that the sha1 command can be used, for example, to digest URLs 48 | into shorter strings for filenames in a cache.) 49 | .PP 50 | In the \fB\-string\fR version, returns sha1 digest alone of \fIstring\fR. 51 | .PP 52 | In the \fB\-chan\fR version, returns list of 2 items: length of data in 53 | \fIchanID\fR followed by sha1 digest of all data in \fIchanID\fR. 54 | \fIChanID\fR is identifier returned from "\fBopen\fR" for example. If 55 | \fB\-copychan\fR is supplied, will also copy all data from \fIchanID\fR to 56 | \fIcopychanID\fR. 57 | .PP 58 | In the third form, \fB\-init\fR returns a descriptor, \fB\-update\fR can be 59 | called any number of times with that descriptor and returns the number of 60 | bytes read, and \fB\-final\fR returns the result in the same form as the 61 | standalone \fB\-chan\fR. 62 | '\" Local Variables: 63 | '\" mode: nroff 64 | '\" fill-column: 78 65 | '\" End: 66 | -------------------------------------------------------------------------------- /README.sha: -------------------------------------------------------------------------------- 1 | sha1 - manipulate sha1 message digests 2 | 3 | SHA1 is NIST's Secure Hashing Algorithm (also known as Secure Hashing 4 | Standard) with the minor modification that they proposed on 7/11/94. 5 | 6 | To make type: 7 | 8 | ./configure 9 | make 10 | make install 11 | 12 | The configure script will deduce $PREFIX from the tcl installation. 13 | The generated Makefile uses the file $PREFIX/lib/tclConfig.sh that was left by 14 | the make of tcl for most of its configuration parameters. 15 | 16 | The Makefile generates pkgIndex.tcl files that are compatible with 17 | tcl7.6. If you are using tcl7.5 then you will need to edit 18 | $PREFIX/lib/pkgIndex.tcl by hand. 19 | 20 | Usage: 21 | 22 | sha1 ?-log2base log2base? -string string 23 | 24 | or 25 | 26 | sha1 ?-log2base log2base? ?-copychan chanID? -chan chanID 27 | 28 | or 29 | 30 | sha1 -init (returns descriptor) 31 | sha1 -update descriptor ?-maxbytes n? ?-copychan chanID? -chan chanID 32 | sha1 ?-log2base log2base? -final descriptor 33 | 34 | 35 | Switches can be in any order. 36 | 37 | Returns a sha1 digest in base 2 ** log2base ascii representation. 38 | log2base defaults to 4, i.e. hex representation. 39 | 40 | log2base length chars 41 | 1 160 01 (binary) 42 | 2 80 0..3 43 | 3 54 0...7 (octal) 44 | 4 40 0..9a..f (hex) 45 | 5 32 0..9a..v 46 | 6 27 0..9a..zA..Z_, 47 | 48 | (The characters in the digest string have been chosen to be usable in 49 | filenames so that the sha1 command can be used, for example, 50 | to digest URLs into shorter strings for filenames in a cache.) 51 | 52 | In the -string version, returns sha1 digest of string. 53 | 54 | In the -chan version, returns list of 2 items: length of data 55 | in chanID followed by sha1 digest of all data in chanID. ChanID is 56 | identifier returned from "open" for example. If -copychan is supplied, 57 | will also copy all data from chanID to copychanID. 58 | 59 | In the third form, -init returns a descriptor, -update can be called 60 | any number of times with that descriptor and returns the number of 61 | bytes read, and -final returns the result in the same form as the 62 | standalone -chan. 63 | 64 | Written by: John Ellson (ellson@lucent.com) 65 | modified by: Dave Dykstra (dwd@bell-labs.com) 66 | 67 | Use at your own risk. No support. No copyright. 68 | -------------------------------------------------------------------------------- /tea/app_config_options.txt: -------------------------------------------------------------------------------- 1 | [section {Appendix B. Configuration options}] 2 | 3 | The [emph configure] script as generated by Autoconf will support a 4 | number of standard configuration options as well as any that you define 5 | for your extension via the [emph AC_ARG_WITH] and [emph AC_ARG_ENABLE] 6 | macros. 7 | [para] 8 | The table below describes the standard configuration options (most of the 9 | text is copied from B. Welch's book "Practical Tcl and Tk programming", 3rd edition) 10 | 11 | [list_begin bullet] 12 | 13 | [bullet] 14 | --prefix=[emph dir] 15 | [nl] 16 | Defines the root of the installation directory - default: /usr/local. 17 | 18 | [bullet] 19 | --exec-prefix=[emph dir] 20 | [nl] 21 | Defines the root of the installation directory for platform-specific files 22 | - default: the value of "--prefix". 23 | 24 | [bullet] 25 | --enable-gcc/--disable-gcc (default) 26 | [nl] 27 | Use the [emph gcc] compiler instead of the native (enable) or use 28 | the native compiler (disable). 29 | 30 | [bullet] 31 | --enable-shared (default)/--disable-shared 32 | [nl] 33 | Compile and link to get [emph {shared/dynamic}] libraries (enable) or compile and link 34 | to get [emph {archive/static}] libraries (disable). 35 | 36 | [bullet] 37 | --enable-symbols/--disable-symbols (default) 38 | [nl] 39 | Compile and link for debugging (enable) or compile and link without debugging (disable). 40 | 41 | [bullet] 42 | --enable-threads/--disable-threads (default) 43 | [nl] 44 | Turn multithreading support on (enable) or off (disable). 45 | 46 | [bullet] 47 | --with-tcl=[emph dir] 48 | [nl] 49 | Specifies the directory where Tcl was built (especially important if you build against 50 | a number of Tcl versions or for more than one platform) 51 | 52 | [bullet] 53 | --with-tk=[emph dir] 54 | [nl] 55 | Specifies the directory where Tk was built 56 | 57 | [bullet] 58 | --with-tclinclude=[emph dir] 59 | [nl] 60 | Specifies the directory where the Tcl include files can be found (notably: tcl.h) 61 | 62 | [bullet] 63 | --with-tcllib=[emph dir] 64 | [nl] 65 | Specifies the directory where the Tcl libraries can be found (notably: libtclstubs.a) 66 | 67 | [bullet] 68 | --with-x11include=[emph dir] 69 | [nl] 70 | Specifies the directory where the X11 include files (such as X11.h) can be found (especially important 71 | if these are not found in one of the usual places) 72 | 73 | [bullet] 74 | --with-x11lib=[emph dir] 75 | [nl] 76 | Specifies the directory where the X11 libraries (e.g. libX11.so) can be found 77 | 78 | [list_end] 79 | 80 | Note that all of these options come with reasonable defaults, so that you only 81 | have to worry about them when the configure script terminates with some kind of 82 | error. 83 | -------------------------------------------------------------------------------- /tea/stubs.txt: -------------------------------------------------------------------------------- 1 | [section {Chapter 5. TCL STUBS}] 2 | 3 | The highly recommended way of using the Tcl and Tk libraries in a 4 | compiled extension is via [emph stubs]. Stubs allow you to compile and 5 | link an extension and use it with any (later) version of Tcl/Tk. If you 6 | do not, then the libraries can only be used with a very specific version 7 | of Tcl/Tk. This chapter provides some information about what the 8 | advantages and disadvantages are of using stubs. 9 | 10 | [para] 11 | It may seem intimidating at first, but the stubs mechanism in Tcl 12 | (available since version 8.1) is actually very simple - from the point 13 | of view of the programmer: 14 | [list_begin bullet] 15 | 16 | [bullet] 17 | You use the call to Tcl_InitStubs() in the initialisation routine 18 | (see the previous chapter) 19 | 20 | [bullet] 21 | You define a macro USE_TCL_STUBS when compiling the code 22 | 23 | [bullet] 24 | You link against the Tcl and Tk stubs library, instead of the actual 25 | libraries. 26 | 27 | [list_end] 28 | 29 | (Needless to say that most is automatically taken care of by the TEA.) 30 | 31 | [para] 32 | Here is what stubs are all about: rather than using the functions in the 33 | Tcl/Tk libraries directly, you access them via a pointer. The actual 34 | code that is involved is hidden from you via C macros, so you have 35 | nothing to worry about, except for the USE_TCL_STUBS macro and the 36 | proper initialisation. More information can be found in ... 37 | 38 | [para] 39 | The limitations of using stubs are that you can only use the Tcl 40 | functions that are publically available in the stub table (see for 41 | details the header files tcl.h and tk.h). You can not use the private 42 | functions (found in the other header files), but this is a bad idea in 43 | the first place, because the interface to these functions may change 44 | from one release to the next - they are simply not meant for use outside 45 | the Tcl library itself. 46 | 47 | [para] 48 | The advantages of stubs are plenty: 49 | 50 | [list_begin bullet] 51 | 52 | [bullet] 53 | You can compile and link the extension against, say, Tcl 8.3 and use 54 | it in Tcl 8.5. That is: the libraries remain useful. 55 | 56 | [bullet] 57 | It is thus also practical to provide binary versions only (if you want 58 | or need to keep the source code secret) 59 | 60 | [bullet] 61 | Stub-enabled extensions can be used in Tclkit, as this relies heavily 62 | on the stub mechanism. 63 | 64 | [list_end] 65 | 66 | To summarise: 67 | [para] 68 | When you use the TEA, then the only thing you need to take care of in 69 | your code, is that the initialisation routine calls Tcl_InitStubs(). 70 | 71 | [para] 72 | Using stubs gives benefits both to you and the users of your extension 73 | that can not be had in another way. 74 | 75 | 76 | [section {Providing your own stubs}] 77 | 78 | A more complicated situation arises when your extension itself defines a 79 | stubs library. This was discussed in some length in Chapter 2. The 80 | advantage is that your functions can be used at the C level too and 81 | would form a veritable extension to the Tcl/Tk API. 82 | 83 | [para] 84 | In the build step this means that besides the ordinary shared object 85 | or DLL also a stubs library must be created. The process is almost 86 | automatic, except that you have to tell which functions are to be made 87 | available in the stubs library (via the .decls file) and you have to 88 | make some provisions in the TEA configuration and make files. 89 | 90 | [para] 91 | If the functions of your extension are to be registered in the Tcl or Tk 92 | library, as is the case with tkimg that provides new formats for the 93 | photo command, then it is necessary or at least highly recommended that 94 | you provide them via the stubs mechanism. 95 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This is a sample extension showing an implementation of the Tcl Extension 2 | Architecture (TEA). Please see the webpage 3 | 4 | http://www.tcl.tk/doc/tea/ 5 | 6 | for more details on TEA. You can also read the enclosed "tea.pdf" document 7 | for instructions on how to adapt this sample extension to your extension. 8 | 9 | This package is a freely available open source package. You can do 10 | virtually anything you like with it, such as modifying it, redistributing 11 | it, and selling it either in whole or in part. See the file 12 | "license.terms" for complete information. 13 | 14 | CONTENTS 15 | ======== 16 | The following is a short description of the files you will find in 17 | the sample extension. 18 | 19 | Makefile.in Makefile template. The configure script uses this file to 20 | produce the final Makefile. 21 | 22 | README This file 23 | 24 | README.sha A description of the extension itself. 25 | 26 | aclocal.m4 Generated file. Do not edit. Autoconf uses this as input 27 | when generating the final configure script. See "tcl.m4" 28 | below. 29 | 30 | configure Generated file. Do not edit. This must be regenerated 31 | anytime configure.in or tclconfig/tcl.m4 changes. 32 | 33 | configure.in Configure script template. Autoconf uses this file as input 34 | to produce the final configure script. 35 | 36 | pkgIndex.tcl.in Package index template. The configure script will use 37 | this file as input to create pkgIndex.tcl. 38 | 39 | sample.c Core Secure Hash Algorithm code. 40 | 41 | sample.h Header file for functions in the C files. 42 | 43 | sha1.n Unix nroff man page 44 | 45 | tclsample.c Implementation of new Tcl command "sha1". 46 | 47 | tea.pdf PDF file describing the current implementation of the 48 | Tcl Extension Architecture 49 | 50 | tclconfig/ This directory contains various template files that build 51 | the configure script. They should not need modification. 52 | 53 | install-sh Program used for copying binaries and script files 54 | to their install locations. 55 | 56 | tcl.m4 Collection of Tcl autoconf macros. Included by 57 | aclocal.m4 to define SC_* macros. 58 | 59 | UNIX BUILD 60 | ========== 61 | 62 | Building under most UNIX systems is easy, just run the configure script 63 | and then run make. For more information about the build process, see 64 | the tcl/unix/README file in the Tcl src dist. The following minimal 65 | example will install the extension in the /opt/tcl directory. 66 | 67 | $ cd sampleextension 68 | $ ./configure --prefix=/opt/tcl 69 | $ make 70 | $ make install 71 | 72 | WINDOWS BUILD 73 | ============= 74 | 75 | The recommended method to build extensions under windows is to use the 76 | Msys + Mingw build process. This provides a Unix-style build while 77 | generating native Windows binaries. Using the Msys + Mingw build tools 78 | means that you can use the same configure script as per the Unix build 79 | to create a Makefile. See the tcl/win/README file for the URL of 80 | the Msys + Mingw download. 81 | 82 | If you have VC++ then you may wish to use the files in the win 83 | subdirectory and build the extension using just VC++. These files have 84 | been designed to be as generic as possible but will require some 85 | additional maintenance by the project developer to synchronise with 86 | the TEA configure.in and Makefile.in files. Instructions for using the 87 | VC++ makefile are written in the first part of the Makefile.vc 88 | file. 89 | 90 | INSTALLATION 91 | ============ 92 | 93 | The installation of a TEA package is structure like so: 94 | 95 | $exec_prefix 96 | / \ 97 | lib bin 98 | | | 99 | PACKAGEx.y (dependent .dll files on Windows) 100 | | 101 | pkgIndex.tcl (.so|.dll files) 102 | 103 | The main .so|.dll library file gets installed in the versioned PACKAGE 104 | directory, which is OK on all platforms because it will be directly 105 | referenced with by 'load' in the pkgIndex.tcl file. Dependent DLL files on 106 | Windows must go in the bin directory (or other directory on the user's 107 | PATH) in order for them to be found. 108 | -------------------------------------------------------------------------------- /tea/app_makefiles.txt: -------------------------------------------------------------------------------- 1 | [section {Appendix A. Explanation of make files and the make utility}] 2 | 3 | If you are not familiar with the [emph make] program, here is a brief 4 | explanation of it. In some of its features it is very similar to 5 | MicroSoft's Visual Studio or other [emph {integrated development environments}]: 6 | it processes descriptions of how to create a program from its 7 | sources and does so in an efficient way. In fact, many IDE's use the 8 | [emph {make}] utility in some form or other underneath. 9 | 10 | [para] 11 | The main difference between the [emph make] utility and most, "modern" 12 | IDE's is that [emph make] does not itself manage the description, the 13 | so-called [emph {make file}]. This is left to the programmer. Another 14 | difference is that [emph make] can be used for almost any task where 15 | files need to be built 16 | from other files using some program, in other words it is very flexible. 17 | 18 | [para] 19 | [emph {A small example}] 20 | [para] 21 | 22 | So far the introduction to [emph make]. Let us now describe how 23 | [emph make] does the 24 | job it is supposed to do, using the following sample program: 25 | 26 | [para] 27 | The program "sample" is built from two C source files, sample.c and 28 | utils.c. The first source file includes a header file utils.h, which 29 | contains the interface to the functions in utils.c. 30 | 31 | [para] 32 | Now changes to any of these files mean that the whole program has to be 33 | rebuilt. For this small program, we could easily type the command: 34 | [example { 35 | cc -o sample sample.c utils.c 36 | }] 37 | 38 | (or something similar, depending on the compiler you want to use). This 39 | would recompile the entire source and relink the program against all its 40 | parts. 41 | 42 | [para] 43 | Now: 44 | 45 | [list_begin bullet] 46 | 47 | [bullet] 48 | If only utils.c has changed, then it is a waste of time to recompile 49 | sample.c. 50 | 51 | [bullet] 52 | If the header file "utils.h" has changed, recompiling both is required, 53 | as the prototype of a function may have changed or something else that 54 | is vital to the functions in "utils.c". Only this is not clear at all 55 | from the command we just typed: the dependence of the two source files 56 | on this header file is hidden inside the sources! 57 | 58 | [list_end] 59 | 60 | This is what the [emph make] utility would do, when properly instructed: 61 | 62 | [list_begin bullet] 63 | 64 | [bullet] 65 | The file "sample" (our executable program) and others are defined 66 | as "targets": things for the [emph make] utility to examine. 67 | 68 | [bullet] 69 | The file "sample" depends on two "object files" (the results of 70 | a compilation): 71 | 72 | [list_begin bullet] 73 | [bullet] 74 | sample.o 75 | [bullet] 76 | utils.o 77 | [list_end] 78 | 79 | If any of these files is out of date, then the program is out of date. 80 | 81 | [bullet] 82 | So check if these two files are out of date, by checking their 83 | dependencies: 84 | 85 | [list_begin bullet] 86 | [bullet] 87 | sample.o depends on sample.c and utils.h (because sample.c uses 88 | that header file) 89 | [bullet] 90 | in a similar way, utils.o depends on utils.c and utils.h. 91 | By the same reasoning, check these three files. 92 | [list_end] 93 | 94 | [bullet] 95 | These files are source files and header files, we have edited these 96 | files manually, they can not be created from other files. So, this 97 | is the end of that step in the reasoning process. 98 | [bullet] 99 | The object files sample.o and utils.o are out of date if the three 100 | files are newer: 101 | 102 | [list_begin bullet] 103 | [bullet] 104 | sample.o is out of date if sample.c or utils.h is newer than this file. 105 | Then use the rule that belongs to sample.o to rebuild it 106 | [bullet] 107 | utils.o is out of date if utils.c or utils.h is newer than this file. 108 | Again: use the rule that belongs to utils.o to rebuild that. 109 | [list_end] 110 | 111 | [bullet] 112 | Now the two files that our program depends on are up to date. 113 | The program itself clearly is not. So, relink that program. 114 | 115 | [list_end] 116 | 117 | The makefile might look like this: 118 | [example { 119 | sample->:->sample.o utils.o 120 | ->cc -o sample sample.o utils.o 121 | 122 | sample.o->:->sample.c utils.h 123 | ->cc -c sample.c 124 | 125 | utils.o->:->utils.c utils.h 126 | ->cc -c utils.c 127 | }] 128 | (the symbol "->" indicates a tab character - this is essential in makefiles, 129 | as it is used to identify what lines belong together) 130 | 131 | [para] 132 | This is a very simple makefile, in practice programs that are maintained with 133 | makefiles are much larger, you need to take of building the documentation, 134 | libraries, of installing the files at the proper location and so on. To make 135 | things worse: many compilers use different options to specify similar 136 | tasks and operating systems require different libraries (or put the 137 | libraries in different places). 138 | 139 | [para] 140 | To help manage the makefiles, the [emph autoconf] utility was created. This 141 | utility prepares the correct makefile from a given template, using a 142 | complicated but relatively easy to use configuration script. 143 | -------------------------------------------------------------------------------- /tea/writingdocs.txt: -------------------------------------------------------------------------------- 1 | [section {Chapter 8. DOCUMENTATION}] 2 | 3 | It may seem a heavy burden for many a programmer, but documentation 4 | is necessary, even though one sometimes gets the impression (quite 5 | wrongly of course, but still) that no user ever bothers to read it. 6 | 7 | [para] 8 | Besides proper comments in the code, we need a guide for users to fall 9 | back on. Traditionally for Tcl/Tk this has been in the form of 10 | UNIX-style man pages: 11 | 12 | [list_begin bullet] 13 | 14 | [bullet] 15 | A short introduction to the command 16 | 17 | [bullet] 18 | A list of commands that one can use 19 | 20 | [bullet] 21 | One or more sections with explanations 22 | 23 | [list_end] 24 | 25 | This is a format that works well for more or less experienced users - 26 | they use the man page as a reference manual. On the other hand, new 27 | users may find them a bit awkward, as a lot of background is 28 | usually assumed. 29 | 30 | [para] 31 | For most extensions, it will suffice to use the classical man page 32 | format with perhaps some more explanation of what the extension is all 33 | about and some more examples and elaborated code fragments than usual. 34 | 35 | [para] 36 | To help with writing the documentation, we strongly suggest you use the 37 | so-called [emph doctools] that are now part of the standard Tcl applications. 38 | The basic idea of doctools is simple: 39 | 40 | [list_begin bullet] 41 | 42 | [bullet] 43 | You write the text for the man page using doctools' macros 44 | 45 | [bullet] 46 | These markup macros can be regarded as embedded Tcl commands and 47 | provide the markup system with clues as to how to format the text 48 | (many of the macros represent [emph semantic] clues, instead of mere style 49 | information) 50 | 51 | [bullet] 52 | The doctools application can then process this text and turn it into 53 | any of a number of formats, such as HTML but also nroff and TMML (Tcl 54 | Manual Markup Language). 55 | 56 | [bullet] 57 | This way, one single source suffices to generate all kinds of output 58 | files, suitable for most online documentation systems. 59 | 60 | [list_end] 61 | 62 | Here is a small example of such an input file: 63 | [example { 64 | ...... 65 | }] 66 | 67 | This file can be processed by the doctools application, to give an 68 | HTML-file that is rendered like this: 69 | 70 | [example { 71 | /picture/ ?? 72 | }] 73 | 74 | [section {Short overview of the macros supported by doctools}] 75 | 76 | [para] 77 | [lb]arg $name[rb] 78 | - argument in a [lb]call[rb] statement 79 | [para] 80 | 81 | [lb]arg_def $type $name $intent[rb] 82 | - description of the argument, what type it is (widget, integer, list, 83 | ...), its name and whether it simply passed to the command (in) 84 | or gets set as well (out or in/out) 85 | [para] 86 | 87 | [lb]bullet[rb] 88 | - start a new item in a bullet list 89 | [para] 90 | 91 | [lb]call $cmd $args[rb] 92 | - define a command (its argument list; the command gets added to the 93 | synopsis) 94 | [para] 95 | 96 | [lb]cmd $name[rb] 97 | - name of the command (first argument for [lb]call[rb]) 98 | [para] 99 | 100 | [lb]comment $text[rb] 101 | - add comments to the original, does not show up in the output 102 | [para] 103 | 104 | [lb]copyright $name[rb] 105 | - insert a copyright string at the end of the rendered document 106 | [para] 107 | 108 | [lb]description[rb] 109 | - start the man page section DESCRIPTION (note: this section is required 110 | at the beginning of the document) 111 | [para] 112 | 113 | [lb]emph $text[rb] 114 | - show the given text as emphasized (typically italic) 115 | [para] 116 | 117 | [lb]example $example[rb] 118 | - insert preformatted text that serves as an example for the commands 119 | being discussed 120 | [para] 121 | 122 | [lb]keywords $args[rb] 123 | - add the keywords given in the variable argument list to the end of the 124 | document 125 | [para] 126 | 127 | [lb]list_begin arg[rb] 128 | - start a list of arguments (after a corresponding [lb]call[rb] command) 129 | [para] 130 | 131 | [lb]list_begin bullet[rb] 132 | - start a bullet list 133 | [para] 134 | 135 | [lb]list_begin definitions[rb] 136 | - start a definitions list 137 | [para] 138 | 139 | [lb]list_begin opt[rb] 140 | - start a list of options 141 | [para] 142 | 143 | [lb]list_end[rb] 144 | - end the current list, brackets [lb]list_begin[rb] 145 | [para] 146 | 147 | [lb]manpage_begin $name $section $version[rb] 148 | - indicate the start of the manual page with the name of the 149 | module/package/extension, the section of the manual pages it should go 150 | into (always "n") and the version number 151 | [para] 152 | 153 | [lb]manpage_end[rb] 154 | mandatory end of the man page, brackets the [lb]manpage_begin[rb] command 155 | [para] 156 | 157 | [lb]moddesc $name[rb] 158 | - identify the module 159 | [para] 160 | 161 | [lb]nl[rb] 162 | - put a break in the flowing text. Useable only within lists 163 | [para] 164 | 165 | [lb]opt_def $keyword $type[rb] 166 | - the keyword for an option (without the leading minus sign) and the 167 | expected value type (if any) 168 | [para] 169 | 170 | [lb]para[rb] 171 | - start a new paragraph 172 | [para] 173 | 174 | [lb]require $package $version[rb] 175 | - insert a "package require" command in the synopsis of the man page to 176 | indicate the dependencies 177 | [para] 178 | 179 | [lb]section $title[rb] 180 | - start a new section, the title is traditionally given in capitals 181 | [para] 182 | 183 | [lb]titledesc $title[rb] 184 | - give the man page a proper title 185 | 186 | 187 | [section REFERENCES] 188 | 189 | [list_begin bullet] 190 | 191 | [bullet] 192 | Will Duquette: Guidelines for using namespaces 193 | 194 | [bullet] 195 | Ray Johnson: Tcl/Tk style guide 196 | 197 | [bullet] 198 | Ray Johnson: Engineering manual 199 | 200 | [bullet] 201 | Andreas Kupries: Documentation doctools 202 | 203 | [bullet] 204 | Boris Beizer: Software Testing Techniques 205 | 206 | [bullet] 207 | ??: Managing project with make 208 | 209 | [bullet] 210 | ??: Information on stubs 211 | 212 | [bullet] 213 | Don Porter: Man page on tcltest 214 | 215 | [bullet] 216 | ??: Autoconf documentation 217 | 218 | [list_end] 219 | -------------------------------------------------------------------------------- /tea/writingtests.txt: -------------------------------------------------------------------------------- 1 | [section {Chapter 7. WRITING AND RUNNING TESTS}] 2 | 3 | As the developer of an extension you are probably in the best 4 | position to identify the kind of things that need to be tested: 5 | 6 | [list_begin bullet] 7 | 8 | [bullet] 9 | The reaction of a command to valid input 10 | 11 | [bullet] 12 | What constitutes invalid input and how your extension deals 13 | with that. 14 | 15 | [list_end] 16 | 17 | It is quite possible to give theoretically sound guidelines for 18 | a complete test suite (complete that is in the sense of some 19 | test criterium, for instance that all code is executed at 20 | least once when all the test cases are run). However, the 21 | same theory also teaches us that each criterium has its 22 | weaknesses and will let through certain types of bugs. 23 | Furthermore, the number of test cases and the management 24 | of the test code becomes unwieldy when your extension achieves 25 | a considerable size. (For more information, the classical 26 | book by Boris Beizer, Software Testing Techniques, can be consulted. 27 | There are many more similar publications.) 28 | 29 | [para] 30 | Let us deal instead with some more practical guidelines. Here are 31 | some minimal requirements: 32 | 33 | [list_begin bullet] 34 | 35 | [bullet] 36 | For all public commands in your extension, there should be at least 37 | one test case. If possible the test case should be small so that 38 | it concentrates on one and only one command, but that may not 39 | always be possible. 40 | 41 | [bullet] 42 | For all public commands at least one or two examples with [emph invalid] 43 | input (if there is any) should be defined. The purpose is to 44 | show that the extension can gracefully deal with such erroneous 45 | calls. 46 | [list_end] 47 | 48 | [para] 49 | If practical, then: 50 | 51 | [list_begin bullet] 52 | 53 | [bullet] 54 | You should define a fairly exhaustive set of 55 | test cases that together deal with all the defined functionality of the extension. 56 | 57 | [bullet] 58 | In a similar fashion all error cases should be included. 59 | 60 | [list_end] 61 | 62 | How we set up the tests? Simple, use the [emph tcltest] package. This package 63 | provides a complete and versatile infrastructure to deal with running 64 | tests and reporting the results (see the quite extensive manual page). 65 | 66 | [para] 67 | Here is a summary: 68 | 69 | [list_begin bullet] 70 | 71 | [bullet] 72 | Define small scripts that should return a known value. 73 | 74 | [bullet] 75 | The scripts are run and the actually returned value is compared 76 | to the expected value. 77 | 78 | [bullet] 79 | If there is a difference, then this is reported and the test fails. 80 | 81 | [bullet] 82 | For more flexibility: 83 | 84 | [list_begin bullet] 85 | [bullet] 86 | You can define the way the two values should be compared 87 | (via glob or regular expression matching or via a user-defined 88 | method, in case of floating-point values for instance) 89 | [bullet] 90 | You can define constraints for the tests - some tests only make 91 | sense on a specific platform for instance 92 | [bullet] 93 | You can prepare files via the special procedures that the tcltest 94 | package provides, so that they can be cleaned up properly. 95 | [list_end] 96 | 97 | [list_end] 98 | 99 | To illustrate this discussion with an example, consider an extension 100 | with a command "isValidXYZFile", this command checks the contents of the 101 | given file (the one argument to this command) and returns 1 if it is 102 | indeed a valid XYZ file (whatever XYZ files are) and 0 if it is not. 103 | 104 | [para] 105 | Test cases for this command could include: 106 | 107 | [list_begin bullet] 108 | 109 | [bullet] 110 | A valid XYZ file 111 | 112 | [bullet] 113 | An arbitrary file (that certainly is not an XYZ file) 114 | 115 | [bullet] 116 | No argument at all 117 | 118 | [bullet] 119 | A non-existent file 120 | 121 | [bullet] 122 | Two or more commands 123 | 124 | [list_end] 125 | 126 | The first two fall in the category "valid input", the others represent 127 | particular invalid input that the command is supposed to gracefully 128 | deal with (recognise that the input is not correct and report an 129 | error). 130 | 131 | [para] 132 | Traditionally, test scripts are contained in files with the extension 133 | ".test". So let us put the following code in a file "xyzfiles.test" to 134 | test our "xyzfiles" extension: 135 | [example { 136 | # 137 | # Initialise the test package (we need only the "test" command) 138 | # 139 | package require tcltest 140 | namespace import ::tcltest::test 141 | 142 | # 143 | # Get our xyzfiles extension 144 | # 145 | package require xyzfiles 146 | namespace import xyzfiles::isValidXYZFile 147 | 148 | # 149 | # Our tests for valid input (sample.xyz is a valid XYZ file 150 | # ships with the extension, sampe2.xyz is an invalid but 151 | # existing file) 152 | # 153 | 154 | test "xyzfiles-1.1" "Valid XYZ file" -body { 155 | isValidXYZFile "sample.xyz" 156 | } -result 1 ;# It is a valid file, so the command returns 1 157 | 158 | test "xyzfiles-1.2" "Not a valid XYZ file" -body { 159 | isValidXYZFile "sample2.xyz" 160 | } -result 0 161 | 162 | # 163 | # Invalid input (the major test number is changed for convenience 164 | # only): 165 | # 166 | 167 | test "xyzfiles-2.1" "No argument" -body { 168 | isValidXYZFile 169 | } -returnCodes error -result "wrong # args: *" -match glob 170 | 171 | # tcltest uses exact matching by default, so we change that for this case 172 | 173 | test "xyzfiles-2.2" "Non-existent file" -body { 174 | isValidXYZFile "non-existent-file.xyz" 175 | } -returnCodes error -result "Non existent file *" -match glob 176 | 177 | test "xyzfiles-2.3" "Too many arguments" -body { 178 | isValidXYZFile 1 2 3 4 179 | } -returnCodes error -result "wrong # args: *" -match glob 180 | }] 181 | 182 | Note that in the last three cases we use the [lb]catch[rb] command to catch 183 | the intended errors and we use the glob matching option to match against 184 | a rough string, rather than an exact string. 185 | 186 | [para] 187 | Testing the arguments is of course much more important in case 188 | of a compiled extension than in case of a Tcl-only procedure, but 189 | if there are subcommands that require different numbers of arguments 190 | it can be a good idea to add tests like the above. 191 | 192 | [para] 193 | These tests can be run by the command: 194 | [example { 195 | > make test 196 | }] 197 | (See the code for "test" target in the make file) 198 | 199 | [para] 200 | It is good style to always run every test in a test suite. If some 201 | tests fail on some platforms, use test constraints to prevent running 202 | of those particular tests. You can also use test constraints to 203 | protect non-test pieces of code in the test file. 204 | -------------------------------------------------------------------------------- /doc/man.macros: -------------------------------------------------------------------------------- 1 | .\" The -*- nroff -*- definitions below are for supplemental macros used 2 | .\" in Tcl/Tk manual entries. 3 | .\" 4 | .\" .AP type name in/out ?indent? 5 | .\" Start paragraph describing an argument to a library procedure. 6 | .\" type is type of argument (int, etc.), in/out is either "in", "out", 7 | .\" or "in/out" to describe whether procedure reads or modifies arg, 8 | .\" and indent is equivalent to second arg of .IP (shouldn't ever be 9 | .\" needed; use .AS below instead) 10 | .\" 11 | .\" .AS ?type? ?name? 12 | .\" Give maximum sizes of arguments for setting tab stops. Type and 13 | .\" name are examples of largest possible arguments that will be passed 14 | .\" to .AP later. If args are omitted, default tab stops are used. 15 | .\" 16 | .\" .BS 17 | .\" Start box enclosure. From here until next .BE, everything will be 18 | .\" enclosed in one large box. 19 | .\" 20 | .\" .BE 21 | .\" End of box enclosure. 22 | .\" 23 | .\" .CS 24 | .\" Begin code excerpt. 25 | .\" 26 | .\" .CE 27 | .\" End code excerpt. 28 | .\" 29 | .\" .VS ?version? ?br? 30 | .\" Begin vertical sidebar, for use in marking newly-changed parts 31 | .\" of man pages. The first argument is ignored and used for recording 32 | .\" the version when the .VS was added, so that the sidebars can be 33 | .\" found and removed when they reach a certain age. If another argument 34 | .\" is present, then a line break is forced before starting the sidebar. 35 | .\" 36 | .\" .VE 37 | .\" End of vertical sidebar. 38 | .\" 39 | .\" .DS 40 | .\" Begin an indented unfilled display. 41 | .\" 42 | .\" .DE 43 | .\" End of indented unfilled display. 44 | .\" 45 | .\" .SO ?manpage? 46 | .\" Start of list of standard options for a Tk widget. The manpage 47 | .\" argument defines where to look up the standard options; if 48 | .\" omitted, defaults to "options". The options follow on successive 49 | .\" lines, in three columns separated by tabs. 50 | .\" 51 | .\" .SE 52 | .\" End of list of standard options for a Tk widget. 53 | .\" 54 | .\" .OP cmdName dbName dbClass 55 | .\" Start of description of a specific option. cmdName gives the 56 | .\" option's name as specified in the class command, dbName gives 57 | .\" the option's name in the option database, and dbClass gives 58 | .\" the option's class in the option database. 59 | .\" 60 | .\" .UL arg1 arg2 61 | .\" Print arg1 underlined, then print arg2 normally. 62 | .\" 63 | .\" .QW arg1 ?arg2? 64 | .\" Print arg1 in quotes, then arg2 normally (for trailing punctuation). 65 | .\" 66 | .\" .PQ arg1 ?arg2? 67 | .\" Print an open parenthesis, arg1 in quotes, then arg2 normally 68 | .\" (for trailing punctuation) and then a closing parenthesis. 69 | .\" 70 | .\" RCS: @(#) $Id$ 71 | .\" 72 | .\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages. 73 | .if t .wh -1.3i ^B 74 | .nr ^l \n(.l 75 | .ad b 76 | .\" # Start an argument description 77 | .de AP 78 | .ie !"\\$4"" .TP \\$4 79 | .el \{\ 80 | . ie !"\\$2"" .TP \\n()Cu 81 | . el .TP 15 82 | .\} 83 | .ta \\n()Au \\n()Bu 84 | .ie !"\\$3"" \{\ 85 | \&\\$1 \\fI\\$2\\fP (\\$3) 86 | .\".b 87 | .\} 88 | .el \{\ 89 | .br 90 | .ie !"\\$2"" \{\ 91 | \&\\$1 \\fI\\$2\\fP 92 | .\} 93 | .el \{\ 94 | \&\\fI\\$1\\fP 95 | .\} 96 | .\} 97 | .. 98 | .\" # define tabbing values for .AP 99 | .de AS 100 | .nr )A 10n 101 | .if !"\\$1"" .nr )A \\w'\\$1'u+3n 102 | .nr )B \\n()Au+15n 103 | .\" 104 | .if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n 105 | .nr )C \\n()Bu+\\w'(in/out)'u+2n 106 | .. 107 | .AS Tcl_Interp Tcl_CreateInterp in/out 108 | .\" # BS - start boxed text 109 | .\" # ^y = starting y location 110 | .\" # ^b = 1 111 | .de BS 112 | .br 113 | .mk ^y 114 | .nr ^b 1u 115 | .if n .nf 116 | .if n .ti 0 117 | .if n \l'\\n(.lu\(ul' 118 | .if n .fi 119 | .. 120 | .\" # BE - end boxed text (draw box now) 121 | .de BE 122 | .nf 123 | .ti 0 124 | .mk ^t 125 | .ie n \l'\\n(^lu\(ul' 126 | .el \{\ 127 | .\" Draw four-sided box normally, but don't draw top of 128 | .\" box if the box started on an earlier page. 129 | .ie !\\n(^b-1 \{\ 130 | \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' 131 | .\} 132 | .el \}\ 133 | \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' 134 | .\} 135 | .\} 136 | .fi 137 | .br 138 | .nr ^b 0 139 | .. 140 | .\" # VS - start vertical sidebar 141 | .\" # ^Y = starting y location 142 | .\" # ^v = 1 (for troff; for nroff this doesn't matter) 143 | .de VS 144 | .if !"\\$2"" .br 145 | .mk ^Y 146 | .ie n 'mc \s12\(br\s0 147 | .el .nr ^v 1u 148 | .. 149 | .\" # VE - end of vertical sidebar 150 | .de VE 151 | .ie n 'mc 152 | .el \{\ 153 | .ev 2 154 | .nf 155 | .ti 0 156 | .mk ^t 157 | \h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' 158 | .sp -1 159 | .fi 160 | .ev 161 | .\} 162 | .nr ^v 0 163 | .. 164 | .\" # Special macro to handle page bottom: finish off current 165 | .\" # box/sidebar if in box/sidebar mode, then invoked standard 166 | .\" # page bottom macro. 167 | .de ^B 168 | .ev 2 169 | 'ti 0 170 | 'nf 171 | .mk ^t 172 | .if \\n(^b \{\ 173 | .\" Draw three-sided box if this is the box's first page, 174 | .\" draw two sides but no top otherwise. 175 | .ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c 176 | .el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c 177 | .\} 178 | .if \\n(^v \{\ 179 | .nr ^x \\n(^tu+1v-\\n(^Yu 180 | \kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c 181 | .\} 182 | .bp 183 | 'fi 184 | .ev 185 | .if \\n(^b \{\ 186 | .mk ^y 187 | .nr ^b 2 188 | .\} 189 | .if \\n(^v \{\ 190 | .mk ^Y 191 | .\} 192 | .. 193 | .\" # DS - begin display 194 | .de DS 195 | .RS 196 | .nf 197 | .sp 198 | .. 199 | .\" # DE - end display 200 | .de DE 201 | .fi 202 | .RE 203 | .sp 204 | .. 205 | .\" # SO - start of list of standard options 206 | .de SO 207 | 'ie '\\$1'' .ds So \\fBoptions\\fR 208 | 'el .ds So \\fB\\$1\\fR 209 | .SH "STANDARD OPTIONS" 210 | .LP 211 | .nf 212 | .ta 5.5c 11c 213 | .ft B 214 | .. 215 | .\" # SE - end of list of standard options 216 | .de SE 217 | .fi 218 | .ft R 219 | .LP 220 | See the \\*(So manual entry for details on the standard options. 221 | .. 222 | .\" # OP - start of full description for a single option 223 | .de OP 224 | .LP 225 | .nf 226 | .ta 4c 227 | Command-Line Name: \\fB\\$1\\fR 228 | Database Name: \\fB\\$2\\fR 229 | Database Class: \\fB\\$3\\fR 230 | .fi 231 | .IP 232 | .. 233 | .\" # CS - begin code excerpt 234 | .de CS 235 | .RS 236 | .nf 237 | .ta .25i .5i .75i 1i 238 | .. 239 | .\" # CE - end code excerpt 240 | .de CE 241 | .fi 242 | .RE 243 | .. 244 | .\" # UL - underline word 245 | .de UL 246 | \\$1\l'|0\(ul'\\$2 247 | .. 248 | .\" # QW - apply quotation marks to word 249 | .de QW 250 | .ie '\\*(lq'"' ``\\$1''\\$2 251 | .\"" fix emacs highlighting 252 | .el \\*(lq\\$1\\*(rq\\$2 253 | .. 254 | .\" # PQ - apply parens and quotation marks to word 255 | .de PQ 256 | .ie '\\*(lq'"' (``\\$1''\\$2)\\$3 257 | .\"" fix emacs highlighting 258 | .el (\\*(lq\\$1\\*(rq\\$2)\\$3 259 | .. 260 | .\" # QR - quoted range 261 | .de QR 262 | .ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3 263 | .\"" fix emacs highlighting 264 | .el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3 265 | .. 266 | .\" # MT - "empty" string 267 | .de MT 268 | .QW "" 269 | .. 270 | -------------------------------------------------------------------------------- /configure.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash -norc 2 | dnl This file is an input file used by the GNU "autoconf" program to 3 | dnl generate the file "configure", which is run during Tcl installation 4 | dnl to configure the system for the local environment. 5 | # 6 | # RCS: @(#) $Id$ 7 | 8 | #----------------------------------------------------------------------- 9 | # Sample configure.in for Tcl Extensions. The only places you should 10 | # need to modify this file are marked by the string __CHANGE__ 11 | #----------------------------------------------------------------------- 12 | 13 | #----------------------------------------------------------------------- 14 | # __CHANGE__ 15 | # Set your package name and version numbers here. 16 | # 17 | # This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION 18 | # set as provided. These will also be added as -D defs in your Makefile 19 | # so you can encode the package version directly into the source files. 20 | # This will also define a special symbol for Windows (BUILD_sample in 21 | # this case) so that we create the export library with the dll. 22 | #----------------------------------------------------------------------- 23 | 24 | AC_INIT([sample], [0.5]) 25 | 26 | #-------------------------------------------------------------------- 27 | # Call TEA_INIT as the first TEA_ macro to set up initial vars. 28 | # This will define a ${TEA_PLATFORM} variable == "unix" or "windows" 29 | # as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. 30 | # -------------------------------------------------------------------- 31 | 32 | TEA_INIT([3.9]) 33 | 34 | AC_CONFIG_AUX_DIR(tclconfig) 35 | 36 | #-------------------------------------------------------------------- 37 | # Load the tclConfig.sh file 38 | #-------------------------------------------------------------------- 39 | 40 | TEA_PATH_TCLCONFIG 41 | TEA_LOAD_TCLCONFIG 42 | 43 | #-------------------------------------------------------------------- 44 | # Load the tkConfig.sh file if necessary (Tk extension) 45 | #-------------------------------------------------------------------- 46 | 47 | #TEA_PATH_TKCONFIG 48 | #TEA_LOAD_TKCONFIG 49 | 50 | #----------------------------------------------------------------------- 51 | # Handle the --prefix=... option by defaulting to what Tcl gave. 52 | # Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. 53 | #----------------------------------------------------------------------- 54 | 55 | TEA_PREFIX 56 | 57 | #----------------------------------------------------------------------- 58 | # Standard compiler checks. 59 | # This sets up CC by using the CC env var, or looks for gcc otherwise. 60 | # This also calls AC_PROG_CC and a few others to create the basic setup 61 | # necessary to compile executables. 62 | #----------------------------------------------------------------------- 63 | 64 | TEA_SETUP_COMPILER 65 | 66 | #----------------------------------------------------------------------- 67 | # __CHANGE__ 68 | # Specify the C source files to compile in TEA_ADD_SOURCES, 69 | # public headers that need to be installed in TEA_ADD_HEADERS, 70 | # stub library C source files to compile in TEA_ADD_STUB_SOURCES, 71 | # and runtime Tcl library files in TEA_ADD_TCL_SOURCES. 72 | # This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS 73 | # and PKG_TCL_SOURCES. 74 | #----------------------------------------------------------------------- 75 | 76 | TEA_ADD_SOURCES([sample.c tclsample.c]) 77 | TEA_ADD_HEADERS([]) 78 | TEA_ADD_INCLUDES([]) 79 | TEA_ADD_LIBS([]) 80 | TEA_ADD_CFLAGS([]) 81 | TEA_ADD_STUB_SOURCES([]) 82 | TEA_ADD_TCL_SOURCES([]) 83 | 84 | #-------------------------------------------------------------------- 85 | # __CHANGE__ 86 | # 87 | # You can add more files to clean if your extension creates any extra 88 | # files by extending CLEANFILES. 89 | # Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure 90 | # and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var. 91 | # 92 | # A few miscellaneous platform-specific items: 93 | # TEA_ADD_* any platform specific compiler/build info here. 94 | #-------------------------------------------------------------------- 95 | 96 | #CLEANFILES="$CLEANFILES pkgIndex.tcl" 97 | if test "${TEA_PLATFORM}" = "windows" ; then 98 | # Ensure no empty if clauses 99 | : 100 | #TEA_ADD_SOURCES([win/winFile.c]) 101 | #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"]) 102 | else 103 | # Ensure no empty else clauses 104 | : 105 | #TEA_ADD_SOURCES([unix/unixFile.c]) 106 | #TEA_ADD_LIBS([-lsuperfly]) 107 | fi 108 | 109 | #-------------------------------------------------------------------- 110 | # __CHANGE__ 111 | # Choose which headers you need. Extension authors should try very 112 | # hard to only rely on the Tcl public header files. Internal headers 113 | # contain private data structures and are subject to change without 114 | # notice. 115 | # This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG 116 | #-------------------------------------------------------------------- 117 | 118 | TEA_PUBLIC_TCL_HEADERS 119 | #TEA_PRIVATE_TCL_HEADERS 120 | 121 | #TEA_PUBLIC_TK_HEADERS 122 | #TEA_PRIVATE_TK_HEADERS 123 | #TEA_PATH_X 124 | 125 | #-------------------------------------------------------------------- 126 | # Check whether --enable-threads or --disable-threads was given. 127 | # This auto-enables if Tcl was compiled threaded. 128 | #-------------------------------------------------------------------- 129 | 130 | TEA_ENABLE_THREADS 131 | 132 | #-------------------------------------------------------------------- 133 | # The statement below defines a collection of symbols related to 134 | # building as a shared library instead of a static library. 135 | #-------------------------------------------------------------------- 136 | 137 | TEA_ENABLE_SHARED 138 | 139 | #-------------------------------------------------------------------- 140 | # This macro figures out what flags to use with the compiler/linker 141 | # when building shared/static debug/optimized objects. This information 142 | # can be taken from the tclConfig.sh file, but this figures it all out. 143 | #-------------------------------------------------------------------- 144 | 145 | TEA_CONFIG_CFLAGS 146 | 147 | #-------------------------------------------------------------------- 148 | # Set the default compiler switches based on the --enable-symbols option. 149 | #-------------------------------------------------------------------- 150 | 151 | TEA_ENABLE_SYMBOLS 152 | 153 | #-------------------------------------------------------------------- 154 | # Everyone should be linking against the Tcl stub library. If you 155 | # can't for some reason, remove this definition. If you aren't using 156 | # stubs, you also need to modify the SHLIB_LD_LIBS setting below to 157 | # link against the non-stubbed Tcl library. Add Tk too if necessary. 158 | #-------------------------------------------------------------------- 159 | 160 | AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs]) 161 | #AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs]) 162 | 163 | #-------------------------------------------------------------------- 164 | # This macro generates a line to use when building a library. It 165 | # depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS, 166 | # and TEA_LOAD_TCLCONFIG macros above. 167 | #-------------------------------------------------------------------- 168 | 169 | TEA_MAKE_LIB 170 | 171 | #-------------------------------------------------------------------- 172 | # Determine the name of the tclsh and/or wish executables in the 173 | # Tcl and Tk build directories or the location they were installed 174 | # into. These paths are used to support running test cases only, 175 | # the Makefile should not be making use of these paths to generate 176 | # a pkgIndex.tcl file or anything else at extension build time. 177 | #-------------------------------------------------------------------- 178 | 179 | TEA_PROG_TCLSH 180 | #TEA_PROG_WISH 181 | 182 | #-------------------------------------------------------------------- 183 | # Finally, substitute all of the various values into the Makefile. 184 | # You may alternatively have a special pkgIndex.tcl.in or other files 185 | # which require substituting th AC variables in. Include these here. 186 | #-------------------------------------------------------------------- 187 | 188 | AC_OUTPUT([Makefile pkgIndex.tcl]) 189 | -------------------------------------------------------------------------------- /generic/sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * sample.c -- 3 | * 4 | * This file implements a secure hashing algorithm 5 | * 6 | * Copyright (c) 1999 Scriptics Corporation. 7 | * 8 | * See the file "license.terms" for information on usage and redistribution 9 | * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 10 | * 11 | */ 12 | 13 | /* 14 | * SHA-1 in C 15 | * By Steve Reid 16 | * 100% Public Domain 17 | * 18 | * Test Vectors (from FIPS PUB 180-1) 19 | * "abc" 20 | * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D 21 | * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 22 | * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 23 | * A million repetitions of "a" 24 | * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F 25 | */ 26 | 27 | /* 28 | * If byte order known, #define LITTLE_ENDIAN or BIG_ENDIAN to be faster 29 | */ 30 | 31 | /* 32 | * Copy data before messing with it. 33 | * #define SHA1HANDSOFF 34 | */ 35 | 36 | #include 37 | #include 38 | #include 39 | #include "sample.h" 40 | 41 | #define Rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) 42 | 43 | /* 44 | * Blk0() and Blk() perform the initial expand. 45 | * I got the idea of expanding during the round function from SSLeay 46 | */ 47 | 48 | #ifdef LITTLE_ENDIAN 49 | #define Blk0(i) (block->l[i] = (Rol(block->l[i],24)&0xFF00FF00) \ 50 | |(Rol(block->l[i],8)&0x00FF00FF)) 51 | #else 52 | #ifdef BIG_ENDIAN 53 | #define Blk0(i) block->l[i] 54 | #else 55 | 56 | /* 57 | * for unknown byte order, to work with either 58 | * results in no change on big endian machines 59 | * added by Dave Dykstra, 4/16/97 60 | */ 61 | 62 | #define Blk0(i) (p = (unsigned char *) (&block->l[i]), \ 63 | block->l[i] = (*p << 24) \ 64 | + (*(p+1) << 16) + (*(p+2) << 8) + *(p+3)) 65 | #endif 66 | #endif 67 | #define Blk(i) (block->l[i&15] = Rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ 68 | ^block->l[(i+2)&15]^block->l[i&15],1)) 69 | 70 | /* 71 | * (R0+R1), R2, R3, R4 are the different operations used in SHA1 72 | */ 73 | 74 | #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+Blk0(i)+0x5A827999+Rol(v,5);w=Rol(w,30); 75 | #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+Blk(i)+0x5A827999+Rol(v,5);w=Rol(w,30); 76 | #define R2(v,w,x,y,z,i) z+=(w^x^y)+Blk(i)+0x6ED9EBA1+Rol(v,5);w=Rol(w,30); 77 | #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+Blk(i)+0x8F1BBCDC+Rol(v,5);w=Rol(w,30); 78 | #define R4(v,w,x,y,z,i) z+=(w^x^y)+Blk(i)+0xCA62C1D6+Rol(v,5);w=Rol(w,30); 79 | 80 | /* 81 | *---------------------------------------------------------------------- 82 | * 83 | * SHA1Transform 84 | * 85 | * Hash a single 512-bit block. This is the core of the algorithm. 86 | * 87 | * Results: 88 | * None. 89 | * 90 | * Side effects: 91 | * Contents of state pointer are changed. 92 | * 93 | *---------------------------------------------------------------------- 94 | */ 95 | 96 | void 97 | SHA1Transform(state, buffer) 98 | sha_uint32_t state[5]; /* State variable */ 99 | unsigned char buffer[64]; /* Modified buffer */ 100 | { 101 | #if (!defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN)) 102 | unsigned char *p; 103 | #endif 104 | sha_uint32_t a, b, c, d, e; 105 | typedef union { 106 | unsigned char c[64]; 107 | sha_uint32_t l[16]; 108 | } CHAR64LONG16; 109 | CHAR64LONG16* block; 110 | 111 | #ifdef SHA1HANDSOFF 112 | static unsigned char workspace[64]; 113 | block = (CHAR64LONG16*)workspace; 114 | memcpy(block, buffer, 64); 115 | #else 116 | block = (CHAR64LONG16*)buffer; 117 | #endif 118 | 119 | assert(sizeof(block->c) == sizeof(block->l)); 120 | 121 | /* 122 | * Copy context->state[] to working vars 123 | */ 124 | 125 | a = state[0]; 126 | b = state[1]; 127 | c = state[2]; 128 | d = state[3]; 129 | e = state[4]; 130 | 131 | /* 132 | * 4 rounds of 20 operations each. Loop unrolled. 133 | */ 134 | 135 | R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); 136 | R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); 137 | R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); 138 | R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); 139 | R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); 140 | R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); 141 | R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); 142 | R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); 143 | R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); 144 | R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); 145 | R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); 146 | R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); 147 | R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); 148 | R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); 149 | R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); 150 | R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); 151 | R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); 152 | R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); 153 | R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); 154 | R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); 155 | 156 | /* 157 | * Add the working vars back into context.state[] 158 | */ 159 | 160 | state[0] += a; 161 | state[1] += b; 162 | state[2] += c; 163 | state[3] += d; 164 | state[4] += e; 165 | 166 | /* 167 | * Wipe variables 168 | */ 169 | 170 | a = b = c = d = e = 0; 171 | 172 | return; 173 | } 174 | 175 | /* 176 | *---------------------------------------------------------------------- 177 | * 178 | * SHA1Init -- 179 | * 180 | * Initialize new context 181 | * 182 | * Results: 183 | * None. 184 | * 185 | * Side effects: 186 | * Contents of context pointer are changed. 187 | * 188 | *---------------------------------------------------------------------- 189 | */ 190 | 191 | void SHA1Init(context) 192 | SHA1_CTX* context; /* Context to initialize */ 193 | { 194 | /* 195 | * SHA1 initialization constants 196 | */ 197 | 198 | context->state[0] = 0x67452301; 199 | context->state[1] = 0xEFCDAB89; 200 | context->state[2] = 0x98BADCFE; 201 | context->state[3] = 0x10325476; 202 | context->state[4] = 0xC3D2E1F0; 203 | context->count[0] = context->count[1] = 0; 204 | 205 | return; 206 | } 207 | 208 | /* 209 | *---------------------------------------------------------------------- 210 | * 211 | * SHA1Update 212 | * 213 | * Updates a context. 214 | * 215 | * Results: 216 | * None. 217 | * 218 | * Side effects: 219 | * Contents of context pointer are changed. 220 | * 221 | *---------------------------------------------------------------------- 222 | */ 223 | 224 | void 225 | SHA1Update(context, data, len) 226 | SHA1_CTX* context; /* Context to update */ 227 | unsigned char* data; /* Data used for update */ 228 | unsigned int len; /* Length of data */ 229 | { 230 | unsigned int i, j; 231 | 232 | j = (context->count[0] >> 3) & 63; 233 | if ((context->count[0] += len << 3) < (len << 3)) { 234 | context->count[1]++; 235 | } 236 | context->count[1] += (len >> 29); 237 | if ((j + len) > 63) { 238 | memcpy(&context->buffer[j], data, (i = 64-j)); 239 | SHA1Transform(context->state, context->buffer); 240 | for ( ; i + 63 < len; i += 64) { 241 | #ifdef CANWRITEDATA 242 | SHA1Transform(context->state, &data[i]); 243 | #else 244 | 245 | /* 246 | * else case added by Dave Dykstra 4/22/97 247 | */ 248 | 249 | memcpy(&context->buffer[0], &data[i], 64); 250 | SHA1Transform(context->state, context->buffer); 251 | #endif 252 | } 253 | j = 0; 254 | } else { 255 | i = 0; 256 | } 257 | 258 | memcpy(&context->buffer[j], &data[i], len - i); 259 | 260 | return; 261 | } 262 | 263 | /* 264 | *---------------------------------------------------------------------- 265 | * 266 | * SHA1Final 267 | * 268 | * Add padding and return the message digest. 269 | * 270 | * Results: 271 | * None. 272 | * 273 | * Side effects: 274 | * Contents of context pointer are changed. 275 | * 276 | *---------------------------------------------------------------------- 277 | */ 278 | 279 | void SHA1Final(context, digest) 280 | SHA1_CTX* context; /* Context to pad */ 281 | unsigned char digest[20]; /* Returned message digest */ 282 | { 283 | sha_uint32_t i, j; 284 | unsigned char finalcount[8]; 285 | 286 | for (i = 0; i < 8; i++) { 287 | /* 288 | * This statement is independent of the endianness 289 | */ 290 | 291 | finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] 292 | >> ((3-(i & 3)) * 8) ) & 255); 293 | } 294 | SHA1Update(context, (unsigned char *)"\200", 1); 295 | while ((context->count[0] & 504) != 448) { 296 | SHA1Update(context, (unsigned char *)"\0", 1); 297 | } 298 | 299 | /* 300 | * Should cause a SHA1Transform() 301 | */ 302 | 303 | SHA1Update(context, finalcount, 8); 304 | for (i = 0; i < 20; i++) { 305 | digest[i] = (unsigned char) 306 | ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); 307 | } 308 | 309 | /* 310 | * Wipe variables 311 | */ 312 | 313 | i = j = 0; 314 | memset(context, 0, sizeof(SHA1_CTX)); 315 | memset(&finalcount, 0, 8); 316 | 317 | /* 318 | * Make SHA1Transform overwrite it's own static vars. 319 | */ 320 | 321 | #ifdef SHA1HANDSOFF 322 | SHA1Transform(context->state, context->buffer); 323 | #endif 324 | 325 | return; 326 | } 327 | -------------------------------------------------------------------------------- /tea/packages.txt: -------------------------------------------------------------------------------- 1 | [section {Chapter 4. TCL PACKAGES}] 2 | 3 | NOTE: needs an update!! 4 | [para] 5 | 6 | The [emph package] mechanism, by which an extension is made available 7 | to a Tcl application is both simple and daunting, simple if you can stick to 8 | the user side, daunting if you need to understand how it actually 9 | works. In this chapter we give an overview of what the average 10 | programmer needs to know about it and nothing more. (The man pages 11 | on the [emph package] command are quite extensive and they document some 12 | of the inner workings too.) 13 | 14 | 15 | [section {The user side}] 16 | 17 | For the programmer who merely uses a particular package, there are two 18 | things he/she needs to know: 19 | 20 | [list_begin bullet] 21 | 22 | [bullet] 23 | the [emph {package require}] command 24 | 25 | [bullet] 26 | the auto_path variable 27 | 28 | [list_end] 29 | 30 | The programmer who needs, say, the Tktable extension, uses the 31 | following command: 32 | [example { 33 | package require Tktable 34 | }] 35 | 36 | (mostly without a version number, sometimes with a version number) 37 | 38 | [para] 39 | This instructs Tcl to go look for files "pkgIndex.tcl" in the 40 | directories listed in the [emph auto_path] variable and any of their 41 | subdirectories. Usually an installed package will be found in the 42 | standard place for extensions (packages): the lib directory under the 43 | Tcl installation directory. If not, the programmer can extend the 44 | auto_path variable with the directory that does contain the required 45 | package. 46 | 47 | 48 | [section {The package side}] 49 | 50 | If you are creating a package, then you need to know a bit more: 51 | - the [emph {package provide}] command for Tcl-based extensions/packages 52 | - the Tcl_PkgProvide() function for C-based extensions/packages 53 | 54 | [para] 55 | Here are small examples of both: 56 | 57 | [para] 58 | From the msgcat extension: 59 | [example { 60 | # msgcat.tcl -- 61 | # 62 | # This file defines various procedures which implement a 63 | # message catalog facility for Tcl programs. It should be 64 | # loaded with the command "package require msgcat". 65 | # 66 | # Copyright (c) 1998-2000 by Ajuba Solutions. 67 | # Copyright (c) 1998 by Mark Harrison. 68 | # 69 | # See the file "license.terms" for information on usage and redistribution 70 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. 71 | # 72 | # RCS: @(#) $Id$ 73 | 74 | package require Tcl 8.2 75 | # When the version number changes, be sure to update the pkgIndex.tcl file, 76 | # and the installation directory in the Makefiles. 77 | package provide msgcat 1.3 78 | 79 | namespace eval msgcat { 80 | ... 81 | } 82 | }] 83 | 84 | The corresponding pkgIndex.tcl file looks like this: 85 | [example { 86 | if {![package vsatisfies [package provide Tcl] 8.2]} {return} 87 | package ifneeded msgcat 1.3 [list source [file join $dir msgcat.tcl]] 88 | }] 89 | 90 | Note the variable "$dir" in the second statement: this variable is set 91 | by the package mechanism when it is looking for the required package. 92 | 93 | [para] 94 | From the example extension (Sample): 95 | [example { 96 | /* 97 | *---------------------------------------------------------------------- 98 | * 99 | * Sample_Init -- 100 | * 101 | * Initialize the new package. The string "Sample" in the 102 | * function name must match the PACKAGE declaration at the top of 103 | * configure.in. 104 | * 105 | * Results: 106 | * A standard Tcl result 107 | * 108 | * Side effects: 109 | * The Sample package is created. 110 | * One new command "sha1" is added to the Tcl interpreter. 111 | * 112 | *---------------------------------------------------------------------- 113 | */ 114 | 115 | int 116 | Sample_Init(Tcl_Interp *interp) 117 | { 118 | if (Tcl_InitStubs(interp, "8.0", 0) == NULL) { 119 | return TCL_ERROR; 120 | } 121 | if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 0) == NULL) { 122 | if (TCL_VERSION[0] == '7') { 123 | if (Tcl_PkgRequire(interp, "Tcl", "8.0", 0) == NULL) { 124 | return TCL_ERROR; 125 | } 126 | } 127 | } 128 | if (Tcl_PkgProvide(interp, "sample", VERSION) != TCL_OK) { 129 | return TCL_ERROR; 130 | } 131 | Tcl_CreateCommand(interp, "sha1", Sha1, 132 | (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); 133 | 134 | ... 135 | } 136 | }] 137 | As this extension is built via the TEA facilities, a pkgIndex.tcl 138 | file is provided for automatically. Instead of simply sourcing a 139 | Tcl script, it will load the shared object or DLL that was built from 140 | the C sources, roughly like: 141 | [example { 142 | package ifneeded sample 1.0 [list load [file join $dir libsample.so]] 143 | }] 144 | or: 145 | [example { 146 | package ifneeded sample 1.0 [list load [file join $dir sample.dll]] 147 | }] 148 | The TEA will create the pkgIndex.tcl file automatically via the 149 | pkg_mkIndex command. 150 | 151 | 152 | [section {Details on version numbers}] 153 | 154 | The package command defines a number of administrative subcommands, like 155 | [emph {package vsatisfies}] that deal with version numbers and so on. 156 | In most cases, all you need to do as an extension writer is to use the 157 | well-known two-part version numbering. 158 | 159 | [para] 160 | It is, however, important to be consistent with the version numbers: 161 | 162 | [list_begin bullet] 163 | 164 | [bullet] 165 | Throughout the extension, the same version number must be used 166 | 167 | [bullet] 168 | New versions get a higher minor number and if there are major changes 169 | or incompatibilities with older versions, the major number should 170 | change. 171 | 172 | [bullet] 173 | This holds not only for the code itself, but also for the 174 | documentation and test cases. 175 | 176 | [list_end] 177 | 178 | For this reason, the TEA defines a C macro, VERSION, that holds the 179 | version string (you can see how it is used in the code for the sample 180 | extension). This string is built up of the major version and a 181 | combination of the minor version and the patchlevel. From the file 182 | "configure.in" (see Chapter 6) we have: 183 | [example { 184 | #-------------------------------------------------------------------- 185 | # __CHANGE__ 186 | # Set your package name and version numbers here. The NODOT_VERSION is 187 | # required for constructing the library name on systems that don't like 188 | # dots in library names (Windows). The VERSION variable is used on the 189 | # other systems. 190 | #-------------------------------------------------------------------- 191 | 192 | PACKAGE=sample 193 | 194 | MAJOR_VERSION=0 195 | MINOR_VERSION=5 196 | PATCHLEVEL= 197 | 198 | VERSION=${MAJOR_VERSION}.${MINOR_VERSION}${PATCHLEVEL} 199 | NODOT_VERSION=${MAJOR_VERSION}${MINOR_VERSION} 200 | }] 201 | 202 | So, the above would result in a macro VERSION with the value 0.5 203 | [para] 204 | The version number is also used to construct a distinguishing name for 205 | the library, like: libsample0.5.so or sample05.dll. 206 | This way there is much less chance of a conflict between versions. 207 | 208 | 209 | [section {Subtleties with package names}] 210 | 211 | There are a few things you must be aware of when choosing a name for 212 | the extension: 213 | [list_begin bullet] 214 | 215 | [bullet] 216 | package names should not end in a digit and should not contain 217 | special characters. Otherwise the script that generates the index file 218 | will be confused. 219 | 220 | [bullet] 221 | package names must be unique within an installation. Before you decide 222 | on some name, check that there is no other (popular) extension of that 223 | name (or something very similar). 224 | 225 | [list_end] 226 | 227 | 228 | [section {Subtleties at the C side}] 229 | 230 | Things are a bit more intertwined on the C side. As the command that 231 | will be used to load a binary extension is: 232 | [example { 233 | load filename 234 | }] 235 | Tcl will have to deduce from the filename alone what the name is of the 236 | initialisation routine. The precise rules are explained in the manual 237 | page for the load command, but here are a few examples: 238 | [example { 239 | Filename Package name Initial procedure 240 | foo.dll foo Foo_Init 241 | FOO.DLL fOO Foo_Init 242 | libFOO.so fOO Foo_Init 243 | libfoo1.2.so fOo Foo_Init 244 | }] 245 | So, in the index file you might see: 246 | [example { 247 | package ifneeded fOo 1.2 [list load [file join $dir libfoo1.2.so]] 248 | }] 249 | A second issue is that for the extension to useful in a [emph safe] 250 | interpreter, you need to define an initialisation routine with a name 251 | like "Foo_SafeInit" (and possibly define the commands in another, safer, 252 | way). 253 | 254 | [para] 255 | The third issue that we would like to bring under your attention is the 256 | fact that under Windows you must explicitly indicate that a function in 257 | a DLL is to made visible (exported) to the outside world. Without this 258 | instruction the initialisation routine can not be loaded and therefore 259 | loading the extension fails. 260 | 261 | [para] 262 | The sample extension contains this fragment of code (sample.h) to take 263 | care of this (in general, the initialisation routine is the only one 264 | that needs to be exported - all others should be defined as [emph static] to 265 | reduce the chance of naming conflicts): 266 | [example { 267 | /* 268 | * Windows needs to know which symbols to export. 269 | */ 270 | 271 | #ifdef BUILD_sample 272 | #undef TCL_STORAGE_CLASS 273 | #define TCL_STORAGE_CLASS DLLEXPORT 274 | #endif /* BUILD_sample */ 275 | 276 | ... 277 | 278 | /* 279 | * Only the _Init function is exported. 280 | */ 281 | 282 | EXTERN int Sample_Init _ANSI_ARGS_((Tcl_Interp * interp)); 283 | }] 284 | -------------------------------------------------------------------------------- /generic/tclsample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tclsample.c -- 3 | * 4 | * This file implements a Tcl interface to the secure hashing 5 | * algorithm functions in sha1.c 6 | * 7 | * Copyright (c) 1999 Scriptics Corporation. 8 | * Copyright (c) 2003 ActiveState Corporation. 9 | * 10 | * See the file "license.terms" for information on usage and redistribution 11 | * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 12 | * 13 | */ 14 | 15 | /* 16 | * Modified from tclmd5.c by Dave Dykstra, dwd@bell-labs.com, 4/22/97 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "sample.h" 24 | 25 | #define TCL_READ_CHUNK_SIZE 4096 26 | 27 | static unsigned char itoa64f[] = 28 | "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_,"; 29 | 30 | static int numcontexts = 0; 31 | static SHA1_CTX *sha1Contexts = NULL; 32 | static int *ctxtotalRead = NULL; 33 | 34 | static int Sha1_Cmd(ClientData clientData, Tcl_Interp *interp, 35 | int onjc, Tcl_Obj *const objv[]); 36 | 37 | #define DIGESTSIZE 20 38 | 39 | /* 40 | *---------------------------------------------------------------------- 41 | * 42 | * Sha1 -- 43 | * 44 | * Implements the new Tcl "sha1" command. 45 | * 46 | * Results: 47 | * A standard Tcl result 48 | * 49 | * Side effects: 50 | * None. 51 | * 52 | *---------------------------------------------------------------------- 53 | */ 54 | 55 | static int 56 | Sha1_Cmd( 57 | ClientData clientData, /* Not used. */ 58 | Tcl_Interp *interp, /* Current interpreter */ 59 | int objc, /* Number of arguments */ 60 | Tcl_Obj *const objv[] /* Argument strings */ 61 | ) 62 | { 63 | /* 64 | * The default base is hex 65 | */ 66 | 67 | int log2base = 4; 68 | int a; 69 | Tcl_Obj *stringObj = NULL; 70 | Tcl_Channel chan = (Tcl_Channel) NULL; 71 | Tcl_Channel copychan = (Tcl_Channel) NULL; 72 | int mode; 73 | int contextnum = 0; 74 | #define sha1Context (sha1Contexts[contextnum]) 75 | char *bufPtr; 76 | int maxbytes = 0; 77 | int doinit = 1; 78 | int dofinal = 1; 79 | Tcl_Obj *descriptorObj = NULL; 80 | int totalRead = 0; 81 | int i, j, n, mask, bits, offset; 82 | 83 | /* 84 | * For binary representation + null char 85 | */ 86 | 87 | char buf[129]; 88 | unsigned char digest[DIGESTSIZE]; 89 | 90 | static const char *options[] = { 91 | "-chan", "-copychan", "-final", "-init", "-log2base", "-maxbytes", 92 | "-string", "-update", NULL 93 | }; 94 | enum ShaOpts { 95 | SHAOPT_CHAN, SHAOPT_COPY, SHAOPT_FINAL, SHAOPT_INIT, SHAOPT_LOG, 96 | SHAOPT_MAXB, SHAOPT_STRING, SHAOPT_UPDATE 97 | }; 98 | 99 | for (a = 1; a < objc; a++) { 100 | int index; 101 | 102 | if (Tcl_GetIndexFromObj(interp, objv[a], options, "option", 0, 103 | &index) != TCL_OK) { 104 | return TCL_ERROR; 105 | } 106 | /* 107 | * Everything except -init takes an argument... 108 | */ 109 | if ((index != SHAOPT_INIT) && (++a >= objc)) { 110 | goto wrongArgs; 111 | } 112 | switch ((enum ShaOpts) index) { 113 | case SHAOPT_INIT: 114 | for (contextnum = 1; contextnum < numcontexts; contextnum++) { 115 | if (ctxtotalRead[contextnum] < 0) { 116 | break; 117 | } 118 | } 119 | if (contextnum == numcontexts) { 120 | /* 121 | * Allocate a new context. 122 | */ 123 | 124 | numcontexts++; 125 | sha1Contexts = (SHA1_CTX *) realloc((void *) sha1Contexts, 126 | numcontexts * sizeof(SHA1_CTX)); 127 | ctxtotalRead = realloc((void *) ctxtotalRead, 128 | numcontexts * sizeof(int)); 129 | } 130 | ctxtotalRead[contextnum] = 0; 131 | SHA1Init(&sha1Context); 132 | sprintf(buf, "sha1%d", contextnum); 133 | Tcl_AppendResult(interp, buf, (char *)NULL); 134 | return TCL_OK; 135 | case SHAOPT_CHAN: 136 | chan = Tcl_GetChannel(interp, Tcl_GetString(objv[a]), &mode); 137 | if (chan == (Tcl_Channel) NULL) { 138 | return TCL_ERROR; 139 | } 140 | if ((mode & TCL_READABLE) == 0) { 141 | Tcl_AppendResult(interp, "chan \"", Tcl_GetString(objv[a]), 142 | "\" wasn't opened for reading", (char *) NULL); 143 | return TCL_ERROR; 144 | } 145 | continue; 146 | case SHAOPT_COPY: 147 | copychan = Tcl_GetChannel(interp, Tcl_GetString(objv[a]), &mode); 148 | if (copychan == (Tcl_Channel) NULL) { 149 | return TCL_ERROR; 150 | } 151 | if ((mode & TCL_WRITABLE) == 0) { 152 | Tcl_AppendResult(interp, "copychan \"", Tcl_GetString(objv[a]), 153 | "\" wasn't opened for writing", (char *) NULL); 154 | return TCL_ERROR; 155 | } 156 | continue; 157 | case SHAOPT_FINAL: 158 | descriptorObj = objv[a]; 159 | doinit = 0; 160 | continue; 161 | case SHAOPT_LOG: 162 | if (Tcl_GetIntFromObj(interp, objv[a], &log2base) != TCL_OK) { 163 | return TCL_ERROR; 164 | } else if ((log2base < 1) || (log2base > 6)) { 165 | Tcl_AppendResult(interp, "parameter to -log2base \"", 166 | Tcl_GetString(objv[a]), 167 | "\" must be integer in range 1...6", (char *) NULL); 168 | return TCL_ERROR; 169 | } 170 | continue; 171 | case SHAOPT_MAXB: 172 | if (Tcl_GetIntFromObj(interp, objv[a], &maxbytes) != TCL_OK) { 173 | return TCL_ERROR; 174 | } 175 | continue; 176 | case SHAOPT_STRING: 177 | stringObj = objv[a]; 178 | continue; 179 | case SHAOPT_UPDATE: 180 | descriptorObj = objv[a]; 181 | doinit = 0; 182 | dofinal = 0; 183 | continue; 184 | } 185 | } 186 | 187 | if (descriptorObj != NULL) { 188 | if ((sscanf(Tcl_GetString(descriptorObj), "sha1%d", 189 | &contextnum) != 1) || (contextnum >= numcontexts) || 190 | (ctxtotalRead[contextnum] < 0)) { 191 | Tcl_AppendResult(interp, "invalid sha1 descriptor \"", 192 | Tcl_GetString(descriptorObj), "\"", (char *) NULL); 193 | return TCL_ERROR; 194 | } 195 | } 196 | 197 | if (doinit) { 198 | SHA1Init(&sha1Context); 199 | } 200 | 201 | if (stringObj != NULL) { 202 | char *string; 203 | if (chan != (Tcl_Channel) NULL) { 204 | goto wrongArgs; 205 | } 206 | string = Tcl_GetStringFromObj(stringObj, &totalRead); 207 | SHA1Update(&sha1Context, (unsigned char *) string, totalRead); 208 | } else if (chan != (Tcl_Channel) NULL) { 209 | bufPtr = ckalloc((unsigned) TCL_READ_CHUNK_SIZE); 210 | totalRead = 0; 211 | while ((n = Tcl_Read(chan, bufPtr, 212 | maxbytes == 0 213 | ? TCL_READ_CHUNK_SIZE 214 | : (TCL_READ_CHUNK_SIZE < maxbytes 215 | ? TCL_READ_CHUNK_SIZE 216 | : maxbytes))) != 0) { 217 | if (n < 0) { 218 | ckfree(bufPtr); 219 | Tcl_AppendResult(interp, Tcl_GetString(objv[0]), ": ", 220 | Tcl_GetChannelName(chan), Tcl_PosixError(interp), 221 | (char *) NULL); 222 | return TCL_ERROR; 223 | } 224 | 225 | totalRead += n; 226 | 227 | SHA1Update(&sha1Context, (unsigned char *) bufPtr, (unsigned int) n); 228 | 229 | if (copychan != (Tcl_Channel) NULL) { 230 | n = Tcl_Write(copychan, bufPtr, n); 231 | if (n < 0) { 232 | ckfree(bufPtr); 233 | Tcl_AppendResult(interp, Tcl_GetString(objv[0]), ": ", 234 | Tcl_GetChannelName(copychan), 235 | Tcl_PosixError(interp), (char *) NULL); 236 | return TCL_ERROR; 237 | } 238 | } 239 | 240 | if ((maxbytes > 0) && ((maxbytes -= n) <= 0)) { 241 | break; 242 | } 243 | } 244 | ckfree(bufPtr); 245 | } else if (descriptorObj == NULL) { 246 | goto wrongArgs; 247 | } 248 | 249 | if (!dofinal) { 250 | ctxtotalRead[contextnum] += totalRead; 251 | Tcl_SetObjResult(interp, Tcl_NewIntObj(totalRead)); 252 | return TCL_OK; 253 | } 254 | 255 | if (stringObj == NULL) { 256 | totalRead += ctxtotalRead[contextnum]; 257 | Tcl_SetObjResult(interp, Tcl_NewIntObj(totalRead)); 258 | } 259 | 260 | SHA1Final(&sha1Context, digest); 261 | 262 | /* 263 | * Take the 20 byte array and print it in the requested base 264 | * e.g. log2base=1 => binary, log2base=4 => hex 265 | */ 266 | 267 | n = log2base; 268 | i = j = bits = 0; 269 | 270 | /* 271 | * if 160 bits doesn't divide exactly by n then the first character of 272 | * the output represents the residual bits. e.g for n=6 (base 64) the 273 | * first character can only take the values 0..f 274 | */ 275 | 276 | offset = (DIGESTSIZE * 8) % n; 277 | if (offset > 0) { 278 | offset = n - offset; 279 | } 280 | mask = (2 << (n-1)) - 1; 281 | while (1) { 282 | bits <<= n; 283 | if (offset <= n) { 284 | if (i == DIGESTSIZE) { 285 | break; 286 | } 287 | bits += (digest[i++] << (n - offset)); 288 | offset += 8; 289 | } 290 | offset -= n; 291 | buf[j++] = itoa64f[(bits>>8)&mask]; 292 | } 293 | buf[j++] = itoa64f[(bits>>8)&mask]; 294 | buf[j++] = '\0'; 295 | Tcl_AppendResult (interp, buf, (char *)NULL); 296 | if (contextnum > 0) { 297 | ctxtotalRead[contextnum] = -1; 298 | } 299 | return TCL_OK; 300 | 301 | wrongArgs: 302 | Tcl_AppendResult (interp, "wrong # args: should be either:\n", 303 | " ", 304 | Tcl_GetString(objv[0]), 305 | " ?-log2base log2base? -string string\n", 306 | " or\n", 307 | " ", 308 | Tcl_GetString(objv[0]), 309 | " ?-log2base log2base? ?-copychan chanID? -chan chanID\n", 310 | " or\n", 311 | " ", 312 | Tcl_GetString(objv[0]), 313 | " -init (returns descriptor)\n", 314 | " ", 315 | Tcl_GetString(objv[0]), 316 | " -update descriptor ?-maxbytes n? ?-copychan chanID? -chan chanID\n", 317 | " (any number of -update calls, returns number of bytes read)\n", 318 | " ", 319 | Tcl_GetString(objv[0]), 320 | " ?-log2base log2base? -final descriptor\n", 321 | " The default log2base is 4 (hex)", 322 | (char *) NULL); 323 | return TCL_ERROR; 324 | } 325 | 326 | /* 327 | *---------------------------------------------------------------------- 328 | * 329 | * Sample_Init -- 330 | * 331 | * Initialize the new package. The string "Sample" in the 332 | * function name must match the PACKAGE declaration at the top of 333 | * configure.in. 334 | * 335 | * Results: 336 | * A standard Tcl result 337 | * 338 | * Side effects: 339 | * The Sample package is created. 340 | * One new command "sha1" is added to the Tcl interpreter. 341 | * 342 | *---------------------------------------------------------------------- 343 | */ 344 | 345 | int 346 | Sample_Init(Tcl_Interp *interp) 347 | { 348 | /* 349 | * This may work with 8.0, but we are using strictly stubs here, 350 | * which requires 8.1. 351 | */ 352 | if (Tcl_InitStubs(interp, "8.1", 0) == NULL) { 353 | return TCL_ERROR; 354 | } 355 | if (Tcl_PkgRequire(interp, "Tcl", "8.1", 0) == NULL) { 356 | return TCL_ERROR; 357 | } 358 | if (Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_VERSION) != TCL_OK) { 359 | return TCL_ERROR; 360 | } 361 | Tcl_CreateObjCommand(interp, "sha1", (Tcl_ObjCmdProc *) Sha1_Cmd, 362 | (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); 363 | 364 | numcontexts = 1; 365 | sha1Contexts = (SHA1_CTX *) malloc(sizeof(SHA1_CTX)); 366 | ctxtotalRead = (int *) malloc(sizeof(int)); 367 | ctxtotalRead[0] = 0; 368 | 369 | return TCL_OK; 370 | } 371 | -------------------------------------------------------------------------------- /tea/makefiles.txt: -------------------------------------------------------------------------------- 1 | [section {Chapter 6. CONFIGURE AND MAKE FILES}] 2 | 3 | A large part of TEA is devoted to making the actual build process as 4 | smoothly as possible, that is, people who install your extension 5 | should not need to know anything of the build process, except for a few 6 | simple commands, found and explained in the INSTALL file. 7 | 8 | [para] 9 | For you as an extension writer, things are a bit more involved, but 10 | again TEA has the task to make the preparation of the build process for 11 | your specific extension as smooth and painless as possible. 12 | Nevertheless, you will have to do something: 13 | 14 | [list_begin bullet] 15 | 16 | [bullet] 17 | Prepare at least two template files, configure.in and Makefile.in, 18 | that contain information about what sources your extension is made of, 19 | under what name your extension will be known and so on. 20 | 21 | [bullet] 22 | Create a [emph {shell script}] (*), called [emph configure], via the Autoconf 23 | program. 24 | 25 | [bullet] 26 | Bundle your extension into a single file that can be delivered to 27 | others. 28 | 29 | [list_end] 30 | 31 | This chapter will guide you through this process. First it will gloss 32 | over the Autoconf program and its purpose. Then it will describe in 33 | detail what the average extension writer has to do. 34 | 35 | [para] 36 | [emph Note:] 37 | [para] 38 | If you are not familiar with [emph {make files}], read the expose in 39 | appendix A first. It will help appreciate the steps you will have to 40 | take. 41 | 42 | [para] 43 | [emph Note:] 44 | [para] 45 | TEA version 3 assumes that you have Autoconf version 2.50 or later. 46 | Autoconf is only necessary when you build the configure script, it is 47 | not required by the users of your extension (see the section 48 | "Required software") 49 | 50 | [para] 51 | (*) For Windows programmers: a shell script can be regarded as a 52 | sophisticated DOS batch file. It has the same purpose, but because UNIX 53 | shell languages (there are several) are more powerful than DOS batch 54 | commands, you can do a lot more with them. 55 | 56 | 57 | [section {The purpose of Autoconf}] 58 | 59 | The GNU program Autoconf, which is one of a suite of programs, is meant 60 | to create a configuration script, which then takes care of everything. 61 | To do this, it reads a file called configure.ac (or configure.in in 62 | older versions) and processes the macros it finds in there. These 63 | macros have been developed to take care of all the nasty little details 64 | that can bother a programmer. (If you familiarise yourself with the 65 | Autoconf tool, you will be able to create new macros. This is actually 66 | one of the great advantages of Autoconf.) 67 | 68 | [para] 69 | While Autoconf takes a template file "configure.ac" or "configure.in", 70 | TEA provides you with a template for this template. All you need to do is: 71 | 72 | [list_begin bullet] 73 | 74 | [bullet] 75 | replace the name of the sample extension (exampleA) by the name 76 | of your extension 77 | 78 | [bullet] 79 | replace the names of the source files in the sample extension by 80 | those of your source files 81 | 82 | [bullet] 83 | adjust version numbers and some other details 84 | 85 | [bullet] 86 | run the Autoconf program 87 | 88 | [list_end] 89 | 90 | The resulting script, called [emph configure], will check for a lot of 91 | things: 92 | 93 | [list_begin bullet] 94 | 95 | [bullet] 96 | where the Tcl libraries and header files are (it may need some help, 97 | though, to find the right directory) 98 | 99 | [bullet] 100 | what compiler and linker options to use 101 | 102 | [bullet] 103 | what file extensions are used on that particular platform 104 | 105 | [bullet] 106 | what external libraries are required 107 | 108 | [bullet] 109 | etc. 110 | 111 | [list_end] 112 | 113 | All of these things are substituted into the template for the make file 114 | (Makefile.in) so that the user can run the make utility to create the 115 | library or program. For instance, in the template you may see: 116 | [example { 117 | CFLAGS_DEBUG = @CFLAGS_DEBUG@ 118 | }] 119 | The first is a variable in the make file that is used to set the flags 120 | for a debug version of your extension. The configure script 121 | replaces the string "@CFLAGS_DEBUG@" by whatever is appropriate for that 122 | platform, often "-g -c". This is accomplished by a command 123 | AC_SUBST([lb]CFLAGS_DEBUG[rb]) somewhere in the configure.in file (or 124 | the macros it uses). 125 | 126 | 127 | [section {The macros used by TEA}] 128 | 129 | The template files that come with TEA are very well documented, 130 | but still some explanation is required, if you are not familiar with 131 | Autoconf (see the example below). 132 | 133 | [para] 134 | [emph Note:] 135 | [para] 136 | The order of the macros is important, as the wrong order can make the 137 | resulting configure script useless (in Autoconf all variables are 138 | global and sometimes the value of a variable causes erroneous 139 | macro processing). 140 | 141 | [example { 142 | Example 143 | }] 144 | 145 | [list_begin bullet] 146 | 147 | [bullet] 148 | The very first macro is AC_INIT(), this has two arguments, the name of 149 | the extension and its version number: 150 | 151 | [list_begin bullet] 152 | [bullet] 153 | the major and minor version numbers of this release 154 | [bullet] 155 | the patchlevel (if any) 156 | [list_end] 157 | 158 | These numbers will be used to identify the resulting files uniquely. 159 | Because of pecularities between platforms, two "version" variables are 160 | created, one with dots and one without. 161 | 162 | [bullet] 163 | The next steps are to initialise the TEA macro library, via 164 | TEA_INIT and to set the directory with auxiliary scripts, tclconfig, 165 | via the macro AC_AUX_CONFIG_DIR. 166 | 167 | [bullet] 168 | Depending on whether your extension uses only Tcl or Tk as well, you 169 | will have to use: 170 | 171 | [list_begin bullet] 172 | [bullet] 173 | TEA_PATH_TCLCONFIG and TEA_LOAD_TCLCONFIG 174 | [bullet] 175 | TEA_PATH_TKCONFIG and TEA_LOAD_TKCONFIG 176 | [list_end] 177 | [nl] 178 | These macros locate the tclConfig.sh and tkConfig.sh files that hold 179 | information about how Tcl/Tk itself was built on this platform (or how 180 | the binary distribution was built). 181 | 182 | [bullet] 183 | TEA_PREFIX is used to set the directory that all files will be 184 | installed under, later, after building the extensions. 185 | 186 | [bullet] 187 | TEA_SETUP_COMPILER identifies the C compiler to be used and the flags 188 | or options needed in general. 189 | 190 | [bullet] 191 | After the call to this macro, we get a small section with information 192 | that is specific to your extension: 193 | 194 | [list_begin bullet] 195 | [bullet] 196 | TEA_ADD_SOURCES should be used to register the source files of your 197 | extension - the listed files will be compiled. 198 | 199 | [bullet] 200 | TEA_ADD_HEADERS is used to register the public header files (so 201 | these header files will be available for other extensions after 202 | installation). 203 | 204 | [bullet] 205 | TEA_ADD_INCLUDES lists possible additional directories to look for 206 | include files. 207 | 208 | [bullet] 209 | TEA_ADD_TCL_SOURCES registers the Tcl scripts that form part of your 210 | extension. 211 | [list_end] 212 | 213 | [nl] 214 | Two macros that are much more specific are: 215 | 216 | [list_begin bullet] 217 | [bullet] 218 | TEA_ADD_CFLAGS gives you the opportunity to add specfic compiler 219 | flags (but note that these can depend on the platform!) 220 | [bullet] 221 | TEA_ADD_STUB_SOURCES lists all the source files that together will 222 | make up the stubs library (if your extension makes one of its own). 223 | [list_end] 224 | [nl] 225 | [bullet] 226 | After this part we need to choose which header files we need: 227 | 228 | [list_begin bullet] 229 | [bullet] 230 | TEA_PUBLIC_TCL_HEADERS and TEA_PUBLIC_TK_HEADERS control the use of 231 | the [emph public] header files. 232 | [bullet] 233 | TEA_PRIVATE_TCL_HEADERS and TEA_PRIVATE_TK_HEADERS control the use 234 | of the [emph private] header files. 235 | [list_end] 236 | 237 | [nl] 238 | Caution: using the private header files is "dangerous" - they may 239 | change without regard for compatibility. In principle extensions 240 | should never rely on these, but in rare cases it might be unavoidable. 241 | 242 | [bullet] 243 | If your extension uses Tk, then the TEA_PATH_X macro is responsible 244 | for finding the system's graphical libraries (on UNIX-like systems) 245 | 246 | [bullet] 247 | Now comes the one place where some platform-dependent code is 248 | required: 249 | 250 | [list_begin bullet] 251 | [bullet] 252 | On Windows, an extension using Tk will need extra libraries and any 253 | extension will need to remove some intermediate files produced by 254 | the MS Visual C/C++ compiler. 255 | [nl] 256 | Also, the macro BUILD_package needs to be set for Windows (see the 257 | Chapter on Design) 258 | [bullet] 259 | There may be some intermediate files that are specific to the 260 | extension that need to be cleaned up. 261 | [list_end] 262 | 263 | [nl] 264 | This is best set via code like in the sample extension. 265 | 266 | [bullet] 267 | The remainder of the configuration file is straightforward: 268 | Several extra checks and finally the macro that tells the configure 269 | script what files to produce: AC_OUTPUT(). 270 | 271 | [bullet] 272 | The rest of the file contains a number of macro calls, each of which 273 | is clearly documented. Use them or comment them as is necessary for 274 | your extension. 275 | 276 | [bullet] 277 | The last line, AC_OUTPUT(), lists all the files that need to be 278 | created by the configure script. 279 | 280 | [list_end] 281 | 282 | You can use a number of other macros in your configure.in file: 283 | 284 | [list_begin bullet] 285 | 286 | [bullet] 287 | AC_DEFINE(variable,value,?description?): 288 | [nl] 289 | Add a C compiler macro "variable" with the given value to the list of 290 | compiler options, something like: 291 | [example { 292 | cc -Dvariable=value 293 | }] 294 | 295 | [bullet] 296 | AC_SUBST(variable,?value?): 297 | [nl] 298 | Substitute the given shell variable into the output files (when 299 | AC_OUTPUT is invoked) 300 | 301 | [bullet] 302 | AC_ARG_WITH(suffix,description,action): 303 | [nl] 304 | Check the command-line arguments of the configure script, such as: 305 | [example { 306 | --with-tcl= 307 | }] 308 | If the argument is present, the action will be carried out. 309 | 310 | [bullet] 311 | AC_ARG_ENABLE(suffix,description,action_on,action_off): 312 | [nl] 313 | Check the command-line arguments of the configure script, such as: 314 | [example { 315 | --enable-threads 316 | }] 317 | If the argument is present as "enabled", the action "on" will be 318 | carried out, otherwise the action "off" will be carried out. 319 | 320 | [bullet] 321 | AC_CHECK_HEADER(headerfile,action_if_found,action_not_found,): 322 | [nl] 323 | Check for the presence of a particular header file and if found, run 324 | the first action, otherwise the second action. 325 | 326 | [bullet] 327 | AC_CHECK_LIB(libfile,function,action_if_found,action_not_found,other_libs): 328 | [nl] 329 | Similar for libraries that should contain a particular function. 330 | 331 | [bullet] 332 | TEA_ADD_LIBS(list-of-names): 333 | [nl] 334 | Add one or more libraries to the link command. Note: the 335 | platform-dependent names are expected. See the TEA_LIB_SPEC macro. 336 | 337 | [bullet] 338 | TEA_LIB_SPEC(basename,extra_dir): 339 | [nl] 340 | Find the exact name of the library given via its basename (e.g. 341 | libinet.a would have the base name "inet" and user32.lib would 342 | have the base name "user32"). The extra directory is used first, 343 | then a bunch of standard directories. The resulting variable 344 | basename_LIB_SPEC can be used with the TEA_ADD_LIBS macro. 345 | 346 | [bullet] 347 | TEA_PATH_CONFIG(pkg) 348 | [nl] 349 | Look for a particular pkgConfig.sh file, which is part of some 350 | extension "pkg". 351 | 352 | [bullet] 353 | TEA_LOAD_CONFIG 354 | [nl] 355 | Load that particular pkgConfig.sh file. 356 | 357 | [list_end] 358 | 359 | 360 | [section {The Makefile.in template}] 361 | 362 | If you study the (well-documented) make file template that comes with 363 | the sample extension, Makefile.in, you will notice that there is very 364 | little that you need to adapt. In fact, there are only two sections that 365 | require your attention: 366 | 367 | [list_begin bullet] 368 | 369 | [bullet] 370 | The section at the top for new variables that you may have defined via 371 | the [emph AC_SUBST] macro. This section - if needed - should contain one 372 | line for each new variable like: 373 | 374 | [example { 375 | SAMPLE_NEW_VAR = @SAMPLE_NEW_VAR@ 376 | }] 377 | This defines a new variable "SAMPLE_NEW_VAR" in the make file which 378 | receives the value of the variable by the same name in the configure 379 | script. 380 | 381 | [nl] 382 | [emph Note:] 383 | For the sake of simplicity, always use the same names! There is no need 384 | to get creative at this point - it will only make things more difficult. 385 | 386 | [bullet] 387 | The section containing the user-definable targets. This section may look 388 | intimidating to someone not familiar with UNIX shells or make files, 389 | but in fact, most of the code found there is completely generic. 390 | [nl] 391 | The exceptions are the targets dealing with the documentation (doc and 392 | install-doc) and with the distribution of the code as a single archive 393 | (tar-file, zip-file or whatever). 394 | [nl] 395 | The reason these targets may need to be adjusted to your needs are: 396 | 397 | [list_begin bullet] 398 | 399 | [bullet] 400 | You use a different system of documentation 401 | 402 | [bullet] 403 | You require more files from different locations to be included 404 | (residing in other directories for instance). 405 | [list_end] 406 | 407 | As it is very difficult to make these tasks generic, this remains an 408 | issue for you as an extension programmer. 409 | 410 | [list_end] 411 | 412 | [section {Making the distribution}] 413 | 414 | Once you have created the configure script, you as the author of the 415 | extension can use to create a bundled file with all the source and 416 | other files for distribution: 417 | 418 | [list_begin bullet] 419 | 420 | [bullet] 421 | Run the configure script 422 | [bullet] 423 | Run the resulting make file: 424 | [example { 425 | make dist 426 | }] 427 | [list_end] 428 | 429 | If you want other files to be generated as part of the distribution, 430 | for instance, the INSTALL file must be adjusted to include the name 431 | and purpose of your extension, then you can do so by defining a 432 | variable specific for that file and define it in the configure script: 433 | 434 | [list_begin bullet] 435 | 436 | [bullet] 437 | Define a file INSTALL.in which has a line "@MY_EXTENSION_TEXT@" 438 | in it. 439 | 440 | [bullet] 441 | Define a variable MY_EXTENSION_TEXT in the configure.in file: 442 | [example { 443 | AC_DEFINE([MY_EXTENSION_TEXT]) 444 | MY_EXTENSION_TEXT="Whatever text you want inserted" 445 | AC_SUBST([MY_EXTENSION_TEXT]) 446 | }] 447 | 448 | [bullet] 449 | Add the name of the file, [emph {without the ".in" extension}], to the 450 | AC_OUTPUT macro: 451 | [example { 452 | AC_OUTPUT([Makefile INSTALL]) 453 | }] 454 | 455 | [list_end] 456 | 457 | 458 | [section {Required software}] 459 | 460 | To create a working configure script via Autoconf, you will need to have 461 | Autoconf 2.50 or better. Autoconf is only needed if you are developing 462 | an extension. The users of your extension only need the configure script 463 | and the make file template. 464 | [para] 465 | Once the configure script is created, you can run it without any 466 | additional software on a UNIX/Linux/*BSD/MacOSX system, as these systems 467 | almost always have the UNIX shells and the make utility. 468 | [para] 469 | For Windows systems, you will need to have such tools as Cygwin or 470 | MingW/MSYS - both ports of the UNIX tools to Windows. 471 | [para] 472 | See the [sectref References] section for the websites where you can get 473 | this software. 474 | 475 | 476 | [section {Making the extension}] 477 | The steps taken by any user who uses the distributed source files are: 478 | 479 | [list_begin bullet] 480 | 481 | [bullet] 482 | run the configure script to tell it where to find, for instance, 483 | the Tcl/Tk header files or what C compiler to use 484 | 485 | [bullet] 486 | this script uses the file Makefile.in as a template to create 487 | the file Makefile. 488 | 489 | [bullet] 490 | when the [emph configure] script is finished, the programmer can run [emph make] 491 | to create the libraries, the programs and the documentation, ready 492 | for installation. 493 | 494 | [bullet] 495 | so, when [emph make] is done and all has been successful, the next steps 496 | can be run: run the tests and install the program(s). 497 | 498 | [list_end] 499 | 500 | The various steps are handled via special keywords in the makefile, 501 | targets that are not connected to a specific file - they are always 502 | considered out of date. 503 | 504 | [para] 505 | So, the above procedure is carried out by running the following 506 | commands on UNIX/Linux (> is the command prompt): 507 | [example { 508 | > ./configure 509 | > make 510 | > make test 511 | > make install 512 | }] 513 | (assuming all steps are successful). 514 | 515 | [para] 516 | If you want to restart (some compilation error had to solved), 517 | you would run: 518 | [example { 519 | > make clean 520 | }] 521 | to throw away most intermediate files, or: 522 | [example { 523 | > make distclean 524 | }] 525 | to start from a really clean slate. 526 | 527 | [para] 528 | TODO: how to use mingw/msys to accomplish this on Windows 529 | [para] 530 | TODO: what about Windows project files? 531 | 532 | -------------------------------------------------------------------------------- /win/makefile.vc: -------------------------------------------------------------------------------- 1 | # makefile.vc -- -*- Makefile -*- 2 | # 3 | # Microsoft Visual C++ makefile for use with nmake.exe v1.62+ (VC++ 5.0+) 4 | # 5 | # This makefile is based upon the Tcl 8.4 Makefile.vc and modified to 6 | # make it suitable as a general package makefile. Look for the word EDIT 7 | # which marks sections that may need modification. As a minumum you will 8 | # need to change the PROJECT, DOTVERSION and DLLOBJS variables to values 9 | # relevant to your package. 10 | # 11 | # See the file "license.terms" for information on usage and redistribution 12 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. 13 | # 14 | # Copyright (c) 1995-1996 Sun Microsystems, Inc. 15 | # Copyright (c) 1998-2000 Ajuba Solutions. 16 | # Copyright (c) 2001 ActiveState Corporation. 17 | # Copyright (c) 2001-2002 David Gravereaux. 18 | # Copyright (c) 2003-2006 Pat Thoyts 19 | # 20 | #------------------------------------------------------------------------- 21 | # RCS: @(#)$Id$ 22 | #------------------------------------------------------------------------- 23 | 24 | # Check to see we are configured to build with MSVC (MSDEVDIR or MSVCDIR) 25 | # or with the MS Platform SDK (MSSDK). Visual Studio .NET 2003 and 2005 define 26 | # VCINSTALLDIR instead. The MSVC Toolkit release defines yet another. 27 | !if !defined(MSDEVDIR) && !defined(MSVCDIR) && !defined(MSSDK) && !defined(VCINSTALLDIR) && !defined(VCToolkitInstallDir) 28 | MSG = ^ 29 | You need to run vcvars32.bat from Developer Studio or setenv.bat from the^ 30 | Platform SDK first to setup the environment. Jump to this line to read^ 31 | the build instructions. 32 | !error $(MSG) 33 | !endif 34 | 35 | #------------------------------------------------------------------------------ 36 | # HOW TO USE this makefile: 37 | # 38 | # 1) It is now necessary to have %MSVCDir% set in the environment. This is 39 | # used as a check to see if vcvars32.bat had been run prior to running 40 | # nmake or during the installation of Microsoft Visual C++, MSVCDir had 41 | # been set globally and the PATH adjusted. Either way is valid. 42 | # 43 | # You'll need to run vcvars32.bat contained in the MsDev's vc(98)/bin 44 | # directory to setup the proper environment, if needed, for your current 45 | # setup. This is a needed bootstrap requirement and allows the swapping of 46 | # different environments to be easier. 47 | # 48 | # 2) To use the Platform SDK (not expressly needed), run setenv.bat after 49 | # vcvars32.bat according to the instructions for it. This can also turn on 50 | # the 64-bit compiler, if your SDK has it. 51 | # 52 | # 3) Targets are: 53 | # all -- Builds everything. 54 | # -- Builds the project (eg: nmake sample) 55 | # test -- Builds and runs the test suite. 56 | # install -- Installs the built binaries and libraries to $(INSTALLDIR) 57 | # in an appropriate subdirectory. 58 | # clean/realclean/distclean -- varying levels of cleaning. 59 | # 60 | # 4) Macros usable on the commandline: 61 | # INSTALLDIR= 62 | # Sets where to install Tcl from the built binaries. 63 | # C:\Progra~1\Tcl is assumed when not specified. 64 | # 65 | # OPTS=static,msvcrt,staticpkg,threads,symbols,profile,loimpact,none 66 | # Sets special options for the core. The default is for none. 67 | # Any combination of the above may be used (comma separated). 68 | # 'none' will over-ride everything to nothing. 69 | # 70 | # static = Builds a static library of the core instead of a 71 | # dll. The shell will be static (and large), as well. 72 | # msvcrt = Effects the static option only to switch it from 73 | # using libcmt(d) as the C runtime [by default] to 74 | # msvcrt(d). This is useful for static embedding 75 | # support. 76 | # staticpkg = Effects the static option only to switch 77 | # tclshXX.exe to have the dde and reg extension linked 78 | # inside it. 79 | # nothreads = Turns off multithreading support (not recommended) 80 | # thrdalloc = Use the thread allocator (shared global free pool). 81 | # symbols = Adds symbols for step debugging. 82 | # profile = Adds profiling hooks. Map file is assumed. 83 | # loimpact = Adds a flag for how NT treats the heap to keep memory 84 | # in use, low. This is said to impact alloc performance. 85 | # 86 | # STATS=memdbg,compdbg,none 87 | # Sets optional memory and bytecode compiler debugging code added 88 | # to the core. The default is for none. Any combination of the 89 | # above may be used (comma separated). 'none' will over-ride 90 | # everything to nothing. 91 | # 92 | # memdbg = Enables the debugging memory allocator. 93 | # compdbg = Enables byte compilation logging. 94 | # 95 | # MACHINE=(IX86|IA64|ALPHA|AMD64) 96 | # Set the machine type used for the compiler, linker, and 97 | # resource compiler. This hook is needed to tell the tools 98 | # when alternate platforms are requested. IX86 is the default 99 | # when not specified. If the CPU environment variable has been 100 | # set (ie: recent Platform SDK) then MACHINE is set from CPU. 101 | # 102 | # TMP_DIR= 103 | # OUT_DIR= 104 | # Hooks to allow the intermediate and output directories to be 105 | # changed. $(OUT_DIR) is assumed to be 106 | # $(BINROOT)\(Release|Debug) based on if symbols are requested. 107 | # $(TMP_DIR) will de $(OUT_DIR)\ by default. 108 | # 109 | # TESTPAT= 110 | # Reads the tests requested to be run from this file. 111 | # 112 | # CFG_ENCODING=encoding 113 | # name of encoding for configuration information. Defaults 114 | # to cp1252 115 | # 116 | # 5) Examples: 117 | # 118 | # Basic syntax of calling nmake looks like this: 119 | # nmake [-nologo] -f makefile.vc [target|macrodef [target|macrodef] [...]] 120 | # 121 | # Standard (no frills) 122 | # c:\tcl_src\win\>c:\progra~1\micros~1\vc98\bin\vcvars32.bat 123 | # Setting environment for using Microsoft Visual C++ tools. 124 | # c:\tcl_src\win\>nmake -f makefile.vc all 125 | # c:\tcl_src\win\>nmake -f makefile.vc install INSTALLDIR=c:\progra~1\tcl 126 | # 127 | # Building for Win64 128 | # c:\tcl_src\win\>c:\progra~1\micros~1\vc98\bin\vcvars32.bat 129 | # Setting environment for using Microsoft Visual C++ tools. 130 | # c:\tcl_src\win\>c:\progra~1\platfo~1\setenv.bat /pre64 /RETAIL 131 | # Targeting Windows pre64 RETAIL 132 | # c:\tcl_src\win\>nmake -f makefile.vc MACHINE=IA64 133 | # 134 | #------------------------------------------------------------------------------ 135 | #============================================================================== 136 | ############################################################################### 137 | #------------------------------------------------------------------------------ 138 | 139 | !if !exist("makefile.vc") 140 | MSG = ^ 141 | You must run this makefile only from the directory it is in.^ 142 | Please `cd` to its location first. 143 | !error $(MSG) 144 | !endif 145 | 146 | #------------------------------------------------------------------------- 147 | # Project specific information (EDIT) 148 | # 149 | # You should edit this with the name and version of your project. This 150 | # information is used to generate the name of the package library and 151 | # it's install location. 152 | # 153 | # For example, the sample extension is going to build sample05.dll and 154 | # would install it into $(INSTALLDIR)\lib\sample05 155 | # 156 | # You need to specify the object files that need to be linked into your 157 | # binary here. 158 | # 159 | #------------------------------------------------------------------------- 160 | 161 | PROJECT = sample 162 | 163 | # Uncomment the following line if this is a Tk extension. 164 | #PROJECT_REQUIRES_TK=1 165 | !include "rules.vc" 166 | 167 | DOTVERSION = 0.5 168 | VERSION = $(DOTVERSION:.=) 169 | STUBPREFIX = $(PROJECT)stub 170 | 171 | DLLOBJS = \ 172 | $(TMP_DIR)\tclsample.obj \ 173 | $(TMP_DIR)\sample.obj \ 174 | !if !$(STATIC_BUILD) 175 | $(TMP_DIR)\sample.res 176 | !endif 177 | 178 | #------------------------------------------------------------------------- 179 | # Target names and paths ( shouldn't need changing ) 180 | #------------------------------------------------------------------------- 181 | 182 | BINROOT = . 183 | ROOT = .. 184 | 185 | PRJIMPLIB = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib 186 | PRJLIBNAME = $(PROJECT)$(VERSION)$(SUFX).$(EXT) 187 | PRJLIB = $(OUT_DIR)\$(PRJLIBNAME) 188 | 189 | PRJSTUBLIBNAME = $(STUBPREFIX)$(VERSION).lib 190 | PRJSTUBLIB = $(OUT_DIR)\$(PRJSTUBLIBNAME) 191 | 192 | ### Make sure we use backslash only. 193 | PRJ_INSTALL_DIR = $(_INSTALLDIR)\$(PROJECT)$(DOTVERSION) 194 | LIB_INSTALL_DIR = $(PRJ_INSTALL_DIR) 195 | BIN_INSTALL_DIR = $(PRJ_INSTALL_DIR) 196 | DOC_INSTALL_DIR = $(PRJ_INSTALL_DIR) 197 | SCRIPT_INSTALL_DIR = $(PRJ_INSTALL_DIR) 198 | INCLUDE_INSTALL_DIR = $(_TCLDIR)\include 199 | 200 | ### The following paths CANNOT have spaces in them. 201 | GENERICDIR = $(ROOT)\generic 202 | WINDIR = $(ROOT)\win 203 | LIBDIR = $(ROOT)\library 204 | DOCDIR = $(ROOT)\doc 205 | TOOLSDIR = $(ROOT)\tools 206 | COMPATDIR = $(ROOT)\compat 207 | 208 | #--------------------------------------------------------------------- 209 | # Compile flags 210 | #--------------------------------------------------------------------- 211 | 212 | !if !$(DEBUG) 213 | !if $(OPTIMIZING) 214 | ### This cranks the optimization level to maximize speed 215 | cdebug = $(OPTIMIZATIONS) 216 | !else 217 | cdebug = 218 | !endif 219 | !else if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64" 220 | ### Warnings are too many, can't support warnings into errors. 221 | cdebug = -Zi -Od $(DEBUGFLAGS) 222 | !else 223 | cdebug = -Zi -WX $(DEBUGFLAGS) 224 | !endif 225 | 226 | ### Declarations common to all compiler options 227 | cwarn = $(WARNINGS) -D _CRT_SECURE_NO_DEPRECATE -D _CRT_NONSTDC_NO_DEPRECATE 228 | cflags = -nologo -c $(COMPILERFLAGS) -DBUILD_$(PROJECT) $(cwarn) -Fp$(TMP_DIR)^\ 229 | 230 | !if $(MSVCRT) 231 | !if $(DEBUG) && !$(UNCHECKED) 232 | crt = -MDd 233 | !else 234 | crt = -MD 235 | !endif 236 | !else 237 | !if $(DEBUG) && !$(UNCHECKED) 238 | crt = -MTd 239 | !else 240 | crt = -MT 241 | !endif 242 | !endif 243 | 244 | !if !$(STATIC_BUILD) 245 | cflags = $(cflags) -DUSE_TCL_STUBS 246 | !if defined(TKSTUBLIB) 247 | cflags = $(cflags) -DUSE_TK_STUBS 248 | !endif 249 | !endif 250 | 251 | INCLUDES = $(TCL_INCLUDES) -I"$(WINDIR)" -I"$(GENERICDIR)" 252 | BASE_CFLAGS = $(cflags) $(cdebug) $(crt) $(INCLUDES) 253 | CON_CFLAGS = $(cflags) $(cdebug) $(crt) -DCONSOLE 254 | TCL_CFLAGS = -DPACKAGE_NAME="\"$(PROJECT)\"" \ 255 | -DPACKAGE_VERSION="\"$(DOTVERSION)\"" \ 256 | -DBUILD_$(PROJECT) \ 257 | $(BASE_CFLAGS) $(OPTDEFINES) 258 | 259 | #--------------------------------------------------------------------- 260 | # Link flags 261 | #--------------------------------------------------------------------- 262 | 263 | !if $(DEBUG) 264 | ldebug = -debug:full -debugtype:cv 265 | !if $(MSVCRT) 266 | ldebug = $(ldebug) -nodefaultlib:msvcrt 267 | !endif 268 | !else 269 | ldebug = -release -opt:ref -opt:icf,3 270 | !endif 271 | 272 | ### Declarations common to all linker options 273 | lflags = -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug) 274 | 275 | !if $(PROFILE) 276 | lflags = $(lflags) -profile 277 | !endif 278 | 279 | !if $(ALIGN98_HACK) && !$(STATIC_BUILD) 280 | ### Align sections for PE size savings. 281 | lflags = $(lflags) -opt:nowin98 282 | !else if !$(ALIGN98_HACK) && $(STATIC_BUILD) 283 | ### Align sections for speed in loading by choosing the virtual page size. 284 | lflags = $(lflags) -align:4096 285 | !endif 286 | 287 | !if $(LOIMPACT) 288 | lflags = $(lflags) -ws:aggressive 289 | !endif 290 | 291 | dlllflags = $(lflags) -dll 292 | conlflags = $(lflags) -subsystem:console 293 | guilflags = $(lflags) -subsystem:windows 294 | !if !$(STATIC_BUILD) 295 | baselibs = $(TCLSTUBLIB) 296 | !if defined(TKSTUBLIB) 297 | baselibs = $(baselibs) $(TKSTUBLIB) 298 | !endif 299 | !endif 300 | 301 | # Avoid 'unresolved external symbol __security_cookie' errors. 302 | # c.f. http://support.microsoft.com/?id=894573 303 | !if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64" 304 | !if $(VCVERSION) >= 1400 && $(VCVERSION) < 1500 305 | baselibs = $(baselibs) bufferoverflowU.lib 306 | !endif 307 | !endif 308 | 309 | baselibs = $(baselibs) user32.lib gdi32.lib 310 | 311 | #--------------------------------------------------------------------- 312 | # TclTest flags 313 | #--------------------------------------------------------------------- 314 | 315 | !IF "$(TESTPAT)" != "" 316 | TESTFLAGS = $(TESTFLAGS) -file $(TESTPAT) 317 | !ENDIF 318 | 319 | #--------------------------------------------------------------------- 320 | # Project specific targets (EDIT) 321 | #--------------------------------------------------------------------- 322 | 323 | all: setup $(PROJECT) 324 | $(PROJECT): setup pkgIndex $(PRJLIB) 325 | install: install-binaries install-libraries install-docs 326 | pkgIndex: $(OUT_DIR)\pkgIndex.tcl 327 | 328 | test: setup $(PROJECT) 329 | @set TCL_LIBRARY=$(TCL_LIBRARY:\=/) 330 | @set TCLLIBPATH=$(OUT_DIR_PATH:\=/) 331 | !if $(TCLINSTALL) 332 | @set PATH=$(_TCLDIR)\bin;$(PATH) 333 | !else 334 | @set PATH=$(_TCLDIR)\win\$(BUILDDIRTOP);$(PATH) 335 | !endif 336 | !if "$(OS)" == "Windows_NT" || "$(MSVCDIR)" == "IDE" 337 | $(DEBUGGER) $(TCLSH) "$(ROOT)/tests/all.tcl" $(TESTFLAGS) 338 | !else 339 | @echo Please wait while the tests are collected... 340 | $(DEBUGGER) $(TCLSH) "$(ROOT)/tests/all.tcl" $(TESTFLAGS) > tests.log 341 | type tests.log | more 342 | !endif 343 | 344 | shell: setup $(PROJECT) 345 | @set VLERQ_LIBRARY=$(LIBDIR:\=/) 346 | @set TCL_LIBRARY=$(TCL_LIBRARY:\=/) 347 | @set TCLLIBPATH=$(OUT_DIR_PATH:\=/) 348 | !if $(TCLINSTALL) 349 | @set PATH=$(_TCLDIR)\bin;$(PATH) 350 | !else 351 | @set PATH=$(_TCLDIR)\win\$(BUILDDIRTOP);$(PATH) 352 | !endif 353 | $(DEBUGGER) $(TCLSH) $(SCRIPT) 354 | 355 | setup: 356 | @if not exist $(OUT_DIR)\nul mkdir $(OUT_DIR) 357 | @if not exist $(TMP_DIR)\nul mkdir $(TMP_DIR) 358 | 359 | # See /win/coffbase.txt for extension base addresses. 360 | $(PRJLIB): $(DLLOBJS) 361 | !if $(STATIC_BUILD) 362 | $(lib32) -nologo -out:$@ @<< 363 | $** 364 | << 365 | !else 366 | $(link32) $(dlllflags) -base:0x10000000 -out:$@ $(baselibs) @<< 367 | $** 368 | << 369 | $(_VC_MANIFEST_EMBED_DLL) 370 | -@del $*.exp 371 | !endif 372 | 373 | $(PRJSTUBLIB): $(PRJSTUBOBJS) 374 | $(lib32) -nologo -out:$@ $(PRJSTUBOBJS) 375 | 376 | #--------------------------------------------------------------------- 377 | # Implicit rules 378 | #--------------------------------------------------------------------- 379 | 380 | {$(WINDIR)}.c{$(TMP_DIR)}.obj:: 381 | $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<< 382 | $< 383 | << 384 | 385 | {$(GENERICDIR)}.c{$(TMP_DIR)}.obj:: 386 | $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<< 387 | $< 388 | << 389 | 390 | {$(COMPATDIR)}.c{$(TMP_DIR)}.obj:: 391 | $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<< 392 | $< 393 | << 394 | 395 | {$(WINDIR)}.rc{$(TMP_DIR)}.res: 396 | $(rc32) -fo $@ -r -i "$(GENERICDIR)" -D__WIN32__ \ 397 | -DCOMMAVERSION=$(DOTVERSION:.=,),0,0 \ 398 | -DDOTVERSION=\"$(DOTVERSION)\" \ 399 | -DVERSION=\"$(VERSION)$(SUFX)\" \ 400 | !if $(DEBUG) 401 | -d DEBUG \ 402 | !endif 403 | !if $(TCL_THREADS) 404 | -d TCL_THREADS \ 405 | !endif 406 | !if $(STATIC_BUILD) 407 | -d STATIC_BUILD \ 408 | !endif 409 | $< 410 | 411 | .SUFFIXES: 412 | .SUFFIXES:.c .rc 413 | 414 | #------------------------------------------------------------------------- 415 | # Explicit dependency rules 416 | # 417 | #------------------------------------------------------------------------- 418 | 419 | $(OUT_DIR)\pkgIndex.tcl: $(ROOT)\pkgIndex.tcl.in 420 | @nmakehlp -s << $** > $@ 421 | @PACKAGE_VERSION@ $(DOTVERSION) 422 | @PACKAGE_NAME@ $(PROJECT) 423 | @PKG_LIB_FILE@ $(PRJLIBNAME) 424 | << 425 | @echo package ifneeded sample $(DOTVERSION) \ 426 | [list load [file join $$dir $(PRJLIBNAME)] Sample] >> $@ 427 | 428 | #--------------------------------------------------------------------- 429 | # Installation. (EDIT) 430 | # 431 | # You may need to modify this section to reflect the final distribution 432 | # of your files and possibly to generate documentation. 433 | # 434 | #--------------------------------------------------------------------- 435 | 436 | install-binaries: 437 | @echo Installing binaries to '$(SCRIPT_INSTALL_DIR)' 438 | @if not exist "$(SCRIPT_INSTALL_DIR)" mkdir "$(SCRIPT_INSTALL_DIR)" 439 | @$(CPY) $(PRJLIB) "$(SCRIPT_INSTALL_DIR)" >NUL 440 | 441 | install-libraries: $(OUT_DIR)\pkgIndex.tcl 442 | @echo Installing libraries to '$(SCRIPT_INSTALL_DIR)' 443 | @if exist $(LIBDIR) $(CPY) $(LIBDIR)\*.tcl "$(SCRIPT_INSTALL_DIR)" 444 | @echo Installing package index in '$(SCRIPT_INSTALL_DIR)' 445 | @$(CPY) $(OUT_DIR)\pkgIndex.tcl $(SCRIPT_INSTALL_DIR) 446 | 447 | install-docs: 448 | @echo Installing documentation files to '$(DOC_INSTALL_DIR)' 449 | @if exist $(DOCDIR) $(CPY) $(DOCDIR)\*.n "$(DOC_INSTALL_DIR)" 450 | 451 | #--------------------------------------------------------------------- 452 | # Clean up 453 | #--------------------------------------------------------------------- 454 | 455 | clean: 456 | @if exist $(TMP_DIR)\nul $(RMDIR) $(TMP_DIR) 457 | @if exist $(WINDIR)\version.vc del $(WINDIR)\version.vc 458 | @if exist $(WINDIR)\vercl.i del $(WINDIR)\vercl.i 459 | @if exist $(WINDIR)\vercl.x del $(WINDIR)\vercl.x 460 | @if exist $(WINDIR)\_junk.pch del $(WINDIR)\_junk.pch 461 | 462 | realclean: clean 463 | @if exist $(OUT_DIR)\nul $(RMDIR) $(OUT_DIR) 464 | 465 | distclean: realclean 466 | @if exist $(WINDIR)\nmakehlp.exe del $(WINDIR)\nmakehlp.exe 467 | @if exist $(WINDIR)\nmakehlp.obj del $(WINDIR)\nmakehlp.obj 468 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in -- 2 | # 3 | # This file is a Makefile for Sample TEA Extension. If it has the name 4 | # "Makefile.in" then it is a template for a Makefile; to generate the 5 | # actual Makefile, run "./configure", which is a configuration script 6 | # generated by the "autoconf" program (constructs like "@foo@" will get 7 | # replaced in the actual Makefile. 8 | # 9 | # Copyright (c) 1999 Scriptics Corporation. 10 | # Copyright (c) 2002-2005 ActiveState Corporation. 11 | # 12 | # See the file "license.terms" for information on usage and redistribution 13 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. 14 | # 15 | # RCS: @(#) $Id$ 16 | 17 | #======================================================================== 18 | # Add additional lines to handle any additional AC_SUBST cases that 19 | # have been added in a customized configure script. 20 | #======================================================================== 21 | 22 | #SAMPLE_NEW_VAR = @SAMPLE_NEW_VAR@ 23 | 24 | #======================================================================== 25 | # Nothing of the variables below this line should need to be changed. 26 | # Please check the TARGETS section below to make sure the make targets 27 | # are correct. 28 | #======================================================================== 29 | 30 | #======================================================================== 31 | # The names of the source files is defined in the configure script. 32 | # The object files are used for linking into the final library. 33 | # This will be used when a dist target is added to the Makefile. 34 | # It is not important to specify the directory, as long as it is the 35 | # $(srcdir) or in the generic, win or unix subdirectory. 36 | #======================================================================== 37 | 38 | PKG_SOURCES = @PKG_SOURCES@ 39 | PKG_OBJECTS = @PKG_OBJECTS@ 40 | 41 | PKG_STUB_SOURCES = @PKG_STUB_SOURCES@ 42 | PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@ 43 | 44 | #======================================================================== 45 | # PKG_TCL_SOURCES identifies Tcl runtime files that are associated with 46 | # this package that need to be installed, if any. 47 | #======================================================================== 48 | 49 | PKG_TCL_SOURCES = @PKG_TCL_SOURCES@ 50 | 51 | #======================================================================== 52 | # This is a list of public header files to be installed, if any. 53 | #======================================================================== 54 | 55 | PKG_HEADERS = @PKG_HEADERS@ 56 | 57 | #======================================================================== 58 | # "PKG_LIB_FILE" refers to the library (dynamic or static as per 59 | # configuration options) composed of the named objects. 60 | #======================================================================== 61 | 62 | PKG_LIB_FILE = @PKG_LIB_FILE@ 63 | PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@ 64 | 65 | lib_BINARIES = $(PKG_LIB_FILE) 66 | BINARIES = $(lib_BINARIES) 67 | 68 | SHELL = @SHELL@ 69 | 70 | srcdir = @srcdir@ 71 | prefix = @prefix@ 72 | exec_prefix = @exec_prefix@ 73 | 74 | bindir = @bindir@ 75 | libdir = @libdir@ 76 | includedir = @includedir@ 77 | datarootdir = @datarootdir@ 78 | datadir = @datadir@ 79 | mandir = @mandir@ 80 | 81 | DESTDIR = 82 | 83 | PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_VERSION) 84 | pkgdatadir = $(datadir)/$(PKG_DIR) 85 | pkglibdir = $(libdir)/$(PKG_DIR) 86 | pkgincludedir = $(includedir)/$(PKG_DIR) 87 | 88 | top_builddir = . 89 | 90 | INSTALL_OPTIONS = 91 | INSTALL = $(SHELL) $(srcdir)/tclconfig/install-sh -c ${INSTALL_OPTIONS} 92 | INSTALL_DATA_DIR = ${INSTALL} -d -m 755 93 | INSTALL_PROGRAM = ${INSTALL} -m 555 94 | INSTALL_DATA = ${INSTALL} -m 444 95 | INSTALL_SCRIPT = ${INSTALL_PROGRAM} 96 | INSTALL_LIBRARY = ${INSTALL_DATA} 97 | 98 | PACKAGE_NAME = @PACKAGE_NAME@ 99 | PACKAGE_VERSION = @PACKAGE_VERSION@ 100 | CC = @CC@ 101 | CFLAGS_DEFAULT = @CFLAGS_DEFAULT@ 102 | CFLAGS_WARNING = @CFLAGS_WARNING@ 103 | EXEEXT = @EXEEXT@ 104 | LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@ 105 | MAKE_LIB = @MAKE_LIB@ 106 | MAKE_SHARED_LIB = @MAKE_SHARED_LIB@ 107 | MAKE_STATIC_LIB = @MAKE_STATIC_LIB@ 108 | MAKE_STUB_LIB = @MAKE_STUB_LIB@ 109 | OBJEXT = @OBJEXT@ 110 | RANLIB = @RANLIB@ 111 | RANLIB_STUB = @RANLIB_STUB@ 112 | SHLIB_CFLAGS = @SHLIB_CFLAGS@ 113 | SHLIB_LD = @SHLIB_LD@ 114 | SHLIB_LD_LIBS = @SHLIB_LD_LIBS@ 115 | STLIB_LD = @STLIB_LD@ 116 | #TCL_DEFS = @TCL_DEFS@ 117 | TCL_BIN_DIR = @TCL_BIN_DIR@ 118 | TCL_SRC_DIR = @TCL_SRC_DIR@ 119 | #TK_BIN_DIR = @TK_BIN_DIR@ 120 | #TK_SRC_DIR = @TK_SRC_DIR@ 121 | 122 | # Not used, but retained for reference of what libs Tcl required 123 | #TCL_LIBS = @TCL_LIBS@ 124 | 125 | #======================================================================== 126 | # TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our 127 | # package without installing. The other environment variables allow us 128 | # to test against an uninstalled Tcl. Add special env vars that you 129 | # require for testing here (like TCLX_LIBRARY). 130 | #======================================================================== 131 | 132 | EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR) 133 | #EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR) 134 | TCLLIBPATH = $(top_builddir) 135 | TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` 136 | PKG_ENV = @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \ 137 | PATH="$(EXTRA_PATH):$(PATH)" \ 138 | TCLLIBPATH="$(TCLLIBPATH)" 139 | 140 | TCLSH_PROG = @TCLSH_PROG@ 141 | TCLSH = $(PKG_ENV) $(TCLSH_ENV) $(TCLSH_PROG) 142 | 143 | #WISH_ENV = TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library` 144 | #WISH_PROG = @WISH_PROG@ 145 | #WISH = $(PKG_ENV) $(TCLSH_ENV) $(WISH_ENV) $(WISH_PROG) 146 | 147 | SHARED_BUILD = @SHARED_BUILD@ 148 | 149 | INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ 150 | #INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@ 151 | 152 | PKG_CFLAGS = @PKG_CFLAGS@ 153 | 154 | # TCL_DEFS is not strictly need here, but if you remove it, then you 155 | # must make sure that configure.in checks for the necessary components 156 | # that your library may use. TCL_DEFS can actually be a problem if 157 | # you do not compile with a similar machine setup as the Tcl core was 158 | # compiled with. 159 | #DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS) 160 | DEFS = @DEFS@ $(PKG_CFLAGS) 161 | 162 | # Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile 163 | CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl 164 | CLEANFILES = @CLEANFILES@ 165 | 166 | CPPFLAGS = @CPPFLAGS@ 167 | LIBS = @PKG_LIBS@ @LIBS@ 168 | AR = @AR@ 169 | CFLAGS = @CFLAGS@ 170 | COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) 171 | 172 | .SUFFIXES: .c .$(OBJEXT) 173 | 174 | #======================================================================== 175 | # Start of user-definable TARGETS section 176 | #======================================================================== 177 | 178 | #======================================================================== 179 | # TEA TARGETS. Please note that the "libraries:" target refers to platform 180 | # independent files, and the "binaries:" target inclues executable programs and 181 | # platform-dependent libraries. Modify these targets so that they install 182 | # the various pieces of your package. The make and install rules 183 | # for the BINARIES that you specified above have already been done. 184 | #======================================================================== 185 | 186 | all: binaries libraries doc 187 | 188 | #======================================================================== 189 | # The binaries target builds executable programs, Windows .dll's, unix 190 | # shared/static libraries, and any other platform-dependent files. 191 | # The list of targets to build for "binaries:" is specified at the top 192 | # of the Makefile, in the "BINARIES" variable. 193 | #======================================================================== 194 | 195 | binaries: $(BINARIES) 196 | 197 | libraries: 198 | 199 | #======================================================================== 200 | # Your doc target should differentiate from doc builds (by the developer) 201 | # and doc installs (see install-doc), which just install the docs on the 202 | # end user machine when building from source. 203 | #======================================================================== 204 | 205 | doc: 206 | @echo "If you have documentation to create, place the commands to" 207 | @echo "build the docs in the 'doc:' target. For example:" 208 | @echo " xml2nroff sample.xml > sample.n" 209 | @echo " xml2html sample.xml > sample.html" 210 | 211 | install: all install-binaries install-libraries install-doc 212 | 213 | install-binaries: binaries install-lib-binaries install-bin-binaries 214 | 215 | #======================================================================== 216 | # This rule installs platform-independent files, such as header files. 217 | # The list=...; for p in $$list handles the empty list case x-platform. 218 | #======================================================================== 219 | 220 | install-libraries: libraries 221 | @$(INSTALL_DATA_DIR) $(DESTDIR)$(includedir) 222 | @echo "Installing header files in $(DESTDIR)$(includedir)" 223 | @list='$(PKG_HEADERS)'; for i in $$list; do \ 224 | echo "Installing $(srcdir)/$$i" ; \ 225 | $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir) ; \ 226 | done; 227 | 228 | #======================================================================== 229 | # Install documentation. Unix manpages should go in the $(mandir) 230 | # directory. 231 | #======================================================================== 232 | 233 | install-doc: doc 234 | @$(INSTALL_DATA_DIR) $(DESTDIR)$(mandir)/mann 235 | @echo "Installing documentation in $(DESTDIR)$(mandir)" 236 | @list='$(srcdir)/doc/*.n'; for i in $$list; do \ 237 | echo "Installing $$i"; \ 238 | $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \ 239 | done 240 | 241 | test: binaries libraries 242 | $(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) 243 | 244 | shell: binaries libraries 245 | @$(TCLSH) $(SCRIPT) 246 | 247 | gdb: 248 | $(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT) 249 | 250 | VALGRINDARGS=--tool=memcheck --num-callers=8 --leak-resolution=high --leak-check=yes --show-reachable=yes -v 251 | 252 | valgrind: binaries libraries 253 | $(TCLSH_ENV) valgrind $(VALGRINDARGS) $(TCLSH_PROG) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) 254 | 255 | valgrindshell: binaries libraries 256 | $(TCLSH_ENV) valgrind $(VALGRINDARGS) $(TCLSH_PROG) $(SCRIPT) 257 | 258 | depend: 259 | 260 | #======================================================================== 261 | # $(PKG_LIB_FILE) should be listed as part of the BINARIES variable 262 | # mentioned above. That will ensure that this target is built when you 263 | # run "make binaries". 264 | # 265 | # The $(PKG_OBJECTS) objects are created and linked into the final 266 | # library. In most cases these object files will correspond to the 267 | # source files above. 268 | #======================================================================== 269 | 270 | $(PKG_LIB_FILE): $(PKG_OBJECTS) 271 | -rm -f $(PKG_LIB_FILE) 272 | ${MAKE_LIB} 273 | $(RANLIB) $(PKG_LIB_FILE) 274 | 275 | $(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS) 276 | -rm -f $(PKG_STUB_LIB_FILE) 277 | ${MAKE_STUB_LIB} 278 | $(RANLIB_STUB) $(PKG_STUB_LIB_FILE) 279 | 280 | #======================================================================== 281 | # We need to enumerate the list of .c to .o lines here. 282 | # 283 | # In the following lines, $(srcdir) refers to the toplevel directory 284 | # containing your extension. If your sources are in a subdirectory, 285 | # you will have to modify the paths to reflect this: 286 | # 287 | # sample.$(OBJEXT): $(srcdir)/generic/sample.c 288 | # $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@ 289 | # 290 | # Setting the VPATH variable to a list of paths will cause the makefile 291 | # to look into these paths when resolving .c to .obj dependencies. 292 | # As necessary, add $(srcdir):$(srcdir)/compat:.... 293 | #======================================================================== 294 | 295 | VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win:$(srcdir)/macosx 296 | 297 | .c.@OBJEXT@: 298 | $(COMPILE) -c `@CYGPATH@ $<` -o $@ 299 | 300 | #======================================================================== 301 | # Distribution creation 302 | # You may need to tweak this target to make it work correctly. 303 | #======================================================================== 304 | 305 | #COMPRESS = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar 306 | COMPRESS = gtar zcvf $(PKG_DIR).tar.gz $(PKG_DIR) 307 | DIST_ROOT = /tmp/dist 308 | DIST_DIR = $(DIST_ROOT)/$(PKG_DIR) 309 | 310 | dist-clean: 311 | rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.* 312 | 313 | dist: dist-clean 314 | mkdir -p $(DIST_DIR) 315 | cp -p $(srcdir)/ChangeLog $(srcdir)/README* $(srcdir)/license* \ 316 | $(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.in \ 317 | $(DIST_DIR)/ 318 | chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4 319 | chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.in 320 | 321 | for i in $(srcdir)/*.[ch]; do \ 322 | if [ -f $$i ]; then \ 323 | cp -p $$i $(DIST_DIR)/ ; \ 324 | fi; \ 325 | done; 326 | 327 | mkdir $(DIST_DIR)/tclconfig 328 | cp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \ 329 | $(DIST_DIR)/tclconfig/ 330 | chmod 664 $(DIST_DIR)/tclconfig/tcl.m4 331 | chmod +x $(DIST_DIR)/tclconfig/install-sh 332 | 333 | list='demos doc generic library mac tests unix win'; \ 334 | for p in $$list; do \ 335 | if test -d $(srcdir)/$$p ; then \ 336 | mkdir $(DIST_DIR)/$$p; \ 337 | cp -p $(srcdir)/$$p/*.* $(DIST_DIR)/$$p/; \ 338 | fi; \ 339 | done 340 | 341 | (cd $(DIST_ROOT); $(COMPRESS);) 342 | 343 | #======================================================================== 344 | # End of user-definable section 345 | #======================================================================== 346 | 347 | #======================================================================== 348 | # Don't modify the file to clean here. Instead, set the "CLEANFILES" 349 | # variable in configure.in 350 | #======================================================================== 351 | 352 | clean: 353 | -test -z "$(BINARIES)" || rm -f $(BINARIES) 354 | -rm -f *.$(OBJEXT) core *.core 355 | -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 356 | 357 | distclean: clean 358 | -rm -f *.tab.c 359 | -rm -f $(CONFIG_CLEAN_FILES) 360 | -rm -f config.cache config.log config.status 361 | 362 | #======================================================================== 363 | # Install binary object libraries. On Windows this includes both .dll and 364 | # .lib files. Because the .lib files are not explicitly listed anywhere, 365 | # we need to deduce their existence from the .dll file of the same name. 366 | # Library files go into the lib directory. 367 | # In addition, this will generate the pkgIndex.tcl 368 | # file in the install location (assuming it can find a usable tclsh shell) 369 | # 370 | # You should not have to modify this target. 371 | #======================================================================== 372 | 373 | install-lib-binaries: binaries 374 | @$(INSTALL_DATA_DIR) $(DESTDIR)$(pkglibdir) 375 | @list='$(lib_BINARIES)'; for p in $$list; do \ 376 | if test -f $$p; then \ 377 | echo " $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p"; \ 378 | $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p; \ 379 | stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \ 380 | if test "x$$stub" = "xstub"; then \ 381 | echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \ 382 | $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \ 383 | else \ 384 | echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \ 385 | $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \ 386 | fi; \ 387 | ext=`echo $$p|sed -e "s/.*\.//"`; \ 388 | if test "x$$ext" = "xdll"; then \ 389 | lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \ 390 | if test -f $$lib; then \ 391 | echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \ 392 | $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \ 393 | fi; \ 394 | fi; \ 395 | fi; \ 396 | done 397 | @list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ 398 | if test -f $(srcdir)/$$p; then \ 399 | destp=`basename $$p`; \ 400 | echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \ 401 | $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \ 402 | fi; \ 403 | done 404 | @if test "x$(SHARED_BUILD)" = "x1"; then \ 405 | echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \ 406 | $(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); \ 407 | fi 408 | 409 | #======================================================================== 410 | # Install binary executables (e.g. .exe files and dependent .dll files) 411 | # This is for files that must go in the bin directory (located next to 412 | # wish and tclsh), like dependent .dll files on Windows. 413 | # 414 | # You should not have to modify this target, except to define bin_BINARIES 415 | # above if necessary. 416 | #======================================================================== 417 | 418 | install-bin-binaries: binaries 419 | @$(INSTALL_DATA_DIR) $(DESTDIR)$(bindir) 420 | @list='$(bin_BINARIES)'; for p in $$list; do \ 421 | if test -f $$p; then \ 422 | echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \ 423 | $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \ 424 | fi; \ 425 | done 426 | 427 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status 428 | cd $(top_builddir) \ 429 | && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status 430 | 431 | uninstall-binaries: 432 | list='$(lib_BINARIES)'; for p in $$list; do \ 433 | rm -f $(DESTDIR)$(pkglibdir)/$$p; \ 434 | done 435 | list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ 436 | p=`basename $$p`; \ 437 | rm -f $(DESTDIR)$(pkglibdir)/$$p; \ 438 | done 439 | list='$(bin_BINARIES)'; for p in $$list; do \ 440 | rm -f $(DESTDIR)$(bindir)/$$p; \ 441 | done 442 | 443 | .PHONY: all binaries clean depend distclean doc install libraries test 444 | 445 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 446 | # Otherwise a system limit (for SysV at least) may be exceeded. 447 | .NOEXPORT: 448 | -------------------------------------------------------------------------------- /win/rules.vc: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------- -*- Makefile -*- 2 | # rules.vc -- 3 | # 4 | # Microsoft Visual C++ makefile include for decoding the commandline 5 | # macros. This file does not need editing to build Tcl. 6 | # 7 | # This version is modified from the Tcl source version to support 8 | # building extensions using nmake. 9 | # 10 | # See the file "license.terms" for information on usage and redistribution 11 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. 12 | # 13 | # Copyright (c) 2001-2002 David Gravereaux. 14 | # Copyright (c) 2003-2008 Patrick Thoyts 15 | # 16 | #------------------------------------------------------------------------------ 17 | # RCS: @(#) $Id$ 18 | #------------------------------------------------------------------------------ 19 | 20 | !ifndef _RULES_VC 21 | _RULES_VC = 1 22 | 23 | cc32 = $(CC) # built-in default. 24 | link32 = link 25 | lib32 = lib 26 | rc32 = $(RC) # built-in default. 27 | 28 | !ifndef INSTALLDIR 29 | ### Assume the normal default. 30 | _INSTALLDIR = C:\Program Files\Tcl 31 | !else 32 | ### Fix the path separators. 33 | _INSTALLDIR = $(INSTALLDIR:/=\) 34 | !endif 35 | 36 | !ifndef MACHINE 37 | !if "$(CPU)" == "" || "$(CPU)" == "i386" 38 | MACHINE = IX86 39 | !else 40 | MACHINE = $(CPU) 41 | !endif 42 | !endif 43 | 44 | !ifndef CFG_ENCODING 45 | CFG_ENCODING = \"cp1252\" 46 | !endif 47 | 48 | #---------------------------------------------------------- 49 | # Set the proper copy method to avoid overwrite questions 50 | # to the user when copying files and selecting the right 51 | # "delete all" method. 52 | #---------------------------------------------------------- 53 | 54 | !if "$(OS)" == "Windows_NT" 55 | RMDIR = rmdir /S /Q 56 | ERRNULL = 2>NUL 57 | !if ![ver | find "4.0" > nul] 58 | CPY = echo y | xcopy /i >NUL 59 | COPY = copy >NUL 60 | !else 61 | CPY = xcopy /i /y >NUL 62 | COPY = copy /y >NUL 63 | !endif 64 | !else # "$(OS)" != "Windows_NT" 65 | CPY = xcopy /i >_JUNK.OUT # On Win98 NUL does not work here. 66 | COPY = copy >_JUNK.OUT # On Win98 NUL does not work here. 67 | RMDIR = deltree /Y 68 | NULL = \NUL # Used in testing directory existence 69 | ERRNULL = >NUL # Win9x shell cannot redirect stderr 70 | !endif 71 | MKDIR = mkdir 72 | 73 | !message =============================================================================== 74 | 75 | #---------------------------------------------------------- 76 | # build the helper app we need to overcome nmake's limiting 77 | # environment. 78 | #---------------------------------------------------------- 79 | 80 | !if !exist(nmakehlp.exe) 81 | !if [$(cc32) -nologo nmakehlp.c -link -subsystem:console > nul] 82 | !endif 83 | !endif 84 | 85 | #---------------------------------------------------------- 86 | # Test for compiler features 87 | #---------------------------------------------------------- 88 | 89 | ### test for optimizations 90 | !if [nmakehlp -c -Ot] 91 | !message *** Compiler has 'Optimizations' 92 | OPTIMIZING = 1 93 | !else 94 | !message *** Compiler does not have 'Optimizations' 95 | OPTIMIZING = 0 96 | !endif 97 | 98 | OPTIMIZATIONS = 99 | 100 | !if [nmakehlp -c -Ot] 101 | OPTIMIZATIONS = $(OPTIMIZATIONS) -Ot 102 | !endif 103 | 104 | !if [nmakehlp -c -Oi] 105 | OPTIMIZATIONS = $(OPTIMIZATIONS) -Oi 106 | !endif 107 | 108 | !if [nmakehlp -c -Op] 109 | OPTIMIZATIONS = $(OPTIMIZATIONS) -Op 110 | !endif 111 | 112 | !if [nmakehlp -c -fp:strict] 113 | OPTIMIZATIONS = $(OPTIMIZATIONS) -fp:strict 114 | !endif 115 | 116 | !if [nmakehlp -c -Gs] 117 | OPTIMIZATIONS = $(OPTIMIZATIONS) -Gs 118 | !endif 119 | 120 | !if [nmakehlp -c -GS] 121 | OPTIMIZATIONS = $(OPTIMIZATIONS) -GS 122 | !endif 123 | 124 | !if [nmakehlp -c -GL] 125 | OPTIMIZATIONS = $(OPTIMIZATIONS) -GL 126 | !endif 127 | 128 | DEBUGFLAGS = 129 | 130 | !if [nmakehlp -c -RTC1] 131 | DEBUGFLAGS = $(DEBUGFLAGS) -RTC1 132 | !elseif [nmakehlp -c -GZ] 133 | DEBUGFLAGS = $(DEBUGFLAGS) -GZ 134 | !endif 135 | 136 | COMPILERFLAGS =-W3 137 | 138 | # In v13 -GL and -YX are incompatible. 139 | !if [nmakehlp -c -YX] 140 | !if ![nmakehlp -c -GL] 141 | OPTIMIZATIONS = $(OPTIMIZATIONS) -YX 142 | !endif 143 | !endif 144 | 145 | !if "$(MACHINE)" == "IX86" 146 | ### test for pentium errata 147 | !if [nmakehlp -c -QI0f] 148 | !message *** Compiler has 'Pentium 0x0f fix' 149 | COMPILERFLAGS = $(COMPILERFLAGSS) -QI0f 150 | !else 151 | !message *** Compiler does not have 'Pentium 0x0f fix' 152 | !endif 153 | !endif 154 | 155 | !if "$(MACHINE)" == "IA64" 156 | ### test for Itanium errata 157 | !if [nmakehlp -c -QIA64_Bx] 158 | !message *** Compiler has 'B-stepping errata workarounds' 159 | COMPILERFLAGS = $(COMPILERFLAGS) -QIA64_Bx 160 | !else 161 | !message *** Compiler does not have 'B-stepping errata workarounds' 162 | !endif 163 | !endif 164 | 165 | !if "$(MACHINE)" == "IX86" 166 | ### test for -align:4096, when align:512 will do. 167 | !if [nmakehlp -l -opt:nowin98] 168 | !message *** Linker has 'Win98 alignment problem' 169 | ALIGN98_HACK = 1 170 | !else 171 | !message *** Linker does not have 'Win98 alignment problem' 172 | ALIGN98_HACK = 0 173 | !endif 174 | !else 175 | ALIGN98_HACK = 0 176 | !endif 177 | 178 | LINKERFLAGS = 179 | 180 | !if [nmakehlp -l -ltcg] 181 | LINKERFLAGS =-ltcg 182 | !endif 183 | 184 | #---------------------------------------------------------- 185 | # MSVC8 (ships with Visual Studio 2005) generates a manifest 186 | # file that we should link into the binaries. This is how. 187 | #---------------------------------------------------------- 188 | 189 | _VC_MANIFEST_EMBED_EXE= 190 | _VC_MANIFEST_EMBED_DLL= 191 | VCVER=0 192 | !if ![echo VCVERSION=_MSC_VER > vercl.x] \ 193 | && ![cl -nologo -TC -P vercl.x $(ERRNULL)] 194 | !include vercl.i 195 | !if $(VCVERSION) >= 1500 196 | VCVER=9 197 | !elseif $(VCVERSION) >= 1400 198 | VCVER=8 199 | !elseif $(VCVERSION) >= 1300 200 | VCVER=7 201 | !elseif $(VCVERSION) >= 1200 202 | VCVER=6 203 | !endif 204 | !endif 205 | 206 | # Since MSVC8 we must deal with manifest resources. 207 | !if $(VCVERSION) >= 1400 208 | _VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1 209 | _VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2 210 | !endif 211 | 212 | #---------------------------------------------------------- 213 | # Decode the options requested. 214 | #---------------------------------------------------------- 215 | 216 | !if "$(OPTS)" == "" || [nmakehlp -f "$(OPTS)" "none"] 217 | STATIC_BUILD = 0 218 | TCL_THREADS = 1 219 | DEBUG = 0 220 | PROFILE = 0 221 | MSVCRT = 0 222 | LOIMPACT = 0 223 | TCL_USE_STATIC_PACKAGES = 0 224 | USE_THREAD_ALLOC = 1 225 | USE_THREAD_STORAGE = 1 226 | UNCHECKED = 0 227 | !else 228 | !if [nmakehlp -f $(OPTS) "static"] 229 | !message *** Doing static 230 | STATIC_BUILD = 1 231 | !else 232 | STATIC_BUILD = 0 233 | !endif 234 | !if [nmakehlp -f $(OPTS) "msvcrt"] 235 | !message *** Doing msvcrt 236 | MSVCRT = 1 237 | !else 238 | MSVCRT = 0 239 | !endif 240 | !if [nmakehlp -f $(OPTS) "staticpkg"] 241 | !message *** Doing staticpkg 242 | TCL_USE_STATIC_PACKAGES = 1 243 | !else 244 | TCL_USE_STATIC_PACKAGES = 0 245 | !endif 246 | !if [nmakehlp -f $(OPTS) "nothreads"] 247 | !message *** Compile explicitly for non-threaded tcl 248 | TCL_THREADS = 0 249 | !else 250 | TCL_THREADS = 1 251 | !endif 252 | !if [nmakehlp -f $(OPTS) "symbols"] 253 | !message *** Doing symbols 254 | DEBUG = 1 255 | !else 256 | DEBUG = 0 257 | !endif 258 | !if [nmakehlp -f $(OPTS) "profile"] 259 | !message *** Doing profile 260 | PROFILE = 1 261 | !else 262 | PROFILE = 0 263 | !endif 264 | !if [nmakehlp -f $(OPTS) "loimpact"] 265 | !message *** Doing loimpact 266 | LOIMPACT = 1 267 | !else 268 | LOIMPACT = 0 269 | !endif 270 | !if [nmakehlp -f $(OPTS) "thrdalloc"] 271 | !message *** Doing thrdalloc 272 | USE_THREAD_ALLOC = 1 273 | !else 274 | USE_THREAD_ALLOC = 0 275 | !endif 276 | !if [nmakehlp -f $(OPTS) "thrdstorage"] 277 | !message *** Doing thrdstorage 278 | USE_THREAD_STORAGE = 1 279 | !else 280 | USE_THREAD_STORAGE = 0 281 | !endif 282 | !if [nmakehlp -f $(OPTS) "unchecked"] 283 | !message *** Doing unchecked 284 | UNCHECKED = 1 285 | !else 286 | UNCHECKED = 0 287 | !endif 288 | !endif 289 | 290 | 291 | !if !$(STATIC_BUILD) 292 | # Make sure we don't build overly fat DLLs. 293 | MSVCRT = 1 294 | # We shouldn't statically put the extensions inside the shell when dynamic. 295 | TCL_USE_STATIC_PACKAGES = 0 296 | !endif 297 | 298 | 299 | #---------------------------------------------------------- 300 | # Figure-out how to name our intermediate and output directories. 301 | # We wouldn't want different builds to use the same .obj files 302 | # by accident. 303 | #---------------------------------------------------------- 304 | 305 | #---------------------------------------- 306 | # Naming convention: 307 | # t = full thread support. 308 | # s = static library (as opposed to an 309 | # import library) 310 | # g = linked to the debug enabled C 311 | # run-time. 312 | # x = special static build when it 313 | # links to the dynamic C run-time. 314 | #---------------------------------------- 315 | SUFX = sgx 316 | 317 | !if $(DEBUG) 318 | BUILDDIRTOP = Debug 319 | !else 320 | BUILDDIRTOP = Release 321 | !endif 322 | 323 | !if "$(MACHINE)" != "IX86" 324 | BUILDDIRTOP =$(BUILDDIRTOP)_$(MACHINE) 325 | !endif 326 | !if $(VCVER) > 6 327 | BUILDDIRTOP =$(BUILDDIRTOP)_VC$(VCVER) 328 | !endif 329 | 330 | !if !$(DEBUG) || $(DEBUG) && $(UNCHECKED) 331 | SUFX = $(SUFX:g=) 332 | !endif 333 | 334 | TMP_DIRFULL = .\$(BUILDDIRTOP)\$(PROJECT)_ThreadedDynamicStaticX 335 | 336 | !if !$(STATIC_BUILD) 337 | TMP_DIRFULL = $(TMP_DIRFULL:Static=) 338 | SUFX = $(SUFX:s=) 339 | EXT = dll 340 | !if $(MSVCRT) 341 | TMP_DIRFULL = $(TMP_DIRFULL:X=) 342 | SUFX = $(SUFX:x=) 343 | !endif 344 | !else 345 | TMP_DIRFULL = $(TMP_DIRFULL:Dynamic=) 346 | EXT = lib 347 | !if !$(MSVCRT) 348 | TMP_DIRFULL = $(TMP_DIRFULL:X=) 349 | SUFX = $(SUFX:x=) 350 | !endif 351 | !endif 352 | 353 | !if !$(TCL_THREADS) 354 | TMP_DIRFULL = $(TMP_DIRFULL:Threaded=) 355 | SUFX = $(SUFX:t=) 356 | !endif 357 | 358 | !ifndef TMP_DIR 359 | TMP_DIR = $(TMP_DIRFULL) 360 | !ifndef OUT_DIR 361 | OUT_DIR = .\$(BUILDDIRTOP) 362 | !endif 363 | !else 364 | !ifndef OUT_DIR 365 | OUT_DIR = $(TMP_DIR) 366 | !endif 367 | !endif 368 | 369 | 370 | #---------------------------------------------------------- 371 | # Decode the statistics requested. 372 | #---------------------------------------------------------- 373 | 374 | !if "$(STATS)" == "" || [nmakehlp -f "$(STATS)" "none"] 375 | TCL_MEM_DEBUG = 0 376 | TCL_COMPILE_DEBUG = 0 377 | !else 378 | !if [nmakehlp -f $(STATS) "memdbg"] 379 | !message *** Doing memdbg 380 | TCL_MEM_DEBUG = 1 381 | !else 382 | TCL_MEM_DEBUG = 0 383 | !endif 384 | !if [nmakehlp -f $(STATS) "compdbg"] 385 | !message *** Doing compdbg 386 | TCL_COMPILE_DEBUG = 1 387 | !else 388 | TCL_COMPILE_DEBUG = 0 389 | !endif 390 | !endif 391 | 392 | 393 | #---------------------------------------------------------- 394 | # Decode the checks requested. 395 | #---------------------------------------------------------- 396 | 397 | !if "$(CHECKS)" == "" || [nmakehlp -f "$(CHECKS)" "none"] 398 | TCL_NO_DEPRECATED = 0 399 | WARNINGS = -W3 400 | !else 401 | !if [nmakehlp -f $(CHECKS) "nodep"] 402 | !message *** Doing nodep check 403 | TCL_NO_DEPRECATED = 1 404 | !else 405 | TCL_NO_DEPRECATED = 0 406 | !endif 407 | !if [nmakehlp -f $(CHECKS) "fullwarn"] 408 | !message *** Doing full warnings check 409 | WARNINGS = -W4 410 | !if [nmakehlp -l -warn:3] 411 | LINKERFLAGS = $(LINKERFLAGS) -warn:3 412 | !endif 413 | !else 414 | WARNINGS = -W3 415 | !endif 416 | !if [nmakehlp -f $(CHECKS) "64bit"] && [nmakehlp -c -Wp64] 417 | !message *** Doing 64bit portability warnings 418 | WARNINGS = $(WARNINGS) -Wp64 419 | !endif 420 | !endif 421 | 422 | #---------------------------------------------------------- 423 | # Set our defines now armed with our options. 424 | #---------------------------------------------------------- 425 | 426 | OPTDEFINES = -DTCL_CFGVAL_ENCODING=$(CFG_ENCODING) -DSTDC_HEADERS 427 | 428 | !if $(TCL_MEM_DEBUG) 429 | OPTDEFINES = $(OPTDEFINES) -DTCL_MEM_DEBUG 430 | !endif 431 | !if $(TCL_COMPILE_DEBUG) 432 | OPTDEFINES = $(OPTDEFINES) -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS 433 | !endif 434 | !if $(TCL_THREADS) 435 | OPTDEFINES = $(OPTDEFINES) -DTCL_THREADS=1 436 | !if $(USE_THREAD_ALLOC) 437 | OPTDEFINES = $(OPTDEFINES) -DUSE_THREAD_ALLOC=1 438 | !endif 439 | !if $(USE_THREAD_STORAGE) 440 | OPTDEFINES = $(OPTDEFINES) -DUSE_THREAD_STORAGE=1 441 | !endif 442 | !endif 443 | !if $(STATIC_BUILD) 444 | OPTDEFINES = $(OPTDEFINES) -DSTATIC_BUILD 445 | !endif 446 | !if $(TCL_NO_DEPRECATED) 447 | OPTDEFINES = $(OPTDEFINES) -DTCL_NO_DEPRECATED 448 | !endif 449 | 450 | !if $(DEBUG) 451 | OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_DEBUG 452 | !elseif $(OPTIMIZING) 453 | OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_OPTIMIZED 454 | !endif 455 | !if $(PROFILE) 456 | OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_PROFILED 457 | !endif 458 | !if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64" 459 | OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_DO64BIT 460 | !endif 461 | 462 | 463 | #---------------------------------------------------------- 464 | # Get common info used when building extensions. 465 | #---------------------------------------------------------- 466 | 467 | !if "$(PROJECT)" != "tcl" 468 | 469 | # If INSTALLDIR set to tcl root dir then reset to the lib dir. 470 | !if exist("$(_INSTALLDIR)\include\tcl.h") 471 | _INSTALLDIR=$(_INSTALLDIR)\lib 472 | !endif 473 | 474 | !if !defined(TCLDIR) 475 | !if exist("$(_INSTALLDIR)\..\include\tcl.h") 476 | TCLINSTALL = 1 477 | _TCLDIR = $(_INSTALLDIR)\.. 478 | _TCL_H = $(_INSTALLDIR)\..\include\tcl.h 479 | TCLDIR = $(_INSTALLDIR)\.. 480 | !else 481 | MSG=^ 482 | Failed to find tcl.h. Set the TCLDIR macro. 483 | !error $(MSG) 484 | !endif 485 | !else 486 | _TCLDIR = $(TCLDIR:/=\) 487 | !if exist("$(_TCLDIR)\include\tcl.h") 488 | TCLINSTALL = 1 489 | _TCL_H = $(_TCLDIR)\include\tcl.h 490 | !elseif exist("$(_TCLDIR)\generic\tcl.h") 491 | TCLINSTALL = 0 492 | _TCL_H = $(_TCLDIR)\generic\tcl.h 493 | !else 494 | MSG =^ 495 | Failed to find tcl.h. The TCLDIR macro does not appear correct. 496 | !error $(MSG) 497 | !endif 498 | !endif 499 | 500 | !if [echo REM = This file is generated from rules.vc > version.vc] 501 | !endif 502 | !if exist("$(_TCL_H)") 503 | !if [echo TCL_DOTVERSION = \>> version.vc] \ 504 | && [nmakehlp -V "$(_TCL_H)" TCL_VERSION >> version.vc] 505 | !endif 506 | !endif 507 | !include version.vc 508 | TCL_VERSION = $(TCL_DOTVERSION:.=) 509 | 510 | !if $(TCLINSTALL) 511 | TCLSH = "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX).exe" 512 | !if !exist($(TCLSH)) && $(TCL_THREADS) 513 | TCLSH = "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX).exe" 514 | !endif 515 | TCLSTUBLIB = "$(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib" 516 | TCLIMPLIB = "$(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib" 517 | TCL_LIBRARY = $(_TCLDIR)\lib 518 | TCL_INCLUDES = -I"$(_TCLDIR)\include" 519 | !else 520 | TCLSH = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX).exe" 521 | !if !exist($(TCLSH)) && $(TCL_THREADS) 522 | TCLSH = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX).exe" 523 | !endif 524 | TCLSTUBLIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib" 525 | TCLIMPLIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib" 526 | TCL_LIBRARY = $(_TCLDIR)\library 527 | TCL_INCLUDES = -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win" 528 | !endif 529 | 530 | !endif 531 | 532 | #---------------------------------------------------------- 533 | # Optionally check for Tk info for building extensions. 534 | #---------------------------------------------------------- 535 | 536 | !ifdef PROJECT_REQUIRES_TK 537 | !if "$(PROJECT)" != "tcl" && "$(PROJECT)" != "tk" 538 | 539 | !if !defined(TKDIR) 540 | !if exist("$(_INSTALLDIR)\..\include\tk.h") 541 | TKINSTALL = 1 542 | _TKDIR = $(_INSTALLDIR)\.. 543 | _TK_H = $(_TKDIR)\include\tk.h 544 | TKDIR = $(_TKDIR) 545 | !elseif exist("$(_TCLDIR)\include\tk.h") 546 | TKINSTALL = 1 547 | _TKDIR = $(_TCLDIR) 548 | _TK_H = $(_TKDIR)\include\tk.h 549 | TKDIR = $(_TKDIR) 550 | !endif 551 | !else 552 | _TKDIR = $(TKDIR:/=\) 553 | !if exist("$(_TKDIR)\include\tk.h") 554 | TKINSTALL = 1 555 | _TK_H = $(_TKDIR)\include\tk.h 556 | !elseif exist("$(_TKDIR)\generic\tk.h") 557 | TKINSTALL = 0 558 | _TK_H = $(_TKDIR)\generic\tk.h 559 | !else 560 | MSG =^ 561 | Failed to find tk.h. The TKDIR macro does not appear correct. 562 | !error $(MSG) 563 | !endif 564 | !endif 565 | 566 | !if defined(TKDIR) 567 | TK_DOTVERSION = 8.4 568 | !if exist("$(_TK_H)") 569 | !if [echo TK_DOTVERSION = \>> version.vc] \ 570 | && [nmakehlp -V "$(_TK_H)" TK_VERSION >> version.vc] 571 | !endif 572 | !endif 573 | !include version.vc 574 | TK_VERSION = $(TK_DOTVERSION:.=) 575 | 576 | !if $(TKINSTALL) 577 | WISH = "$(_TKDIR)\bin\wish$(TK_VERSION)$(SUFX).exe" 578 | !if !exist($(WISH)) && $(TCL_THREADS) 579 | WISH = "$(_TKDIR)\bin\wish$(TK_VERSION)t$(SUFX).exe" 580 | !endif 581 | TKSTUBLIB = "$(_TKDIR)\lib\tkstub$(TK_VERSION).lib" 582 | TKIMPLIB = "$(_TKDIR)\lib\tk$(TK_VERSION)$(SUFX).lib" 583 | TK_INCLUDES = -I"$(_TKDIR)\include" 584 | TK_LIBRARY = $(_TKDIR)\lib 585 | !else 586 | WISH = "$(_TKDIR)\win\$(BUILDDIRTOP)\wish$(TCL_VERSION)$(SUFX).exe" 587 | !if !exist($(WISH)) && $(TCL_THREADS) 588 | WISH = "$(_TKDIR)\win\$(BUILDDIRTOP)\wish$(TCL_VERSION)t$(SUFX).exe" 589 | !endif 590 | TKSTUBLIB = "$(_TKDIR)\win\$(BUILDDIRTOP)\tkstub$(TCL_VERSION).lib" 591 | TKIMPLIB = "$(_TKDIR)\win\$(BUILDDIRTOP)\tk$(TCL_VERSION)$(SUFX).lib" 592 | TK_INCLUDES = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib" 593 | TK_LIBRARY = $(_TKDIR)\library 594 | !endif 595 | 596 | !endif 597 | !endif 598 | !endif 599 | 600 | 601 | #---------------------------------------------------------- 602 | # Setup the fully qualified OUT_DIR path as OUT_DIR_PATH 603 | #---------------------------------------------------------- 604 | !if [echo OUT_DIR_PATH = \>> version.vc] \ 605 | && [nmakehlp -Q "$(OUT_DIR)" >> version.vc] 606 | !endif 607 | !include version.vc 608 | 609 | 610 | #---------------------------------------------------------- 611 | # Display stats being used. 612 | #---------------------------------------------------------- 613 | 614 | !message *** Intermediate directory will be '$(TMP_DIR)' 615 | !message *** Output directory will be '$(OUT_DIR)' 616 | !message *** Suffix for binaries will be '$(SUFX)' 617 | !message *** Optional defines are '$(OPTDEFINES)' 618 | !message *** Compiler version $(VCVER). Target machine is $(MACHINE) 619 | !message *** Compiler options '$(COMPILERFLAGS) $(OPTIMIZATIONS) $(DEBUGFLAGS) $(WARNINGS)' 620 | !message *** Link options '$(LINKERFLAGS)' 621 | 622 | !endif 623 | -------------------------------------------------------------------------------- /tea/design.txt: -------------------------------------------------------------------------------- 1 | [section {Chapter 2. DESIGN AND CODING}] 2 | 3 | [section {Tcl extensions}] 4 | [para] 5 | 6 | In this document a [emph {Tcl extension}] is simply a collection of Tcl 7 | commands that can be distributed separately: an extension can be used 8 | in any application that wants to use the functionality it offers. 9 | 10 | [para] 11 | 12 | Well-known examples of extensions are: 13 | [list_begin bullet] 14 | [bullet] 15 | [emph msgcat]: translate text in an application that is to be shown to 16 | the user into the language that the user prefers. It is a collection 17 | of Tcl scripts that is shipped with Tcl itself. 18 | 19 | [bullet] 20 | [emph tktable]: a sophisticated widget to display and manipulate tabular 21 | data. In contrast to [emph msgcat], it is a [emph compiled] extension, 22 | consisting of both Tcl scripts and a loadable library of C functions. 23 | 24 | [bullet] 25 | [emph snack]: play and record sound from within a Tcl application. This 26 | extension relies on the presence of specific hardware and software (the computer 27 | must have audio capabilities). Such an extension is more complicated 28 | to maintain than either of the two others - you need to be aware of the 29 | typical libraries that are available on the various platforms and of 30 | the typical hardware that people use. 31 | 32 | [bullet] 33 | [emph tkimg]: manipulate images and image files with the support of a 34 | number of external libraries. 35 | 36 | [list_end] 37 | 38 | [para] 39 | Each of the four extensions we described exemplifies a category of 40 | extensions: 41 | 42 | [list_begin bullet] 43 | 44 | [bullet] 45 | Tcl-only extensions 46 | 47 | [bullet] 48 | Extensions built from Tcl and C code, but which are more or less 49 | independent of the operating system 50 | 51 | [bullet] 52 | Extensions built from Tcl and C code that do need to take care of the 53 | particular operating system 54 | 55 | [bullet] 56 | Extensions built from Tcl and C code that export new compiled 57 | functions (not commands!) to the Tcl interpreter. This adds an extra 58 | complication to the build process (see also the chapter on the stubs 59 | mechanism). 60 | 61 | [list_end] 62 | 63 | [emph Note:] 64 | [para] 65 | We have talked about C code, not because it is the only possibility, but 66 | because it is the most commonly used compiled language to extend Tcl. It 67 | is very well possible to use C++ or Fortran to build libraries that can 68 | be used from Tcl scripts. However, we will not go into these matters, 69 | they are beyond the scope of this document. 70 | 71 | [para] 72 | [emph Note:] 73 | [para] 74 | It is somewhat confusing that we use the words packages, extensions and 75 | modules to mean the same thing: Tcl commands or procedures that can be 76 | added to an application from some generally useable collection. The words 77 | each indicate a slightly different viewpoint: 78 | 79 | [list_begin bullet] 80 | [bullet] 81 | [emph package] refers to the mechanism by which a programmer loads the 82 | commands into his or her application: the commands are treated as a 83 | single collection. 84 | 85 | [bullet] 86 | [emph module] is often used to refer to a smaller collection inside a 87 | collection that is otherwise known as a whole, such as the 88 | Tcllib collection. Such large collections can be very heterogeneous, 89 | mixing network facilities with text processing facilities for 90 | instance. 91 | 92 | [bullet] 93 | [emph extension] is mostly used when a collection of commands is built 94 | from C sources, rather than Tcl scripts only, and it refers to both 95 | the source code and the actual compiled library or libraries. 96 | 97 | [list_end] 98 | 99 | Actually, all these terms can be used interchangeably and rather than 100 | invent a new word to replace them all, we will simply use all three 101 | terms, depending on the context. 102 | 103 | [para] 104 | Let us examine each of the above types of extensions in more detail in 105 | the next few sections. 106 | 107 | [section {Tcl-only extensions}] 108 | 109 | If you have a collection of Tcl scripts that you would like to distribute 110 | as a whole to others, then the situation is easy: 111 | 112 | [list_begin bullet] 113 | [bullet] 114 | Provide proper documentation, so that people can understand the extension 115 | without having to understand the code. 116 | 117 | [bullet] 118 | Provide the code as a package (more on the [emph package] mechanism in Chapter ..) 119 | 120 | [bullet] 121 | Wrap it in a zip-file or a tar-ball and put it on the Internet. 122 | 123 | [list_end] 124 | 125 | Well, things are a bit more complex than that. Let us have a look again at 126 | the [emph msgcat] extension as it is present in any or all Tcl installations: 127 | 128 | [list_begin bullet] 129 | 130 | [bullet] 131 | It lives in a directory of its own under the lib/tcl8.x directory 132 | 133 | [bullet] 134 | The file "pkgIndex.tcl" is used by the [emph {package require}] command to 135 | identify the presence of the package or extension and how to get it 136 | into the application (*). 137 | 138 | [bullet] 139 | Because it is used in Tk, you will find a few message catalogue files 140 | in the lib/tk8.x/msgs directory to translate text that appears in 141 | the wish window to the user's language. 142 | 143 | [list_end] 144 | 145 | (*) Note the uppercase "i" in this name: under Windows file names may be 146 | case-insensitive, this is not so under UNIX/Linux and many other 147 | operating systems. So, please take note of the precise spelling of 148 | file names. 149 | 150 | [para] 151 | Here is an excerpt of the directory that holds the extension itself (we 152 | used Tcl8.4 for this): 153 | [example { 154 | lib/ 155 | tcl8.4/ 156 | msgcat1.3/ 157 | msgcat.tcl 158 | pkgIndex.tcl 159 | }] 160 | In the source distribution, we can also find the file "msgcat.test" 161 | (containing the test cases) in the directory "tests" and the 162 | documentation in the file "msgcat.man". 163 | 164 | [para] 165 | The number "1.3" at the end of the directory name is no coincidence: it 166 | is the version number of the [emph msgcat] package. This way you can keep 167 | various versions of a package around. 168 | 169 | [para] 170 | In Tcllib, such a collection of files is found more commonly 171 | together, like for the CRC module (an excerpt from the CVS repository): 172 | [example { 173 | tcllib/ 174 | modules/ 175 | crc/ 176 | ChangeLog file containing short descriptions of 177 | changes over time 178 | cksum.man the documentation file 179 | cksum.tcl the actual Tcl script that implements 180 | the cksum command 181 | cksum.test the test cases 182 | ... (other related sources) 183 | }] 184 | 185 | There is no "pkgIndex.tcl" script, as this is created by the 186 | installation procedure for Tcllib as a whole. 187 | 188 | [para] 189 | [emph Note:] 190 | [para] 191 | If you are not familiar with CVS, it is a widely used source code 192 | control system. CVS is short for "concurrent version system". Such 193 | systems help automate the tedious task of keeping track of changes in 194 | the source code, documentation and other things over time. This is 195 | important, because this way you can see if a bug has actually been 196 | solved and when, for instance. 197 | 198 | 199 | [section {Extensions that are platform-independent}] 200 | 201 | A well-known extension like Tktable has to be built for all platforms 202 | that Tcl supports. Tktable itself does not have (much) code that differs 203 | from platform to platform. Yet, as the directory structure shows, it 204 | does have directories specific for the major platform categories, 205 | [emph {in the same way as do Tcl and Tk themselves}]: 206 | [example { 207 | tktable/ 208 | demos/ directory with demonstration scripts 209 | doc/ documentation 210 | generic/ the platform-independent sources 211 | library/ supporting scripts (in this case: key 212 | bindings and such) 213 | mac/ mac-specific sources (here: the 214 | project-file for building on Mac) 215 | tclconfig/ scripts that are used while building 216 | the extension 217 | tests/ test scripts 218 | unix/ unix-specific sources (here: nothing???) 219 | win/ Windows-specific sources (here: the 220 | project-file for building on Windows) 221 | ChangeLog description of changes 222 | Makefile.in TEA-template for the makefile 223 | aclocal.m4 "include" file required by Autoconf 224 | configure configure script generated by Autoconf 225 | configure.in TEA-template for the configure script 226 | ... (others files, not related to the building 227 | process itself) 228 | }] 229 | 230 | In this overview you will see some files related to the TEA, most 231 | notably, [emph Makefile.in] and [emph configure.in]. These will be described in 232 | great detail in Chapter 7 (fortunately the details have become less and 233 | less painful with the further development of TEA). 234 | 235 | [para] 236 | The most important thing is that this extension uses the [emph same] 237 | directory structure as Tcl/Tk itself. This may not always seem necessary 238 | (for instance, a Windows-specific extension might do without the unix 239 | and mac directories), but by keeping this same structure, you make it 240 | easier for others to manoeuvre through the source directory: they know 241 | what to expect. 242 | 243 | [section {Platform-dependent extensions}] 244 | 245 | Extensions that depend on the particular platform may need to deal with 246 | various OS aspects: 247 | 248 | [list_begin bullet] 249 | 250 | [bullet] 251 | They may require specific OS libraries 252 | 253 | [bullet] 254 | They may have extensive source code that is platform-dependent 255 | 256 | [bullet] 257 | They may have to deal with deficiencies of the platform, such as 258 | broken implementations of some standard library function (functions 259 | like strtod() are notorious in this respect) 260 | 261 | [list_end] 262 | 263 | The directory structure described in the previous section is 264 | quite useable in this case too. The platform-dependencies are expressed 265 | in the mac, unix and win directories containing one or more source files 266 | (not just project or make files), but also in the configure.in and 267 | Makefile.in files containing extra code to find the relevant 268 | OS libraries or checks for deficiencies. 269 | 270 | [section {Extensions exporting their own functions}] 271 | 272 | Complications arise when extensions need to export their own 273 | (compiled) functions, to provide their functionality. Again, this is not 274 | so much a matter of the directory structure, as it is a problem for 275 | building the extension. 276 | 277 | [para] 278 | In [emph tkimg] this is necessary because the photo command must have 279 | access to the functions that [emph tkimg] supplies. To do this in a way 280 | that does not tie [emph tkimg] to a particular version of Tcl/Tk, the 281 | stubs mechanism (see Chapter 5) is needed. 282 | 283 | [para] 284 | A simpler extension that provides its own stubs library is the backport 285 | of the dictionary data structure that is new in Tcl 8.5 to Tcl 4.x 286 | (done by Pascal Scheffers, ). The stubs 287 | library allows other extensions to use the functionality this [emph dict] 288 | extension provides, in much the same way as you can use the general Tcl 289 | API. We will discuss the implications in the next section and in the 290 | chapter on Tcl stubs. 291 | 292 | [section {Coding a C extension}] 293 | 294 | Now that we have covered the directory structure an extension should 295 | use, let us have a quick look at the C source code itself. (This is not 296 | a tutorial about how to use the Tcl/Tk API to build new 297 | compiled extensions. We simpy give some very basic information.) 298 | 299 | [para] 300 | A C extension, like the example that comes with TEA, contains an 301 | (exported) function with a specific name: Package_Init(), where 302 | "Package" is to be replaced by the name of the package (the first letter 303 | is capitalised, the rest is in lower-case). Here is the skeleton code 304 | for such a function: 305 | 306 | [example { 307 | int 308 | Package_Init(Tcl_Interp *interp) 309 | { 310 | /* Initialise the stubs library - see chapter 5 311 | */ 312 | if (Tcl_InitStubs(interp, "8.0", 0) == NULL) { 313 | return TCL_ERROR; 314 | } 315 | 316 | /* Require some version of Tcl, at least 8.0 317 | */ 318 | if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 0) == NULL) { 319 | if (TCL_VERSION[0] == '7') { 320 | if (Tcl_PkgRequire(interp, "Tcl", "8.0", 0) == NULL) { 321 | return TCL_ERROR; 322 | } 323 | } 324 | } 325 | 326 | /* Make the package known 327 | */ 328 | if (Tcl_PkgProvide(interp, "Package", VERSION) != TCL_OK) { 329 | return TCL_ERROR; 330 | } 331 | 332 | /* Create all the commands: 333 | Tcl command "cmd1" is implemented by the function Cmd1, 334 | etc. 335 | */ 336 | Tcl_CreateObjCommand(interp, "cmd1", Cmd1, 337 | (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); 338 | ... other commands ... 339 | 340 | return TCL_OK; 341 | } 342 | }] 343 | 344 | The functions that actually implement the Tcl commands are usually 345 | static functions, so that there is no name clash with other libraries. 346 | 347 | [para] 348 | The structure of the functions can be anything you like, but it is usual 349 | to: 350 | 351 | [list_begin bullet] 352 | 353 | [bullet] 354 | first check if the correct number of arguments is used 355 | 356 | [bullet] 357 | then dispatch on the first argument, in case subcommands are used 358 | 359 | [list_end] 360 | 361 | [example { 362 | (Code example) 363 | }] 364 | 365 | [para] 366 | The functions that your extension implements for public use should be 367 | properly prototyped via a header file - this is a matter of C coding 368 | style, but it also gives other people the opportunity to use your 369 | extension in their C extension. 370 | 371 | [para] 372 | The header file for an extension also contains the magic for 373 | building it on various platforms. To explain this magic and what you 374 | should be aware of, have a look at the header file of the sample 375 | extension: 376 | 377 | [example { 378 | /* 379 | * exampleA.h -- 380 | * 381 | * This header file contains the function declarations needed for 382 | * all of the source files in this package. 383 | * 384 | * Copyright (c) 1998-1999 Scriptics Corporation. 385 | * 386 | * See the file "license.terms" for information on usage and redistribution 387 | * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 388 | * 389 | */ 390 | 391 | #ifndef _EXAMPLEA 392 | #define _EXAMPLEA 393 | 394 | #include 395 | 396 | /* 397 | * Windows needs to know which symbols to export. Unix does not. 398 | * BUILD_exampleA should be undefined for Unix. 399 | */ 400 | 401 | #ifdef BUILD_exampleA 402 | #undef TCL_STORAGE_CLASS 403 | #define TCL_STORAGE_CLASS DLLEXPORT 404 | #endif /* BUILD_exampleA */ 405 | 406 | typedef struct { 407 | unsigned long state[5]; 408 | unsigned long count[2]; 409 | unsigned char buffer[64]; 410 | } SHA1_CTX; 411 | 412 | void SHA1Init _ANSI_ARGS_((SHA1_CTX* context)); 413 | void SHA1Update _ANSI_ARGS_((SHA1_CTX* context, unsigned char* data, 414 | unsigned int len)); 415 | void SHA1Final _ANSI_ARGS_((SHA1_CTX* context, unsigned char digest[20])); 416 | 417 | /* 418 | * Only the _Init function is exported. 419 | */ 420 | 421 | EXTERN int Examplea_Init _ANSI_ARGS_((Tcl_Interp * interp)); 422 | 423 | #endif /* _EXAMPLEA */ 424 | }] 425 | 426 | Explanation: 427 | 428 | [list_begin bullet] 429 | 430 | [bullet] 431 | The header file starts with a standard information block, describing 432 | the extension it belongs to. 433 | 434 | [bullet] 435 | The actual declarations are "bracketed" by an #ifndef/#endif pair to 436 | avoid multiple inclusions. 437 | 438 | [bullet] 439 | It includes the public Tcl header for access to the Tcl API, 440 | [emph {but not the private header file}] (see the recommendations section). 441 | 442 | [bullet] 443 | There is a piece of magic involving Windows builds: the macro 444 | BUILD_exampleA controls this. This is a macro that is defined via the 445 | [emph configure] file - more about this in Chapter 7. Note: this is 446 | boiler-plate stuff, only the name of the macro needs to be adjusted. 447 | 448 | [bullet] 449 | Most of what follows is specific to the extension: 450 | 451 | [list_begin bullet] 452 | [bullet] 453 | The definition of the structure that this extension uses 454 | [bullet] 455 | The prototypes for the public functions in the SHA1 library 456 | (the example extension is a wrapper for that library), but do 457 | note the use of the macro [emph ANSI_ARGS] - some systems still do 458 | not conform to the ANSI/ISO C standard 459 | [bullet] 460 | The last few lines concern the initialisation procedure, here 461 | again some magic, controlled by the EXTERN macro. 462 | [list_end] 463 | 464 | [list_end] 465 | 466 | If the extension provides its own [emph {stubs library}], then: 467 | [list_begin bullet] 468 | 469 | [bullet] 470 | add the following code fragments to the header file for your extension: 471 | 472 | [example { 473 | EXTERN CONST char * Examplea_InitStubs 474 | _ANSI_ARGS_((Tcl_Interp *interp, 475 | CONST char *version, int exact)); 476 | 477 | #ifndef USE_TCL_STUBS 478 | 479 | /* 480 | * When not using stubs, make it a macro. 481 | */ 482 | 483 | #define Examplea_InitStubs(interp, version, exact) \\ 484 | Tcl_PkgRequire(interp, "ExampleA", version, exact) 485 | 486 | #endif /* USE_TCL_STUBS */ 487 | 488 | /* 489 | * Include the public function declarations that are accessible via 490 | * the stubs table. 491 | */ 492 | 493 | #include "exampleaDecls.h"}] 494 | 495 | [bullet] 496 | prepare a declarations file (examplea.dict) that contains the 497 | definitions of all functions available via the stubs library. 498 | Here is a fragment of the dict extension: 499 | 500 | [example { 501 | # dict.decls -- 502 | # 503 | # This file contains the declarations for all supported public 504 | # functions that are exported by the Dict Tcl library via the 505 | # stubs table. 506 | # This file is used to generate the dictDecls.h and dictStub.c files. 507 | # 508 | # 509 | # Copyright (c) 1998-1999 by Scriptics Corporation. 510 | # Copyright (c) 2001, 2002 by Kevin B. Kenny. All rights reserved. 511 | # See the file "license.terms" for information on usage and redistribution 512 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. 513 | # 514 | # $Id$ 515 | # 516 | # Branched from: 517 | # RCS: @(#) Id: tcl.decls,v 1.103 2004/03/17 18:14:12 das Exp 518 | # for the dict backport. 519 | 520 | library dict 521 | 522 | # Define the dict interface, no sub interfaces. 523 | 524 | interface dict 525 | #hooks {} 526 | 527 | # Declare each of the functions in the public dict interface. Note that 528 | # the an index should never be reused for a different function in order 529 | # to preserve backwards compatibility. 530 | 531 | # DICTIONARIES - TIP#111 532 | declare 0 generic { 533 | int Tcl_DictObjPut(Tcl_Interp *interp, Tcl_Obj *dictPtr, 534 | Tcl_Obj *keyPtr, Tcl_Obj *valuePtr) 535 | } 536 | declare 1 generic { 537 | int Tcl_DictObjGet(Tcl_Interp *interp, Tcl_Obj *dictPtr, 538 | Tcl_Obj *keyPtr, Tcl_Obj **valuePtrPtr) 539 | } 540 | }] 541 | 542 | This file (yes, simply Tcl code) is processed by the tools/genStubs.tcl 543 | script to produce the "exampleaDecls.h" header file and the code for 544 | the stubs library. (Most of this is taken care of automatically - 545 | just make sure that the above steps are properly taken). 546 | 547 | [list_end] 548 | 549 | [section {Some recommendations}] 550 | 551 | We conclude this chapter with the following general recommendations: 552 | 553 | [list_begin bullet] 554 | 555 | [bullet] 556 | Use the Tcl_Obj interface, instead of the older string 557 | interface, as it is easier to work with and especially because 558 | it results in faster command processing. 559 | 560 | [bullet] 561 | If your use options, use key-value pairs, like in the Tk 562 | widgets: 563 | [example { 564 | $w configure -foreground black 565 | }] 566 | 567 | The reason is that this gives you much more freedom (options are known 568 | to expand over time, often you want to explicitly negate an option and 569 | inventing new keywords is more troublesome than just a new value. 570 | 571 | [bullet] 572 | Use only the public API of Tcl/Tk or any other extension. 573 | Otherwise your extension becomes tied to one particular version of 574 | Tcl/Tk, forbidding use in Tclkit for instance. What is more, if these 575 | internals change, you will have to change your extension as well. 576 | The public API is very unlikely to change, and if it changes, then 577 | backward compatibility is almost guaranteed (like with the string 578 | interface that still exists). 579 | 580 | [list_end] 581 | 582 | [para] 583 | [emph TODO:] 584 | Refer to TIP #55 and to Tcllib 585 | Describe a preferred directory structure (based on TIP #55) 586 | What about namespaces? 587 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2010-12-15 Stuart Cassoff 2 | 3 | * configure.in: Upgrade to newer install-sh and use it. 4 | * Makefile.in: 5 | * configure: Regenerated to use latest TEA tcl.m4. 6 | 7 | 2010-12-14 Stuart Cassoff 8 | 9 | * configure: Regenerated to use latest TEA tcl.m4. 10 | Better building on OpenBSD. 11 | 12 | 2010-12-14 Stuart Cassoff 13 | 14 | * Makefile.in: Make .SUFFIXES work for more (BSD) make programs. 15 | 16 | 2010-12-14 Jan Nijtmans 17 | 18 | * configure: Regenerated to use latest TEA tcl.m4. 19 | This adds cross-compile support to UNIX and Win, and 20 | support for building 64-bit executables with mingw-w64 21 | build tools. 22 | 23 | 2010-09-14 Jeff Hobbs 24 | 25 | * Makefile.in (valgrind): add valgrind sample targets 26 | 27 | 2010-08-16 Jeff Hobbs 28 | 29 | * Makefile.in (PKG_CFLAGS): remove -DBUILD_sample as that is 30 | auto-defined in TEA 3.9 31 | * configure, configure.in: update TEA 3.9 32 | 33 | 2010-08-12 Jeff Hobbs 34 | 35 | * configure: update TEA 3.8 36 | * Makefile.in (VPATH): add macosx. 37 | 38 | 2010-08-11 Jeff Hobbs 39 | 40 | * configure, configure.in: TEA 3.8 update, just include tcl.m4, 41 | modify TEA_INIT version and run autoconf 2.59 42 | 43 | 2010-04-30 Donal K. Fellows 44 | 45 | * doc/sha1.n: [Bug 2994714]: Updated documentation formatting to more 46 | closely follow Tcl's best practice guidelines in many aspects. 47 | 48 | 2010-04-29 Jan Nijtmans 49 | 50 | * doc/sha1.n [Enh 2788534]: add package require to doc 51 | 52 | 2010-04-23 Jan Nijtmans 53 | 54 | * configure: Regenerated to use latest TEA tcl.m4. 55 | * [Bug 2782806]: sample package's test cases fail 56 | Always define BUILD_sample, even on UNIX. 57 | 58 | 2010-02-19 Stuart Cassoff 59 | 60 | * tcl.m4: Correct compiler/linker flags for threaded builds on OpenBSD. 61 | * configure: Regenerated to use latest TEA tcl.m4. 62 | 63 | 2010-01-19 Jan Nijtmans 64 | 65 | * configure: Regenerated to use latest TEA tcl.m4. 66 | 67 | 2009-04-27 Jeff Hobbs 68 | 69 | * tcl.m4 (TEA_CONFIG_CFLAGS): harden the check to add _r to CC on AIX 70 | with threads. 71 | 72 | 2009-03-26 Jan Nijtmans 73 | 74 | * configure: Regenerated to use latest TEA tcl.m4. 75 | 76 | 2009-03-20 Andreas Kupries 77 | 78 | * configure: Regenerated to get my latest updates to tcl.m4 (See 79 | tclconfig/ChangeLog). 80 | 81 | NOTE: This pulled in an unexpected set of changes regarding 82 | SHLIB_VERSION and SHARED_LIB_SUFFIX, indicating that configure was not 83 | regenerated since some older change to tcl.m4. 84 | 85 | 2009-03-18 Stuart Cassoff 86 | 87 | * Makefile.in: [Bug 2429444]: Removed offending 'rm -f' line. 88 | 89 | 2009-03-11 Joe English 90 | 91 | * pkgIndex.tcl.in: [Bug 1960628]: use @PACKAGE_NAME@ instead of 92 | "Tclsha1". 93 | 94 | 2008-12-20 Daniel Steffen 95 | 96 | * Makefile.in: use INSTALL_LIBRARY instead of INSTALL_PROGRAM to 97 | install libraries, avoids breakage from tcl's install-strip when built 98 | as a bundled package. 99 | 100 | 2008-06-18 Pat Thoyts 101 | 102 | * win/makefile.vc: Updated win build files. Added new option to 103 | * win/rules.vc: nmakehlp to qualify a path name for use in setting 104 | * win/nmakehlp.c: up paths for test. 105 | 106 | 2007-10-23 Jeff Hobbs 107 | 108 | *** Tagged tea-3-branch to start TEA 4 development on HEAD *** 109 | 110 | * Makefile.in: separate PKG_ENV parts from TCLSH/WISH_ENV parts to 111 | better allow 8.4 and 8.5 core variant testing. 112 | 113 | 2007-05-11 Pat Thoyts 114 | 115 | * win/nmakehlp.c: Added support for simple substitution of an 116 | * win/makefile.vc: input file. This permits us to make use of 117 | pkgIndex.tcl.in style files without resorting to use of the tclsh 118 | we are building against -- when compiling for a foreign target (eg 119 | AMD64 from a ix86 host) we may not be able to run the 120 | tclsh. nmakehlp however must always be a native executable. 121 | 122 | 2007-05-03 Pat Thoyts 123 | 124 | * win/makefile.vc: Round of updating to synch up with the Tcl 125 | * win/rules.vc: core version of this build system. 126 | * win/nmakehlp.c: 127 | * win/sample.rc: Added sample resource file. 128 | 129 | 2007-02-09 Jeff Hobbs 130 | 131 | * Makefile.in, configure.in (CLEANFILES): correct cleanup handling 132 | of pkgIndex.tcl and clarify when it should be in CLEANFILES, 133 | CONFIG_CLEAN_FILES and/or BINARIES. [Bug 1655088] 134 | * configure: Updated with TEA 3.6 changes 135 | 136 | 2006-11-26 Daniel Steffen 137 | 138 | * Makefile.in: add datarootdir for autoconf-2.60. 139 | 140 | * configure: autoconf-2.59 for TEA updates. 141 | 142 | 2006-09-24 Pat Thoyts 143 | 144 | * win/nmakehlp.c: Updated for building extensions with msvc8, 145 | * win/makefile.vc: support for varying compiler options for 146 | * win/rules.vc: msvc6,7,8. 147 | 148 | 2006-01-23 Jeff Hobbs 149 | 150 | * configure.in, configure: update to TEA 3.5 151 | 152 | 2006-01-10 Daniel Steffen 153 | 154 | * generic/sample.c: 155 | * generic/tclsample.c: fix gcc4 warnings. 156 | 157 | * configure: autoconf-2.59 for TEA updates. 158 | 159 | 2005-12-01 Daniel Steffen 160 | 161 | * configure: autoconf-2.59 for TEA updates. 162 | 163 | 2005-11-29 Jeff Hobbs 164 | 165 | * configure, configure.in: update to TEA 3.4 (darwin-64, Win-64 166 | build improvements). [Bug 1369597] 167 | 168 | * pkgIndex.tcl.in: specify $PACKAGE_NAME to load 169 | 170 | 2005-11-27 Daniel Steffen 171 | 172 | * configure: autoconf-2.59 for TEA updates. 173 | 174 | 2005-09-13 Jeff Hobbs 175 | 176 | * configure, configure.in: using TEA 3.3 that has threads enabled 177 | by default. 178 | 179 | * Makefile.in: remove unnecessary private dir info 180 | 181 | 2005-07-26 Mo DeJong 182 | 183 | * Makefile.in: Remove SYSTEM_TCLSH and revert 184 | back to just using TCLSH_PROG and WISH_PROG. 185 | Remove use of SYSTEM_TCLSH at build time since 186 | this is no longer supported. 187 | * configure: Regen. 188 | * configure.in: Don't invoke TEA_BUILD_TCLSH or 189 | TEA_BUILD_WISH since these were removed from 190 | tcl.m4. This fixes up support for a build 191 | or installed version of Tcl. 192 | 193 | 2005-07-24 Mo DeJong 194 | 195 | * README: Add info about mingw and mention 196 | pkgIndex.tcl.in. 197 | * configure: Regen. 198 | * configure.in: Emit a pkgIndex.tcl in the 199 | build directory. This makes it possible to 200 | build and install sampleextension without 201 | having to run anything in a tclsh shell. 202 | A build process that depends on running 203 | the software being built will not work 204 | when cross compiling. 205 | * pkgIndex.tcl.in: Add template. 206 | 207 | 2005-07-24 Mo DeJong 208 | 209 | * Makefile.in: Subst TCLSH_PROG from PATH 210 | as SYSTEM_TCLSH and subst BUILD_TCLSH and 211 | BUILD_WISH. Use SYSTEM_TCLSH for the 212 | pkgIndex.tcl generation target. 213 | * configure: Regen. 214 | * configure.in: Invoke new TEA_BUILD_TCLSH 215 | and TEA_BUILD_WISH macros defined in tcl.m4. 216 | [Tcl bug 1160114] 217 | [Tcl patch 1244153] 218 | 219 | 2005-06-23 Daniel Steffen 220 | 221 | * Makefile.in: added commented out variable definitions for building 222 | extensions using Tk, to document exactly what needs to be added for Tk. 223 | Commented out obsolete makefile variables TCL_DEFS and TCL_LIBS. 224 | 225 | * configure: autoconf-2.59 for TEA updates. 226 | 227 | 2005-06-18 Daniel Steffen 228 | 229 | * configure: autoconf-2.59 for TEA updates. 230 | 231 | 2005-06-04 Daniel Steffen 232 | 233 | * configure: autoconf-2.59 for TEA updates. 234 | 235 | 2005-04-25 Daniel Steffen 236 | 237 | * Makefile.in: split out TCLLIBPATH from TCLSH_ENV to allow 238 | customization and overriding, add PKG_LIB_FILE dependency to 239 | pkgIndex.tcl target. 240 | * configure.in: added AC_DEFINE* descriptions to allow 241 | use with autoheader. 242 | * configure: autoconf-2.59. 243 | 244 | 2005-03-25 Jeff Hobbs 245 | 246 | * Makefile.in: add binaries dep to install-lib-binaries and 247 | install-bin-binaries. (steffen) 248 | 249 | 2005-03-24 Don Porter 250 | 251 | * Makefile.in: Corrected the `make dist` target. 252 | * configure: TEA updates. 253 | 254 | 2005-03-18 Jeff Hobbs 255 | 256 | * configure: regen with later tcl.m4. 257 | * Makefile.in: use @AR@ instead of hard-coded 'ar' to fix AIX 258 | 64-bit static build. 259 | 260 | 2005-02-08 Jeff Hobbs 261 | 262 | * configure: update for minor tcl.m4 changes. This is the first 263 | checkin that uses autoconf-2.59 (previously used 2.57). 264 | 265 | 2005-02-07 Jeff Hobbs 266 | 267 | * Makefile.in: SHLIB_LD_FLAGS no longer exported 268 | 269 | 2005-02-01 Jeff Hobbs 270 | 271 | * configure, configure.in: update for TEA 3.2. 272 | 273 | * Makefile.in: add comments about doc target. [RFE #681117] 274 | 275 | 2005-01-24 Jeff Hobbs 276 | 277 | * Makefile.in, tclconfig/tcl.m4: update to TEA 3.1, better CFLAGS 278 | * configure, configure.in: handling, evc4 and msys support. 279 | 280 | 2004-12-29 Joe English 281 | 282 | * tclconfig/tcl.m4: Do not use ${DBGX} suffix when building 283 | shared libraries [patch #1081595, TIP #34] 284 | 285 | 2004-12-02 Donal K. Fellows 286 | 287 | * generic/tclsample.c (Sha1_Cmd): Rewrote to use the Tcl_Obj API 288 | for arguments instead of the old string API. [FRQ #1076907] 289 | 290 | 2004-07-16 Jeff Hobbs 291 | 292 | * configure.in, configure, Makefile.in: Reorder configure.in for 293 | better 64-bit build configuration, replacing EXTRA_CFLAGS with 294 | CFLAGS. [Bug #874058] 295 | (install-doc, install-libraries): guard against null globs 296 | 297 | 2004-07-05 Pat Thoyts 298 | 299 | * win/rules.vc: Modified the nmake build system to support 300 | * win/makefile.vc: an specific installation directory not in the 301 | tcl install tree. eg: a site-lib directory. Some general fixups 302 | too, get the tests working again, update the version, and use the 303 | new PACKAGE_VERSION macro. 304 | 305 | 2004-07-04 Pat Thoyts 306 | 307 | * tests/all.tcl: Added a compatability function to permit running 308 | tests on tcl 8.2. 309 | 310 | 2003-12-10 Jeff Hobbs 311 | 312 | * Makefile.in: added TEA_ADD_LIBS, TEA_ADD_INCLUDES and 313 | * configure: TEA_ADD_CFLAGS to configurable parameters with 314 | * configure.in: PKG_* equivs in the Makefile. This allows the 315 | * tclconfig/tcl.m4: user to worry less about actual magic VAR names. 316 | Corrected Makefile.in to note that TEA_ADD_TCL_SOURCES requires 317 | exact file names. 318 | 319 | 2003-12-09 Jeff Hobbs 320 | 321 | * Makefile.in: added stub lib support even though sample doesn't 322 | yet create a stub library. 323 | 324 | * configure, tclconfig/tcl.m4: updated OpenBSD support based on 325 | [Patch #775246] (cassoff) 326 | 327 | 2003-12-08 Jeff Hobbs 328 | 329 | * generic/sample.c: 330 | * generic/sample.h: updated for 64-bit correctness 331 | 332 | 2003-12-05 Jeff Hobbs 333 | 334 | * configure: 335 | * configure.in: 336 | * Makefile.in (VPATH): readd $(srcdir) to front of VPATH as the 337 | first part of VPATH can get chopped off. 338 | Change .c.$(OBJEXT) rule to .c.@OBJEXT@ to support more makes. 339 | * tclconfig/tcl.m4: add TEA_ADD_STUB_SOURCES to support libstub 340 | generation and TEA_ADD_TCL_SOURCES to replace RUNTIME_SOURCES as 341 | the way the user specifies library files. 342 | 343 | 2003-12-03 Jeff Hobbs 344 | 345 | * configure: Update of TEA spec to (hopefully) simplify 346 | * configure.in: some aspects of TEA by making use of more 347 | * Makefile.in: AC 2.5x features. Use PACKAGE_NAME (instead 348 | * generic/tclsample.c: of PACKAGE) and PACKAGE_VERSION (instead of 349 | * tclconfig/tcl.m4: VERSION) arguments to AC_INIT as the TEA 350 | package name and version. 351 | Provide a version argument to TEA_INIT - starting with 3.0. 352 | Drop all use of interior shell substs that older makefiles didn't 353 | like. Use PKG_* naming convention instead. 354 | Move specification of source files and public headers into 355 | configure.in with TEA_ADD_SOURCES and TEA_ADD_HEADERS. These will 356 | be munged during ./configure into the right obj file names (no 357 | $(SOURCES:.c=.obj) needed). 358 | There is almost nothing that should be touched in Makefile.in now 359 | for the developer. May want to add a TEA_ADD_TCL_SOURCES for the 360 | RUNTIME_SOURCES that remains. 361 | Use SHLID_LD_FLAGS (instead of SHLID_LDFLAGS) as Tcl does. 362 | Only specify the user requested LDFLAGS/CFLAGS in the Makefile, 363 | don't mention the _OPTIMIZE/_DEBUG variants. 364 | 365 | * generic/sample.h: remove outdated ANSI_ARGS usage 366 | 367 | 2003-11-26 Jeff Hobbs 368 | 369 | **** tagged sampleextension-0-4 **** 370 | 371 | 2003-10-06 Jeff Hobbs 372 | 373 | * configure: regened with autoconf 2.5x tcl.m4 374 | 375 | * Makefile.in (CFLAGS_WARNING): added to base makefile 376 | 377 | 2003-10-01 Pat Thoyts 378 | 379 | * tea.pdf: Set to binary so it downloads properly under Win32 380 | 381 | * win/rules.vc: Fixed nmakehlp to find the correct Tcl or Tk 382 | * win/nmakehlp.c: version from the tcl.h header file. This will 383 | * win/makefile.vc then pick up the right libraries. 384 | 385 | 2003-07-02 Pat Thoyts 386 | 387 | * README: Added notes for the win/ build files. 388 | 389 | * win/Makefile.vc: Patch #762878 applied to provide a sample VC++ 390 | * win/rules.vc: build system. This is NOT TEA but is a useful 391 | * win/nmakehlp.c: alternative for win32 developers. 392 | 393 | 2003-04-04 Andreas Kupries 394 | 395 | * configure.in: 396 | * tclconfig/tcl.m4: Updated to newest tcl.m4, regenerated 397 | configure's. 398 | 399 | 2003-02-25 Mo DeJong 400 | 401 | * README: Add generic unix build instructions 402 | and suggest the msys + mingw build process 403 | described in tcl/win/README. 404 | * README.cygwin: Remove Cygwin specific info since 405 | this is now covered in the README file. 406 | [Tc Patch 679416] 407 | 408 | 2002-10-15 Jeff Hobbs 409 | 410 | * configure: 411 | * configure.in: move the CFLAGS definition into TEA_ENABLE_SHARED 412 | and make it pick up the env CFLAGS at configure time. 413 | 414 | 2002-07-11 Jeff Hobbs 415 | 416 | * Makefile.in: make TCL_DEFS come first in DEFS to that our DEFS 417 | would redefine the Tcl ones. 418 | 419 | * generic/tclsample.c: renamed Sha1 to Sha1_Cmd to better follow 420 | convention 421 | 422 | 2002-04-22 Jeff Hobbs 423 | 424 | * configure: regen'ed 425 | * configure.in (CLEANFILES): added pkgIndex.tcl 426 | 427 | * README.cygwin: improved notes on using cygwin. 428 | 429 | 2002-04-03 Jeff Hobbs 430 | 431 | * Makefile.in: improved use of DESTDIR in install targets. 432 | Removed need for installdirs target. 433 | Broke TCLSH_PROG into TCLSH_ENV and TCLSH_PROG with TCLSH var and 434 | added comments about TCLSH_ENV. 435 | Added default shell and gdb targets. 436 | Added comments about using RUNTIME_SOURCES var. 437 | 438 | * README.cygwin: updated notes about using mingw gcc as a compiler. 439 | 440 | * configure: 441 | * configure.in: updated to new TEA base that: prefixes all macros 442 | with TEA_* instead of SC_*; adds TEA_PREFIX, which defaults the 443 | prefix and exec_prefix values to what Tcl used; adds 444 | TEA_SETUP_COMPILER, which handles basic compiler / support program 445 | checks and simplifies the configure.in. 446 | 447 | 2002-04-01 Jeff Hobbs 448 | 449 | * Makefile.in (install-lib-binaries): ensure that binary files are 450 | installed with executable bit set (use INSTALL_PROGRAM) 451 | 452 | 2002-03-29 Jeff Hobbs 453 | 454 | * configure: regen'ed from changed tclconfig/tcl.m4 455 | 456 | * generic/tclsample.c: added #include for strlen / 457 | strcmp declarations. 458 | 459 | 2002-03-28 Jeff Hobbs 460 | 461 | * Makefile.in: moved setting TCLLIBPATH to the test target because 462 | that is where it is needed, added a little doc about it. 463 | 464 | * configure: 465 | * configure.in: BUILD_${PACKAGE} had to be static BUILD_sample in 466 | AC_DEFINE because autoconf wasn't substituting ${PACKAGE}. 467 | 468 | * tests/all.tcl: added message about starting pwd 469 | 470 | 2002-03-27 Jeff Hobbs 471 | 472 | * Makefile.in (TCLSH_PROG): moved and updated env var definitions 473 | to have tclsh work from build dir. Removed TCL_EXTRA_CFLAGS, 474 | TCL_LD_FLAGS, TCL_SHLIB_LD_LIBS, TCL_DBGX, TCL_STUB_LIB_FILE, 475 | TCL_STUB_LIB_SPEC as they aren't needed (configure acquires all 476 | that info for us). TCL_LIBS is also not needed, but left in as a 477 | reference to the libs Tcl used. 478 | 479 | * configure: regen based on updated tclconfig/tcl.m4 480 | * configure.in: moved the SHLIB_LD_LIBS magic into 481 | tclconfig/tcl.m4 and noted where users can modify (SHLIB_LD_)LIBS. 482 | 483 | 2002-03-20 Jeff Hobbs 484 | 485 | * Makefile.in (install-binaries): corrected if shell error 486 | [Bug #532557] (virden) 487 | 488 | 2002-03-19 Jeff Hobbs 489 | 490 | * README: 491 | * mkIndex.tcl.in (removed): removed the need for this script by 492 | simplifying the default install structure to use pkglibdir for the 493 | main dynamic library file generated. 494 | 495 | * configure: 496 | * configure.in: use double eval on the ${PACKAGE}_LIB_FILE to 497 | substitute the ${DBGX} variable. 498 | Remove output of the mkIndex.tcl script. 499 | 500 | * Makefile.in: added pkgIndex.tcl to binaries dependencies. 501 | Removed use of mkIndex.tcl script. Simple pkgIndex.tcl target 502 | added and install-lib-binaries modified to use pkglibdir instead 503 | of bindir and libdir directories. 504 | 505 | 2002-03-12 Jeff Hobbs 506 | 507 | * configure: regenerated 508 | * configure.in: removed pulling (UN)SHARED_LIB_SUFFIX from 509 | tclConfig.sh as these are defined by SC_CONFIG_CFLAGS. 510 | 511 | * Makefile.in (TCLSH_PROG): added a viable TCL_LIBRARY for when 512 | the TCLSH_PROG is a built, but not installed, executable. 513 | (install-binaries, test, LIB_FILE): use $($(PACKAGE)_LIB_FILE) 514 | instead of directly referencing package name to reduce number of 515 | lines that need changing. 516 | (dist): removed install of no longer existent tclconfig/config.* 517 | 518 | 2002-03-11 Jeff Hobbs 519 | 520 | * Makefile.in: 521 | * doc/sha1.n: moved from sha1.n 522 | * generic/sample.c: moved from sample.c 523 | * generic/sample.h: moved from sample.h 524 | * generic/tclsample.c: moved from tclsample.c 525 | 526 | 2002-03-06 Jeff Hobbs 527 | 528 | * Makefile.in: add EXTRA_SOURCES, WIN_SOURCES, UNIX_SOURCES 529 | example lines, remove $(sample_LIB_FILE)_OBJECTS problematic 530 | macro, move lib_BINARIES and BINARIES as they don't need editing. 531 | Replace $(mkinstalldirs) with "mkdir -p", added $(srcdir)/unix to 532 | VPATH, removed inclusion of tclconfig/installFile.tcl and 533 | tclconfig/mkinstalldirs in dist: target. 534 | 535 | * aclocal.m4: added comments 536 | 537 | 2002-03-05 Jeff Hobbs 538 | 539 | * Makefile.in: removed unused @vars@. Cleaned up targets. Added 540 | dist and dist-clean generic targets. Improved use of OBJEXT. 541 | 542 | * configure.in: bumped package to 0.3, cleaned up macro usage. 543 | 544 | * README: 545 | * README.cygwin: 546 | * aclocal.m4: 547 | * configure (new): 548 | * install-sh, mkinstalldirs, tcl.m4 (removed): complete revamp to 549 | use the tclconfig updated TEA module 550 | 551 | * exampleA.c, sample.c: 552 | * exampleA.h, sample.h: 553 | * tclexampleA.c, tclsample.c: s/exampleA/sample/g 554 | 555 | 2001-05-21 Jeff Hobbs 556 | 557 | * tcl.m4: 419812 558 | 559 | 2000-06-26 Mike Thomas 560 | 561 | * Makefile.in: Changed TCLTESTARGS to TESTFLAGS in test: target. 562 | 563 | 2000-02-03 Mike Thomas 564 | 565 | * tests/: Added tests subdirectory with sample test files 566 | * Makefile.in: Added test target to Makefile. 567 | * configure.in: Added hooks for when we later move some of the config 568 | files to a subdirectory. 569 | 570 | 2000-02-02 Mike Thomas 571 | 572 | * configure.in: 573 | * Makefile.in: Applied patch from Andreas Kupries to fix install 574 | problems when building static libraries. 575 | 576 | 2000-01-24 Mike Thomas 577 | 578 | * tcl.m4: Look for CYGWIN_98 and CYGWIN_95 environments, not just 579 | CYGWIN_NT. Also search for executables with the $EXEEXT extension 580 | in SC_PROG_TCLSH and SC_PROG_WISH so that we don't pick up MS VS 581 | junk files. 582 | * configure.in: Changes to support building on Win 95/98 using 583 | the cygwin environment. 584 | -------------------------------------------------------------------------------- /win/nmakehlp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ---------------------------------------------------------------------------- 3 | * nmakehlp.c -- 4 | * 5 | * This is used to fix limitations within nmake and the environment. 6 | * 7 | * Copyright (c) 2002 by David Gravereaux. 8 | * Copyright (c) 2006 by Pat Thoyts 9 | * 10 | * See the file "license.terms" for information on usage and redistribution of 11 | * this file, and for a DISCLAIMER OF ALL WARRANTIES. 12 | * 13 | * ---------------------------------------------------------------------------- 14 | * RCS: @(#) $Id$ 15 | * ---------------------------------------------------------------------------- 16 | */ 17 | 18 | #define _CRT_SECURE_NO_DEPRECATE 19 | #include 20 | #define NO_SHLWAPI_GDI 21 | #define NO_SHLWAPI_STREAM 22 | #define NO_SHLWAPI_REG 23 | #include 24 | #pragma comment (lib, "user32.lib") 25 | #pragma comment (lib, "kernel32.lib") 26 | #pragma comment (lib, "shlwapi.lib") 27 | #include 28 | #include 29 | 30 | /* 31 | * This library is required for x64 builds with _some_ versions of MSVC 32 | */ 33 | #if defined(_M_IA64) || defined(_M_AMD64) 34 | #if _MSC_VER >= 1400 && _MSC_VER < 1500 35 | #pragma comment(lib, "bufferoverflowU") 36 | #endif 37 | #endif 38 | 39 | /* ISO hack for dumb VC++ */ 40 | #ifdef _MSC_VER 41 | #define snprintf _snprintf 42 | #endif 43 | 44 | 45 | 46 | /* protos */ 47 | 48 | int CheckForCompilerFeature(const char *option); 49 | int CheckForLinkerFeature(const char *option); 50 | int IsIn(const char *string, const char *substring); 51 | int GrepForDefine(const char *file, const char *string); 52 | int SubstituteFile(const char *substs, const char *filename); 53 | int QualifyPath(const char *path); 54 | const char * GetVersionFromFile(const char *filename, const char *match); 55 | DWORD WINAPI ReadFromPipe(LPVOID args); 56 | 57 | /* globals */ 58 | 59 | #define CHUNK 25 60 | #define STATICBUFFERSIZE 1000 61 | typedef struct { 62 | HANDLE pipe; 63 | char buffer[STATICBUFFERSIZE]; 64 | } pipeinfo; 65 | 66 | pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'}; 67 | pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'}; 68 | 69 | /* 70 | * exitcodes: 0 == no, 1 == yes, 2 == error 71 | */ 72 | 73 | int 74 | main( 75 | int argc, 76 | char *argv[]) 77 | { 78 | char msg[300]; 79 | DWORD dwWritten; 80 | int chars; 81 | 82 | /* 83 | * Make sure children (cl.exe and link.exe) are kept quiet. 84 | */ 85 | 86 | SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); 87 | 88 | /* 89 | * Make sure the compiler and linker aren't effected by the outside world. 90 | */ 91 | 92 | SetEnvironmentVariable("CL", ""); 93 | SetEnvironmentVariable("LINK", ""); 94 | 95 | if (argc > 1 && *argv[1] == '-') { 96 | switch (*(argv[1]+1)) { 97 | case 'c': 98 | if (argc != 3) { 99 | chars = snprintf(msg, sizeof(msg) - 1, 100 | "usage: %s -c \n" 101 | "Tests for whether cl.exe supports an option\n" 102 | "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); 103 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, 104 | &dwWritten, NULL); 105 | return 2; 106 | } 107 | return CheckForCompilerFeature(argv[2]); 108 | case 'l': 109 | if (argc != 3) { 110 | chars = snprintf(msg, sizeof(msg) - 1, 111 | "usage: %s -l \n" 112 | "Tests for whether link.exe supports an option\n" 113 | "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); 114 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, 115 | &dwWritten, NULL); 116 | return 2; 117 | } 118 | return CheckForLinkerFeature(argv[2]); 119 | case 'f': 120 | if (argc == 2) { 121 | chars = snprintf(msg, sizeof(msg) - 1, 122 | "usage: %s -f \n" 123 | "Find a substring within another\n" 124 | "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); 125 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, 126 | &dwWritten, NULL); 127 | return 2; 128 | } else if (argc == 3) { 129 | /* 130 | * If the string is blank, there is no match. 131 | */ 132 | 133 | return 0; 134 | } else { 135 | return IsIn(argv[2], argv[3]); 136 | } 137 | case 'g': 138 | if (argc == 2) { 139 | chars = snprintf(msg, sizeof(msg) - 1, 140 | "usage: %s -g \n" 141 | "grep for a #define\n" 142 | "exitcodes: integer of the found string (no decimals)\n", 143 | argv[0]); 144 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, 145 | &dwWritten, NULL); 146 | return 2; 147 | } 148 | return GrepForDefine(argv[2], argv[3]); 149 | case 's': 150 | if (argc == 2) { 151 | chars = snprintf(msg, sizeof(msg) - 1, 152 | "usage: %s -s \n" 153 | "Perform a set of string map type substutitions on a file\n" 154 | "exitcodes: 0\n", 155 | argv[0]); 156 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, 157 | &dwWritten, NULL); 158 | return 2; 159 | } 160 | return SubstituteFile(argv[2], argv[3]); 161 | case 'V': 162 | if (argc != 4) { 163 | chars = snprintf(msg, sizeof(msg) - 1, 164 | "usage: %s -V filename matchstring\n" 165 | "Extract a version from a file:\n" 166 | "eg: pkgIndex.tcl \"package ifneeded http\"", 167 | argv[0]); 168 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, 169 | &dwWritten, NULL); 170 | return 0; 171 | } 172 | printf("%s\n", GetVersionFromFile(argv[2], argv[3])); 173 | return 0; 174 | case 'Q': 175 | if (argc != 3) { 176 | chars = snprintf(msg, sizeof(msg) - 1, 177 | "usage: %s -q path\n" 178 | "Emit the fully qualified path\n" 179 | "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); 180 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, 181 | &dwWritten, NULL); 182 | return 2; 183 | } 184 | return QualifyPath(argv[2]); 185 | } 186 | } 187 | chars = snprintf(msg, sizeof(msg) - 1, 188 | "usage: %s -c|-l|-f|-g|-V|-s|-Q ...\n" 189 | "This is a little helper app to equalize shell differences between WinNT and\n" 190 | "Win9x and get nmake.exe to accomplish its job.\n", 191 | argv[0]); 192 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); 193 | return 2; 194 | } 195 | 196 | int 197 | CheckForCompilerFeature( 198 | const char *option) 199 | { 200 | STARTUPINFO si; 201 | PROCESS_INFORMATION pi; 202 | SECURITY_ATTRIBUTES sa; 203 | DWORD threadID; 204 | char msg[300]; 205 | BOOL ok; 206 | HANDLE hProcess, h, pipeThreads[2]; 207 | char cmdline[100]; 208 | 209 | hProcess = GetCurrentProcess(); 210 | 211 | ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); 212 | ZeroMemory(&si, sizeof(STARTUPINFO)); 213 | si.cb = sizeof(STARTUPINFO); 214 | si.dwFlags = STARTF_USESTDHANDLES; 215 | si.hStdInput = INVALID_HANDLE_VALUE; 216 | 217 | ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); 218 | sa.nLength = sizeof(SECURITY_ATTRIBUTES); 219 | sa.lpSecurityDescriptor = NULL; 220 | sa.bInheritHandle = FALSE; 221 | 222 | /* 223 | * Create a non-inheritible pipe. 224 | */ 225 | 226 | CreatePipe(&Out.pipe, &h, &sa, 0); 227 | 228 | /* 229 | * Dupe the write side, make it inheritible, and close the original. 230 | */ 231 | 232 | DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE, 233 | DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); 234 | 235 | /* 236 | * Same as above, but for the error side. 237 | */ 238 | 239 | CreatePipe(&Err.pipe, &h, &sa, 0); 240 | DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE, 241 | DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); 242 | 243 | /* 244 | * Base command line. 245 | */ 246 | 247 | lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X -Fp.\\_junk.pch "); 248 | 249 | /* 250 | * Append our option for testing 251 | */ 252 | 253 | lstrcat(cmdline, option); 254 | 255 | /* 256 | * Filename to compile, which exists, but is nothing and empty. 257 | */ 258 | 259 | lstrcat(cmdline, " .\\nul"); 260 | 261 | ok = CreateProcess( 262 | NULL, /* Module name. */ 263 | cmdline, /* Command line. */ 264 | NULL, /* Process handle not inheritable. */ 265 | NULL, /* Thread handle not inheritable. */ 266 | TRUE, /* yes, inherit handles. */ 267 | DETACHED_PROCESS, /* No console for you. */ 268 | NULL, /* Use parent's environment block. */ 269 | NULL, /* Use parent's starting directory. */ 270 | &si, /* Pointer to STARTUPINFO structure. */ 271 | &pi); /* Pointer to PROCESS_INFORMATION structure. */ 272 | 273 | if (!ok) { 274 | DWORD err = GetLastError(); 275 | int chars = snprintf(msg, sizeof(msg) - 1, 276 | "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err); 277 | 278 | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS| 279 | FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars], 280 | (300-chars), 0); 281 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg,lstrlen(msg), &err,NULL); 282 | return 2; 283 | } 284 | 285 | /* 286 | * Close our references to the write handles that have now been inherited. 287 | */ 288 | 289 | CloseHandle(si.hStdOutput); 290 | CloseHandle(si.hStdError); 291 | 292 | WaitForInputIdle(pi.hProcess, 5000); 293 | CloseHandle(pi.hThread); 294 | 295 | /* 296 | * Start the pipe reader threads. 297 | */ 298 | 299 | pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID); 300 | pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID); 301 | 302 | /* 303 | * Block waiting for the process to end. 304 | */ 305 | 306 | WaitForSingleObject(pi.hProcess, INFINITE); 307 | CloseHandle(pi.hProcess); 308 | 309 | /* 310 | * Wait for our pipe to get done reading, should it be a little slow. 311 | */ 312 | 313 | WaitForMultipleObjects(2, pipeThreads, TRUE, 500); 314 | CloseHandle(pipeThreads[0]); 315 | CloseHandle(pipeThreads[1]); 316 | 317 | /* 318 | * Look for the commandline warning code in both streams. 319 | * - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002. 320 | */ 321 | 322 | return !(strstr(Out.buffer, "D4002") != NULL 323 | || strstr(Err.buffer, "D4002") != NULL 324 | || strstr(Out.buffer, "D9002") != NULL 325 | || strstr(Err.buffer, "D9002") != NULL 326 | || strstr(Out.buffer, "D2021") != NULL 327 | || strstr(Err.buffer, "D2021") != NULL); 328 | } 329 | 330 | int 331 | CheckForLinkerFeature( 332 | const char *option) 333 | { 334 | STARTUPINFO si; 335 | PROCESS_INFORMATION pi; 336 | SECURITY_ATTRIBUTES sa; 337 | DWORD threadID; 338 | char msg[300]; 339 | BOOL ok; 340 | HANDLE hProcess, h, pipeThreads[2]; 341 | char cmdline[100]; 342 | 343 | hProcess = GetCurrentProcess(); 344 | 345 | ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); 346 | ZeroMemory(&si, sizeof(STARTUPINFO)); 347 | si.cb = sizeof(STARTUPINFO); 348 | si.dwFlags = STARTF_USESTDHANDLES; 349 | si.hStdInput = INVALID_HANDLE_VALUE; 350 | 351 | ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); 352 | sa.nLength = sizeof(SECURITY_ATTRIBUTES); 353 | sa.lpSecurityDescriptor = NULL; 354 | sa.bInheritHandle = TRUE; 355 | 356 | /* 357 | * Create a non-inheritible pipe. 358 | */ 359 | 360 | CreatePipe(&Out.pipe, &h, &sa, 0); 361 | 362 | /* 363 | * Dupe the write side, make it inheritible, and close the original. 364 | */ 365 | 366 | DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE, 367 | DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); 368 | 369 | /* 370 | * Same as above, but for the error side. 371 | */ 372 | 373 | CreatePipe(&Err.pipe, &h, &sa, 0); 374 | DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE, 375 | DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); 376 | 377 | /* 378 | * Base command line. 379 | */ 380 | 381 | lstrcpy(cmdline, "link.exe -nologo "); 382 | 383 | /* 384 | * Append our option for testing. 385 | */ 386 | 387 | lstrcat(cmdline, option); 388 | 389 | ok = CreateProcess( 390 | NULL, /* Module name. */ 391 | cmdline, /* Command line. */ 392 | NULL, /* Process handle not inheritable. */ 393 | NULL, /* Thread handle not inheritable. */ 394 | TRUE, /* yes, inherit handles. */ 395 | DETACHED_PROCESS, /* No console for you. */ 396 | NULL, /* Use parent's environment block. */ 397 | NULL, /* Use parent's starting directory. */ 398 | &si, /* Pointer to STARTUPINFO structure. */ 399 | &pi); /* Pointer to PROCESS_INFORMATION structure. */ 400 | 401 | if (!ok) { 402 | DWORD err = GetLastError(); 403 | int chars = snprintf(msg, sizeof(msg) - 1, 404 | "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err); 405 | 406 | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS| 407 | FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars], 408 | (300-chars), 0); 409 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg,lstrlen(msg), &err,NULL); 410 | return 2; 411 | } 412 | 413 | /* 414 | * Close our references to the write handles that have now been inherited. 415 | */ 416 | 417 | CloseHandle(si.hStdOutput); 418 | CloseHandle(si.hStdError); 419 | 420 | WaitForInputIdle(pi.hProcess, 5000); 421 | CloseHandle(pi.hThread); 422 | 423 | /* 424 | * Start the pipe reader threads. 425 | */ 426 | 427 | pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID); 428 | pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID); 429 | 430 | /* 431 | * Block waiting for the process to end. 432 | */ 433 | 434 | WaitForSingleObject(pi.hProcess, INFINITE); 435 | CloseHandle(pi.hProcess); 436 | 437 | /* 438 | * Wait for our pipe to get done reading, should it be a little slow. 439 | */ 440 | 441 | WaitForMultipleObjects(2, pipeThreads, TRUE, 500); 442 | CloseHandle(pipeThreads[0]); 443 | CloseHandle(pipeThreads[1]); 444 | 445 | /* 446 | * Look for the commandline warning code in the stderr stream. 447 | */ 448 | 449 | return !(strstr(Out.buffer, "LNK1117") != NULL || 450 | strstr(Err.buffer, "LNK1117") != NULL || 451 | strstr(Out.buffer, "LNK4044") != NULL || 452 | strstr(Err.buffer, "LNK4044") != NULL); 453 | } 454 | 455 | DWORD WINAPI 456 | ReadFromPipe( 457 | LPVOID args) 458 | { 459 | pipeinfo *pi = (pipeinfo *) args; 460 | char *lastBuf = pi->buffer; 461 | DWORD dwRead; 462 | BOOL ok; 463 | 464 | again: 465 | if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) { 466 | CloseHandle(pi->pipe); 467 | return (DWORD)-1; 468 | } 469 | ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L); 470 | if (!ok || dwRead == 0) { 471 | CloseHandle(pi->pipe); 472 | return 0; 473 | } 474 | lastBuf += dwRead; 475 | goto again; 476 | 477 | return 0; /* makes the compiler happy */ 478 | } 479 | 480 | int 481 | IsIn( 482 | const char *string, 483 | const char *substring) 484 | { 485 | return (strstr(string, substring) != NULL); 486 | } 487 | 488 | /* 489 | * Find a specified #define by name. 490 | * 491 | * If the line is '#define TCL_VERSION "8.5"', it returns 85 as the result. 492 | */ 493 | 494 | int 495 | GrepForDefine( 496 | const char *file, 497 | const char *string) 498 | { 499 | char s1[51], s2[51], s3[51]; 500 | FILE *f = fopen(file, "rt"); 501 | 502 | if (f == NULL) { 503 | return 0; 504 | } 505 | 506 | do { 507 | int r = fscanf(f, "%50s", s1); 508 | 509 | if (r == 1 && !strcmp(s1, "#define")) { 510 | /* 511 | * Get next two words. 512 | */ 513 | 514 | r = fscanf(f, "%50s %50s", s2, s3); 515 | if (r != 2) { 516 | continue; 517 | } 518 | 519 | /* 520 | * Is the first word what we're looking for? 521 | */ 522 | 523 | if (!strcmp(s2, string)) { 524 | double d1; 525 | 526 | fclose(f); 527 | 528 | /* 529 | * Add 1 past first double quote char. "8.5" 530 | */ 531 | 532 | d1 = atof(s3 + 1); /* 8.5 */ 533 | while (floor(d1) != d1) { 534 | d1 *= 10.0; 535 | } 536 | return ((int) d1); /* 85 */ 537 | } 538 | } 539 | } while (!feof(f)); 540 | 541 | fclose(f); 542 | return 0; 543 | } 544 | 545 | /* 546 | * GetVersionFromFile -- 547 | * Looks for a match string in a file and then returns the version 548 | * following the match where a version is anything acceptable to 549 | * package provide or package ifneeded. 550 | */ 551 | 552 | const char * 553 | GetVersionFromFile( 554 | const char *filename, 555 | const char *match) 556 | { 557 | size_t cbBuffer = 100; 558 | static char szBuffer[100]; 559 | char *szResult = NULL; 560 | FILE *fp = fopen(filename, "rt"); 561 | 562 | if (fp != NULL) { 563 | /* 564 | * Read data until we see our match string. 565 | */ 566 | 567 | while (fgets(szBuffer, cbBuffer, fp) != NULL) { 568 | LPSTR p, q; 569 | 570 | p = strstr(szBuffer, match); 571 | if (p != NULL) { 572 | /* 573 | * Skip to first digit. 574 | */ 575 | 576 | while (*p && !isdigit(*p)) { 577 | ++p; 578 | } 579 | 580 | /* 581 | * Find ending whitespace. 582 | */ 583 | 584 | q = p; 585 | while (*q && (isalnum(*q) || *q == '.')) { 586 | ++q; 587 | } 588 | 589 | memcpy(szBuffer, p, q - p); 590 | szBuffer[q-p] = 0; 591 | szResult = szBuffer; 592 | break; 593 | } 594 | } 595 | fclose(fp); 596 | } 597 | return szResult; 598 | } 599 | 600 | /* 601 | * List helpers for the SubstituteFile function 602 | */ 603 | 604 | typedef struct list_item_t { 605 | struct list_item_t *nextPtr; 606 | char * key; 607 | char * value; 608 | } list_item_t; 609 | 610 | /* insert a list item into the list (list may be null) */ 611 | static list_item_t * 612 | list_insert(list_item_t **listPtrPtr, const char *key, const char *value) 613 | { 614 | list_item_t *itemPtr = malloc(sizeof(list_item_t)); 615 | if (itemPtr) { 616 | itemPtr->key = strdup(key); 617 | itemPtr->value = strdup(value); 618 | itemPtr->nextPtr = NULL; 619 | 620 | while(*listPtrPtr) { 621 | listPtrPtr = &(*listPtrPtr)->nextPtr; 622 | } 623 | *listPtrPtr = itemPtr; 624 | } 625 | return itemPtr; 626 | } 627 | 628 | static void 629 | list_free(list_item_t **listPtrPtr) 630 | { 631 | list_item_t *tmpPtr, *listPtr = *listPtrPtr; 632 | while (listPtr) { 633 | tmpPtr = listPtr; 634 | listPtr = listPtr->nextPtr; 635 | free(tmpPtr->key); 636 | free(tmpPtr->value); 637 | free(tmpPtr); 638 | } 639 | } 640 | 641 | /* 642 | * SubstituteFile -- 643 | * As windows doesn't provide anything useful like sed and it's unreliable 644 | * to use the tclsh you are building against (consider x-platform builds - 645 | * eg compiling AMD64 target from IX86) we provide a simple substitution 646 | * option here to handle autoconf style substitutions. 647 | * The substitution file is whitespace and line delimited. The file should 648 | * consist of lines matching the regular expression: 649 | * \s*\S+\s+\S*$ 650 | * 651 | * Usage is something like: 652 | * nmakehlp -S << $** > $@ 653 | * @PACKAGE_NAME@ $(PACKAGE_NAME) 654 | * @PACKAGE_VERSION@ $(PACKAGE_VERSION) 655 | * << 656 | */ 657 | 658 | int 659 | SubstituteFile( 660 | const char *substitutions, 661 | const char *filename) 662 | { 663 | size_t cbBuffer = 1024; 664 | static char szBuffer[1024], szCopy[1024]; 665 | char *szResult = NULL; 666 | list_item_t *substPtr = NULL; 667 | FILE *fp, *sp; 668 | 669 | fp = fopen(filename, "rt"); 670 | if (fp != NULL) { 671 | 672 | /* 673 | * Build a list of substutitions from the first filename 674 | */ 675 | 676 | sp = fopen(substitutions, "rt"); 677 | if (sp != NULL) { 678 | while (fgets(szBuffer, cbBuffer, sp) != NULL) { 679 | char *ks, *ke, *vs, *ve; 680 | ks = szBuffer; 681 | while (ks && *ks && isspace(*ks)) ++ks; 682 | ke = ks; 683 | while (ke && *ke && !isspace(*ke)) ++ke; 684 | vs = ke; 685 | while (vs && *vs && isspace(*vs)) ++vs; 686 | ve = vs; 687 | while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve; 688 | *ke = 0, *ve = 0; 689 | list_insert(&substPtr, ks, vs); 690 | } 691 | fclose(sp); 692 | } 693 | 694 | /* debug: dump the list */ 695 | #ifdef _DEBUG 696 | { 697 | int n = 0; 698 | list_item_t *p = NULL; 699 | for (p = substPtr; p != NULL; p = p->nextPtr, ++n) { 700 | fprintf(stderr, "% 3d '%s' => '%s'\n", n, p->key, p->value); 701 | } 702 | } 703 | #endif 704 | 705 | /* 706 | * Run the substitutions over each line of the input 707 | */ 708 | 709 | while (fgets(szBuffer, cbBuffer, fp) != NULL) { 710 | list_item_t *p = NULL; 711 | for (p = substPtr; p != NULL; p = p->nextPtr) { 712 | char *m = strstr(szBuffer, p->key); 713 | if (m) { 714 | char *cp, *op, *sp; 715 | cp = szCopy; 716 | op = szBuffer; 717 | while (op != m) *cp++ = *op++; 718 | sp = p->value; 719 | while (sp && *sp) *cp++ = *sp++; 720 | op += strlen(p->key); 721 | while (*op) *cp++ = *op++; 722 | *cp = 0; 723 | memcpy(szBuffer, szCopy, sizeof(szCopy)); 724 | } 725 | } 726 | printf(szBuffer); 727 | } 728 | 729 | list_free(&substPtr); 730 | } 731 | fclose(fp); 732 | return 0; 733 | } 734 | 735 | /* 736 | * QualifyPath -- 737 | * 738 | * This composes the current working directory with a provided path 739 | * and returns the fully qualified and normalized path. 740 | * Mostly needed to setup paths for testing. 741 | */ 742 | 743 | int 744 | QualifyPath( 745 | const char *szPath) 746 | { 747 | char szCwd[MAX_PATH + 1]; 748 | char szTmp[MAX_PATH + 1]; 749 | char *p; 750 | GetCurrentDirectory(MAX_PATH, szCwd); 751 | while ((p = strchr(szPath, '/')) && *p) 752 | *p = '\\'; 753 | PathCombine(szTmp, szCwd, szPath); 754 | PathCanonicalize(szCwd, szTmp); 755 | printf("%s\n", szCwd); 756 | return 0; 757 | } 758 | 759 | /* 760 | * Local variables: 761 | * mode: c 762 | * c-basic-offset: 4 763 | * fill-column: 78 764 | * indent-tabs-mode: t 765 | * tab-width: 8 766 | * End: 767 | */ 768 | --------------------------------------------------------------------------------