\documentclass[]{article}
\usepackage{amsmath,graphicx,supertabular,hyperref,tabularx,ifthen}
\title{TIP \#265: A Convenient C-side Command Option Parser for Tcl}
\date{April 03, 2006}
\author{Sam Bromley}
\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 \#265}&\textbf{A Convenient C-side Command Option Parser for Tcl}\\\hline
Author&

Sam Bromley \tipmail{sam}{sambromley.com}
\\
Created&Monday, \(\text{3}^{\text{rd}}\) April 2006\\
Type&Project\\
Tcl Version&\(8.6\)\\
State&Final\\
Vote&Done\\
Version&\tipversion$Revision: 1.7 $\\
Keywords&Command line parsing, C implementation\\
Post History&\\
\hline\end{tabularx}\end{center}
\thispagestyle{empty}\pagestyle{empty}
\begin{tipabstract}

The Tk C library provides developers with a \textit{Tk\_ParseArgv}() function that allows command line parsing of options of the ``-option'' form. Archived discussions on \url{news:comp.lang.tcl} and on the Wiki indicate that a desire for similar functionality without Tk has arisen several times in the past. This TIP presents a Tk-free implementation of \textit{Tk\_ParseArgv()} named \textbf{Tcl\_ParseArgvObj}, that developers can use to parse ``-option'' style command options in C implementations of Tcl commands using the Tcl\_Obj interface.
\end{tipabstract}
\tableofcontents\setcounter{page}{0}\clearpage\pagestyle{plain}

\section{Rationale}

While the parsing of command options can be readily accomplished on the Tcl side, a uniform method for parsing ``-option'' formed options does not exist on the C side. Many developers are familiar with the ease of use of libpopt-style command line parsing, but a similarly clean method does not currently exist in Tcl. The common approach is to use \textit{Tcl\_GetIndexFromObj}(), yet this method alone does not allow the flexibilty and ease of use of libpopt-style parsing.

One drawback of the classical \textit{Tcl\_GetIndexFromObj}()-only approach is the need to handle the specifies of your command option parsing for each unique command. This leads to significant code duplication. A libpopt-style approach is to bundle all of your parsing specifics into a single array of structures capturing the details, and then let a specific parsing routine handle the parsing of every option for you. The \textbf{Tcl\_ParseArgvObj}() routine introduced in this TIP provides this functionality, thereby allowing the removal of all parsing specifics from the command implimentation other than that necessary to describe each optional argument.

Additionally, a function \textbf{Tcl\_ParseArgsObjv} is provided to provide the functionality of \textit{Tk\_ParseArgs}() to those who desire it. A discussion in 2002 on \url{news:comp.lang.tcl} [\url{http://groups.google.com/group/comp.lang.tcl/browse_thread/thread/c4fea8f0346cf8ae/036961bf476a3b99?q=tcl_parseargv&rnum=2\#036961bf476a3b99}] indicated that this is a desired feature. Arguments against a \textbf{Tcl\_ParseArgsObjv} implementation include that it is better to do all command line parsing on the Tcl side. However, this implies writing two wrapper functions: (i) A C implementation of a Tcl command; and (ii) A Tcl wrapper that pre-parses the options before calling the C command. This can lead to significant duplication of effort when porting a large project to a Tcl enabled version. This point is particularly relevent in the context of \textbf{Tcl\_ParseArgvObj}(), as then one is not assuming that one can simply replace the main() routine with Tcl, but rather that one is truly embedding the C side in a larger system.

\textbf{Tcl\_ParseArgvObj}() offers a clean method to enable flexible command line parsing to C implementations of Tcl commands.

\section{Specification}

This document proposes adding \textbf{Tcl\_ParseArgsObjv}, whose arguments shall be:

\begin{quote}
int \textbf{Tcl\_ParseArgsObjv}(Tcl\_Interp *\textit{interp}, const Tcl\_ArgvInfo *\textit{argTable}, int *\textit{objcPtr}, Tcl\_Obj *const *\textit{objv}, Tcl\_Obj ***\textit{remainingObjv})
\end{quote}

\textbf{Note} that the count of arguments (referred to by \textit{objcPtr}) will be modified, and a modified array will be returned via \textit{remainingObjv} (and need \textbf{ckfree}ing). The input array of objects will not be modified.

\section{Reference Implementation}

A working implementation has been submitted to the Feature Request Tracker at SourceForge [\url{https://sourceforge.net/support/tracker.php?&aid=1446696}].

\section{Example of Use}
\begingroup\small\begin{verbatim}
#include <tcl.h>
#include <tclArgv.h> /* not needed if subsumed into core */

int g_test_cmd(ClientData clientData, Tcl_Interp *interp,
    int objc, Tcl_Obj *CONST objv[])
{
  char *gname,*filename;
  int i;
  int numRepeat;
  double scalar;
  int doErase = 0;
  size_t size;

  /* this table specifies the possible options, all in one place.*/
  Tcl_ArgvInfo argTable[] = {
    {"-erase", TCL_ARGV_CONSTANT, (void *) 1, &doErase,
      "erase image before plotting"},
    {"-numRepeat", TCL_ARGV_INT, NULL, &numRepeat,
      "number of times to repeat test"},
    {"-scalar", TCL_ARGV_FLOAT, NULL, &scalar,
      "scalar multiple to use for test"},
    {"-outfile", TCL_ARGV_STRING, NULL, &filename,
      "name of file to which to dump result"},
    {NULL, TCL_ARGV_END, NULL, NULL, NULL}
  };

  /* Call Tcl_ParseArgObjv to do all the parsing! */
  if (Tcl_ParseArgsObjv(interp,argTable,&objc,objv,&private_objv) != TCL_OK) {
     return TCL_ERROR;
  }

  /* Should recheck objc here */

  /* at this point, any unhandled options are repacked in private_objv */
  gname = Tcl_GetString(private_obj[1]);

  /* all done */
  ckfree(private_objv);

  /* rest of code continues here...*/

  return TCL_OK;
}
\end{verbatim}
\endgroup

\section{Copyright}

This document has been placed in the public domain.

\section{Colophon}

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