:TITLE: Building Libraries of procs - pkg_mkIndex, unknown, info library
;#
;# RCSID: $Header: /home/cvs/TclTutor3/lesson/Tcl_English/Tcl_English31.lsn,v 1.2 2010/12/22 15:53:19 clif Exp $
;# Copyright (c) 1995 Clif Flynt
;# 9300 Fleming Rd.
;# Dexter, MI  48130
;# clif@cflynt.com
;# See file "NOTICE" for licensing terms.
;#
::CMD:: if {([info exists tcl_platform])} {
  switch $tcl_platform(platform) {
    unix        {
                set Tutor(lsn.codeMod) {
                }
        }
    windows     {
                set Tutor(lsn.codeMod) {
    		    {global env}
		    {regsub -all {\\} $env(COMSPEC) {/} cspec}
		    {regsub {cat} $line " $cspec /C type" line}
                    {if {[glob -nocomplain C:/temp] != ""} {
                      regsub "/tmp" $line {C:/temp} line
		    }
		    }
                    {if {[glob -nocomplain C:/windows/temp] != ""} {
                      regsub "/tmp" $line {C:/windows/temp} line
		    }
		    }
                    {if {[glob -nocomplain C:/winnt/temp] != ""} {
                      regsub "/tmp" $line {C:/winnt/temp} line
		    }
		    }
                }         
        }
    mac         {
                set Tutor(lsn.codeMod) {
		}
                }
    default     {
                puts "I don't recognize the platform: $tcl_platform(platform)"
                puts "Can't set platform specific parameters"
                }
    } 
  }

:LESSON_TEXT_START_LEVEL 0:
Tcl provides a library facility for finding procs when they are
needed.  The libraries in Tcl are referred to as packages.  A package
can contain either compiled code, Tcl scripts or both.  It may consist
of a single file, or multiple files.
<P>
Some packages (like http support) are provided in the base Tcl distribution,
and many more are included in the tcllib collection.  (See <B>tcllib.sourceforge.net</B>)
<P>
To use a package 
 <OL>
   <LI> Make certain that the <CODE>auto_path</CODE> global variable includes
   the path to the package you wish to include.  The standard Tcl distributions
   include the proper paths by default.
   <LI> Include a line like this in the application that uses a package:
<BR>
<CODE>package require <I>nameOfPackage</I></CODE>
<BR>
You script will need a separate <CODE>package require</CODE> command
for each package you wish to include.
 </OL>
<P>
To create a package, you'll need
<OL>
  <LI> to include a <CODE>package provide</CODE> command like
  <BR> package provide <I>nameOfPackage revisionNumber</I>
  <BR> in each file that's included in the package
  <LI> create a <CODE>pkgIndex.tcl</CODE> file to describe the files in the package.<BR>
  This can be done with the <CODE>pkg_mkIndex</CODE> command.
</OL>
<P>
<DL>
<B><DT>package require</B> <I>name ?revision?</I>
<DD>Tells the interpreter to find a package with the given name and
optional revision number.  If the revision number is absent, the largest
revision available is used.

<B><DT>package provide </B> <I>name revision</I>
<DD>Declares that this file provides an implementation of a specific
revision of a package.  A file may include only one <CODE>package provide</CODE>
command.

<B><DT>pkg_mkIndex</B> <I>libdir file1 ... filen</I>
<DD>Creates an index file (pkgIndex.tcl) in <I>libdir</I> from the source
code modules listed as <I>file1 - filen</I>.  Each proc in the files
will be listed in the index file, with a reference to the source code
module that contains it.
<P>
The file descriptors may be any number of strings using the same
format as arguments to the <B>glob</B> command.
<P>
<B><DT>info library</B>
<DD>Returns the name of the library directory in which the standard
Tcl scripts are stored.
<P>
Tcl procs that are in files in the Tcl library directory are loaded
automatically when they are executed.  
<P>
Tcl expects to find init.tcl in the default library location,
defined when the Tcl interpreter is built.  This path can be
changed by setting the environment variable TCL_LIBRARY.
<B><DT>unknown</B> <I>args</I>
<DD>This proc is called by the interpreter when it encounters a
command that can be parsed, but the command name is not in the tables.
Unknown attempts the following steps to execute the command
<UL COMPACT>
<LI> Checks the index in the directories listed in auto_path to see
if the proc exists in a file.  If the proc is found, the script is loaded
with the <B>auto_load</B> proc, and the proc is executed.
<LI>If the interpreter is running interactively, Tcl attempts to <B>exec</B>
the command with the <B>auto_exec</B> proc.
<LI>If the command is a unique prefix to a Tcl command, <B>unknown</B>
completes the command name, and executes that command
</UL>
</DL>
:TEXT_END:

