\documentclass[]{article}
\usepackage{amsmath,graphicx,supertabular,hyperref,tabularx,ifthen}
\title{TIP \#216: Handling Command-Line Options in Tclsh and Wish}
\date{August 23, 2004}
\author{Arjen Markus}
\urlstyle{sf}
\setlength{\parskip}{1ex}
\setlength{\parindent}{0pt}
\def\tipversion$#1${\texttt{\$#1\$}}
\def\tiplangle#1{\ensuremath{<}}
\def\tiprangle#1{\ensuremath{>}}
\def\tipbar#1{\ensuremath{|}}
\def\tipmail#1#2{\(\langle\){\small\expandafter\url{#1@#2}}\(\rangle\)}
\ifx\pdfoutput\undefined
\newcommand{\tipimage}[2]{\typeout{Make sure you download #1.eps}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.eps}}{\includegraphics[width=0.8\textwidth]{#1.eps}}}
\newcommand{\tipxref}[1]{}
\newcommand{\tipxrefend}{}
\else
\newcommand{\tipimage}[2]{\typeout{Make sure you create #1.pdf}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.pdf}}{\includegraphics[width=0.8\textwidth]{#1.pdf}}}
\pdfcatalog{/PageMode /UseOutlines}
\newcommand{\tipxref}[1]{\pdfannotlink attr {/C [0.5 0.5 1.0] /Border [0 0 1]} goto name {#1}}
\newcommand{\tipxrefend}{\pdfendlink}
\fi
\newenvironment{tipabstract}{\begin{abstract}}{\end{abstract}}
\begin{document}\maketitle
\begin{center}\begin{tabularx}{\linewidth}{|r@{: }X|}\hline
\textbf{TIP \#216}&\textbf{Handling Command-Line Options in Tclsh and Wish}\\\hline
Author&

Arjen Markus \tipmail{arjen.markus}{wldelft.nl}
\\
Created&Monday, \(\text{23}^{\text{rd}}\) August 2004\\
Type&Project\\
Tcl Version&\(8.7\)\\
State&Draft\\
Vote&Pending\\
Version&\tipversion$Revision: 1.5 $\\
Keywords&Tcl, debugging, argument, shell\\
Post History&\\
\hline\end{tabularx}\end{center}
\thispagestyle{empty}\pagestyle{empty}
\begin{tipabstract}

Currently there is no means to add new command-line options to the standard Tcl shells, tclsh and wish, that can be handled at the script level. This hampers the development of, for instance, a scripted debugger or tracing tool, because the shell must be called with an awkward command line (stating the location of the script file implementing the facility). This TIP proposes a simple mechanism so that a command line like ``tclsh -debug myprog.tcl'' is possible. The new mechanism relies on the existing package mechanism and a few conventions. It can be implemented for the most part in Tcl.
\end{tipabstract}
\tableofcontents\setcounter{page}{0}\clearpage\pagestyle{plain}

\section{Rationale}

With Tcl 8.4 it is quite easy to create a scripted debugger --- see for instance [\url{http://wiki.tcl.tk/6007}] and [\url{http://wiki.tcl.tk.12251}] --- since this version introduced execution traces. However, it is less simple to turn that into an ``out-of-the-box'' resource: suppose its implementation file is ``debug.tcl'', residing in a directory ``\~{}/my-tcl-utils'' (or ``d:\(\backslash\)my-tcl-utils'' under Windows), then the following command-line is necessary:
\begingroup\small\begin{verbatim}
 tclsh ~/my-tcl-utils/debug.tcl myapp.tcl
\end{verbatim}
\endgroup

or under Windows:
\begingroup\small\begin{verbatim}
 tclsh d:\my-tcl-utils\debug.tcl myapp.tcl
\end{verbatim}
\endgroup

instead of the more elegant:
\begingroup\small\begin{verbatim}
 tclsh -debug myapp.tcl
\end{verbatim}
\endgroup

where some mechanism links the option ``-debug'' to the implementation file ``debug.tcl''.

An alternative method could be to make the file ``debug.tcl'' a loadable package but this requires the user to change the application: it should then load the debug package whenever the user wants to interactively debug it.

\section{Proposed Changes}

The only thing that needs to be changed in tclsh and wish (\textit{TclMain.c} and \textit{TkMain.c} respectively) or any other shell to benefit from this new feature is that just before sourcing the file given on the command-line or going into an interactive loop, is that a new procedure is called, ``HandleCmdLine'' (and some proper processing of its results).

This procedure, which will reside in \textit{init.tcl}, does the following (at least in the proposed, default, implementation):
\begin{itemize}
\item{}
it loops over the command-line arguments (in the global variable \textit{argv}): if the argument starts with ``-'', it is considered an option (and it is removed from \textit{argv}).
\item{}
the option is translated into the name of a package that gets loaded.
\item{}
if the initialisation code of the package recognises other arguments, it must remove them from the list contained in \textit{argv}.
\item{}
this continues until an argument is found that does not qualify as an option.
\end{itemize}

A simple implementation of this procedure is:
\begingroup\small\begin{verbatim}
 proc HandleCmdLine {} {
    while { [string index [lindex $::argv 0]] == "-" } {
       set pkg [string range [lindex $::argv 0] 1 end]
       package require $pkg

       set ::argv [lrange $::argv 1 end]
    }

    if { [llength $::argv] > 0 } {
       set ::argv0 [lindex $::argv 0]
       set ::argv [lrange $::argv 1 end]
    }
 }
\end{verbatim}
\endgroup

(Details like proper error handling are left out for simplicity.)

After the call to this procedure in the C code, variable \textit{argv0} must be examined to determine if the shell is to be run interactively or not.

With the proposed mechanism, tclsh or wish can be invoked with:
\begingroup\small\begin{verbatim}
 tclsh -debug myapp.tcl
\end{verbatim}
\endgroup

or:
\begingroup\small\begin{verbatim}
 tclsh -trace -out "report.out" myapp.tcl
\end{verbatim}
\endgroup

(assuming that the package trace recognises the option -out)

or:
\begingroup\small\begin{verbatim}
 wish -tkcon myapp.tcl
\end{verbatim}
\endgroup

(assuming Tkcon has been turned into a package)

\section{Reference Implementation}

None yet.

\section{Copyright}

This document is placed in the public domain.

\section{Colophon}

\textit{TIP AutoGenerator --- written by Donal K. Fellows}
\end{document}
