\documentclass[]{article}
\usepackage{amsmath,graphicx,supertabular,hyperref,tabularx,ifthen}
\title{TIP \#60: EXTERN Macro Change to Support a Wider Set of Attributes}
\date{September 06, 2001}
\author{David Gravereaux, Donal K. Fellows}
\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 \#60}&\textbf{EXTERN Macro Change to Support a Wider Set of Attributes}\\\hline
Author&

David Gravereaux \tipmail{davygrvy}{pobox.com}
\par
Donal K. Fellows \tipmail{fellowsd}{cs.man.ac.uk}
\\
Created&Thursday, \(\text{6}^{\text{th}}\) September 2001\\
Type&Project\\
Tcl Version&\(8.6\)\\
State&Rejected\\
Vote&Done\\
Version&\tipversion$Revision: 1.21 $\\
Post History&\\
\hline\end{tabularx}\end{center}
\thispagestyle{empty}\pagestyle{empty}
\begin{tipabstract}

This TIP proposes a change to how the EXTERN macro in \textit{tcl.h} works to support a wider range of compiler specific attributes.
\end{tipabstract}
\tableofcontents\setcounter{page}{0}\clearpage\pagestyle{plain}

\section{Rationale}

With working on Borland support recently, I found that luckily the newest ``free commandline tools'' [\url{http://www.borland.com/bcppbuilder/freecompiler/}] does support Microsoft's \textit{\_\_declspec(dllexport)} attribute. But at the same time, the older way with \textit{\_\_export} is still valid, but can't be used due to the order within the prototype declaration of the EXTERN macro.

What's this with the MS compiler:
\begingroup\small\begin{verbatim}
	__declspec(dllexport) __cdecl int func (int a, int b);
\end{verbatim}
\endgroup

will have to be this with Borland:
\begingroup\small\begin{verbatim}
	int __export __cdecl func (int a, int b);
\end{verbatim}
\endgroup

The order of the attribute needs to be after the return type.

Even though \textit{\_\_declspec} is supported in the Microsoft style with version 5.5+ of the Borland compiler, if EXTERN could swap around the order a hair, old Turbo C v5.0 has a better chance to make a DOS library. Should someone feel the need.

Let's leave the existing EXTERN macro as-is and just make a new one called TCL\_EXTERN to support the new behavior.

Karl Lembuaer (sp?) did a presentation @ OSCON regarding his recent tinytcl project \textit{\%TODO: add link here\%} about his DOS port of Tcl 6.7 for use in a hand-held device.

Stepping backward for DOS support, may actually be a leap forward in an off-beat manner...

\section{Rejected Alternatives}

I saw something like this in a very old DDE extension that someone at Sun wrote. It was used as an example windows extension for years.

\url{ftp://tcl.activestate.com/pub/tcl/misc/example.zip}

In example.h is this:
\begingroup\small\begin{verbatim}
#if defined(__WIN32__)
#   if defined(_MSC_VER)
#	define EXPORT(a,b) __declspec(dllexport) a b
#   else
#	if defined(__BORLANDC__)
#	    define EXPORT(a,b) a _export b
#	else
#	    define EXPORT(a,b) a b
#	endif
#   endif
#else
#   define EXPORT(a,b) a b
#endif

EXTERN EXPORT(int,Example_Init) _ANSI_ARGS_((Tcl_Interp *interp));
\end{verbatim}
\endgroup

That work is doing the same job, but I prefer the method that I'm proposing.

It is also mentioned on \url{http://tcl.activestate.com/doc/howto/winext.html} and feel it is rather out-of-date and the order issue with \textit{\_\_export} should be brought into the core with this patch and be fix for good.

Is\tiprangle{}
\begingroup\small\begin{verbatim}
	EXTERN int Foobar_Init (Tcl_Interp *interp);
\end{verbatim}
\endgroup

Proposed\tiprangle{}
\begingroup\small\begin{verbatim}
	TCL_EXTERN(int) Foobar_Init (Tcl_Interp *interp);
\end{verbatim}
\endgroup

\section{Reference Implementation}

\url{https://sourceforge.net/tracker/download.php?group_id=10894&atid=310894&file_id=70480&aid=436116}

\section{Examples}

Is:
\begingroup\small\begin{verbatim}
EXTERN int
Foobar_Init (Tcl_Interp *interp)
{
#ifdef USE_TCL_STUBS
    if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
        return TCL_ERROR;
    }
#endif
    Tcl_CreateObjCommand(interp, "foobar", FooBar, NULL, NULL);
    return TCL_OK;
};
\end{verbatim}
\endgroup

Proposed:
\begingroup\small\begin{verbatim}
TCL_EXTERN(int)
Foobar_Init (Tcl_Interp *interp)
{
#ifdef USE_TCL_STUBS
    if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
        return TCL_ERROR;
    }
#endif
    Tcl_CreateObjCommand(interp, "foobar", FooBar, NULL, NULL);
    return TCL_OK;
};
\end{verbatim}
\endgroup

Preprocessor output is the following:

\begin{quote}
Borland:
\end{quote}
\begingroup\small\begin{verbatim}
/* foobar.c 14: */extern  int __export
/* foobar.c 15: */Foobar_Init (Tcl_Interp *interp)
/* foobar.c 16: */{
/* foobar.c 17: */
/* foobar.c 18: */if (Tcl_InitStubs(interp, "8.1", 0) == 0) {
/* foobar.c 19: */return 1;
/* foobar.c 20: */}
/* foobar.c 21: */
/* foobar.c 22: */(tclStubsPtr->tcl_CreateObjCommand)(interp, "foobar", FooBar, 0, 0);
/* foobar.c 23: */return 0;
/* foobar.c 24: */};
\end{verbatim}
\endgroup

\begin{quote}
VC++:
\end{quote}
\begingroup\small\begin{verbatim}
extern  __declspec(dllexport) int
Foobar_Init (Tcl_Interp *interp)
{

    if (Tcl_InitStubs(interp, "8.1", 0) == ((void *)0)) {
        return 1;
    }
#line 22 "foobar.c"
    (tclStubsPtr->tcl_CreateObjCommand)(interp, "foobar", FooBar, ((void *)0), ((void *)0));
    return 0;
};
\end{verbatim}
\endgroup

\begin{quote}
MinGW (native gcc on win):
\end{quote}
\begingroup\small\begin{verbatim}
extern       int
Foobar_Init (Tcl_Interp *interp)
{

    if (Tcl_InitStubs(interp, "8.1", 0) == ((void *)0) ) {
        return 1 ;
    }

    (tclStubsPtr->tcl_CreateObjCommand) (interp, "foobar", FooBar, ((void *)0) , ((void *)0) );
    return 0 ;
};
\end{verbatim}
\endgroup

\section{Random Notes}

In \textit{tclInt.h} starting around line 1916, are prototypes for the internal cmdprocs. I can't think of any reason why they should be exported. Also note the comment about line:1673, as it states:
\begingroup\small\begin{verbatim}
/*
 *----------------------------------------------------------------
 * Procedures shared among Tcl modules but not used by the outside
 * world:
 *----------------------------------------------------------------
 */
\end{verbatim}
\endgroup

As the current EXTERN macro places "``everything''" exportable, the use of EXTERN following this comment in \textit{tclInt.h} is contradictory. In place of EXTERN for this purpose I used the new TCL\_EXTRNC in the reference implementation.

\section{Copyright}

This document has been placed in the public domain.

\section{Colophon}

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