:LESSON_TEXT_START_LEVEL 1:
Tcl supports grouping multiple procedures or compiled "C" code modules
into a single entity referred to as a <I>package</I>.
A package may consist of a single file, multiple files or a mix of
compiled and Tcl script files.
<P>
Some packages (like http and Tk) are provided in the base Tcl distribution,
and many more are included in the tcllib collection.  (See <B>tcllib.sourceforge.net</B>)
<P>
To access a package from a script:
 <OL>
   <LI> Make certain that the <CODE>auto_path</CODE> global variable includes
   the path to the package you wish to include.  The standard Tcl distributions
   include the proper paths by default.
   <LI> Include a line like this in the application that uses a package:
<BR>
<CODE>package require <I>nameOfPackage</I></CODE>
<BR>
You script will need a separate <CODE>package require</CODE> command
for each package you wish to include.
 </OL>
<P>
To create a package, you'll need
<OL>
  <LI> to include a <CODE>package provide</CODE> command like
  <BR> package provide <I>nameOfPackage revisionNumber</I>
  <BR> in each file that's included in the package
  <LI> create a <CODE>pkgIndex.tcl</CODE> file to describe the files in the package.<BR>
  This can be done with the <CODE>pkg_mkIndex</CODE> command.
</OL>
<P>
<DL>
<B><DT>package require</B> <I>name ?revision?</I>
<DD>Tells the interpreter to find a package with the given name and
optional revision number.  If the revision number is absent, the largest
revision available is used.

<B><DT>package provide </B> <I>name revision</I>
<DD>Declares that this file provides an implementation of a specific
revision of a package.  A file may include only one <CODE>package provide</CODE>
command.

<B><DT>pkg_mkIndex</B> <I>libdir file1 ... filen</I>
<DD>Creates an index file (pkgIndex.tcl) in <I>libdir</I> from the source
code modules listed as <I>file1 - filen</I>.  Each proc in the files
will be listed in the index file, with a reference to the source code
module that contains it.
<P>
The file descriptors may be any number of strings using the same
format as arguments to the <B>glob</B> command.
<P>
Two other commands are related to finding packages and processing them.
Your code will not need to use these, but you may find them useful in understanding
how the system behaves.
<P>
<B><DT>info library</B>
<DD>Returns the name of the library directory in which the standard
Tcl scripts are stored.
<P>
Tcl procs that are in files in the Tcl library directory are loaded
automatically when they are executed.  
<P>
Tcl expects to find init.tcl in the default library location,
defined when the Tcl interpreter is built.  This path can be
changed by setting the environment variable TCL_LIBRARY.
<B><DT>unknown</B> <I>args</I>
<DD>This proc is called by the interpreter when it encounters a
command that can be parsed, but the command name is not in the tables.
Unknown attempts the following steps to execute the command
<UL COMPACT>
<LI> Checks the index in the directories listed in auto_path to see
if the proc exists in a file.  If the proc is found, the script is loaded
with the <B>auto_load</B> proc, and the proc is executed.
<LI>If the interpreter is running interactively, Tcl attempts to <B>exec</B>
the command with the <B>auto_exec</B> proc.
<LI>If the command is a unique prefix to a Tcl command, <B>unknown</B>
completes the command name, and executes that command
</UL>
</DL>
:TEXT_END:

:LESSON_TEXT_START_LEVEL 2: The <CODE>source</CODE> command gives a
developer a powerful tool for modularizing their code and making it
easy to maintain and re-use. 



<P> However it requires that each
application that uses the <CODE>source</CODE> command must know the
full path to each file it will source.  This creates fragile code that
relies on an underlying file system layout. 

<P> One side-effect of this
is that someone who is maintaining the support procedures cannot
re-organize them without breaking all the applications that use them.


<P> Tcl supports grouping multiple procedures or compiled "C" code
modules into a single entity referred to as a <I>package</I>. A package
may consist of a single file, multiple files or a mix of compiled code
and Tcl script files. 

<P> An application programmer can use a package
in his script without worrying about how it's been implemented or where
it's stored on the disk.  This makes life simpler for the application
programmer (one <CODE>package require</CODE> instead of a half-dozen
source  commands) as well as for the library maintainer (the freedom to
fix bugs and reorganize without needing to retain an old (perhaps bad)
set of filenames). 

<P> Some packages (like http and Tk) are provided in
the base Tcl distribution, and many more are included in the tcllib
collection.  (See <B>tcllib.sourceforge.net</B>) 

<P> To access a
package from a script:
 <OL>
   <LI> Make certain that the <CODE>auto_path</CODE> global variable includes
   the path to the package you wish to include.  The standard Tcl distributions
   include the proper paths by default.
   <LI> Include a line like this in the application that uses a package:
<BR>
<CODE>package require <I>nameOfPackage</I></CODE>
<BR>
You script will need a separate <CODE>package require</CODE> command
for each package you wish to include.
 </OL>
<P>
To create a package, you'll need
<OL>
  <LI> to include a <CODE>package provide</CODE> command like
  <BR> package provide <I>nameOfPackage revisionNumber</I>
  <BR> in each file that's included in the package
  <LI> create a <CODE>pkgIndex.tcl</CODE> file to describe the files in the package.<BR>
  This can be done with the <CODE>pkg_mkIndex</CODE> command.
</OL>
<P>
<DL>
<B><DT>package require</B> <I>name ?revision?</I>
<DD>Tells the interpreter to find a package with the given name and
optional revision number.  If the revision number is absent, the largest
revision available is used.

<B><DT>package provide </B> <I>name revision</I>
<DD>Declares that this file provides an implementation of a specific
revision of a package.  A file may include only one <CODE>package provide</CODE>
command.

<B><DT>pkg_mkIndex</B> <I>libdir file1 ... filen</I>
<DD>Creates an index file (pkgIndex.tcl) in <I>libdir</I> from the source
code modules listed as <I>file1 - filen</I>.  Each proc in the files
will be listed in the index file, with a reference to the source code
module that contains it.
<P>
The file descriptors may be any number of strings using the same
format as arguments to the <B>glob</B> command.
<P>
Two other commands are related to finding packages and processing them.
Your code will not need to use these, but you may find them useful in understanding
how the system behaves.
<P>
<B><DT>info library</B>
<DD>Returns the name of the library directory in which the standard
Tcl scripts are stored.
<P>
Tcl procs that are in files in the Tcl library directory are loaded
automatically when they are executed.  
<P>
Tcl expects to find init.tcl in the default library location,
defined when the Tcl interpreter is built.  This path can be
changed by setting the environment variable TCL_LIBRARY.
<B><DT>unknown</B> <I>args</I>
<DD>This proc is called by the interpreter when it encounters a
command that can be parsed, but the command name is not in the tables.
Unknown attempts the following steps to execute the command
<UL COMPACT>
<LI> Checks the index in the directories listed in auto_path to see
if the proc exists in a file.  If the proc is found, the script is loaded
with the <B>auto_load</B> proc, and the proc is executed.
<LI>If the interpreter is running interactively, Tcl attempts to <B>exec</B>
the command with the <B>auto_exec</B> proc.
<LI>If the command is a unique prefix to a Tcl command, <B>unknown</B>
completes the command name, and executes that command
</UL>
</DL>
:TEXT_END:

:CODE_START:
;# Set up a temporary file with a test proc.

set filename "TT_[pid].tcl"
set outfile [open "/tmp/$filename" "w"];

puts $outfile "package provide tutordemo 1.0"
puts $outfile "proc demoproc {} {"
puts $outfile "puts {Running the demoproc}"
puts $outfile "}"
close $outfile;

pkg_mkIndex /tmp $filename

# With Tcl8.3, this must come after auto_mkindex.

lappend auto_path "/tmp"

puts "procedures matching demopr before package require are: [info proc demopr*]"
package require tutordemo
puts "procedures matching demopr after package require are: [info proc demopr*]"
demoproc
puts "procedures matching demopr after using deomproc : [info proc demopr*]"

# file delete /tmp/pkgIndex
# file delete $filename 

:TEXT_END:

