'\"
'\" Generated from file 'critcl_usingit\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) Jean-Claude Wippler
'\" Copyright (c) Steve Landers
'\" Copyright (c) 2011-2018 Andreas Kupries
'\"
.TH "critcl_use" n 3\&.1\&.18\&.1 doc "C Runtime In Tcl (CriTcl)"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
.\"	and indent is equivalent to second arg of .IP (shouldn't ever be
.\"	needed;  use .AS below instead)
.\"
.\" .AS ?type? ?name?
.\"	Give maximum sizes of arguments for setting tab stops.  Type and
.\"	name are examples of largest possible arguments that will be passed
.\"	to .AP later.  If args are omitted, default tab stops are used.
.\"
.\" .BS
.\"	Start box enclosure.  From here until next .BE, everything will be
.\"	enclosed in one large box.
.\"
.\" .BE
.\"	End of box enclosure.
.\"
.\" .CS
.\"	Begin code excerpt.
.\"
.\" .CE
.\"	End code excerpt.
.\"
.\" .VS ?version? ?br?
.\"	Begin vertical sidebar, for use in marking newly-changed parts
.\"	of man pages.  The first argument is ignored and used for recording
.\"	the version when the .VS was added, so that the sidebars can be
.\"	found and removed when they reach a certain age.  If another argument
.\"	is present, then a line break is forced before starting the sidebar.
.\"
.\" .VE
.\"	End of vertical sidebar.
.\"
.\" .DS
.\"	Begin an indented unfilled display.
.\"
.\" .DE
.\"	End of indented unfilled display.
.\"
.\" .SO ?manpage?
.\"	Start of list of standard options for a Tk widget. The manpage
.\"	argument defines where to look up the standard options; if
.\"	omitted, defaults to "options". The options follow on successive
.\"	lines, in three columns separated by tabs.
.\"
.\" .SE
.\"	End of list of standard options for a Tk widget.
.\"
.\" .OP cmdName dbName dbClass
.\"	Start of description of a specific option.  cmdName gives the
.\"	option's name as specified in the class command, dbName gives
.\"	the option's name in the option database, and dbClass gives
.\"	the option's class in the option database.
.\"
.\" .UL arg1 arg2
.\"	Print arg1 underlined, then print arg2 normally.
.\"
.\" .QW arg1 ?arg2?
.\"	Print arg1 in quotes, then arg2 normally (for trailing punctuation).
.\"
.\" .PQ arg1 ?arg2?
.\"	Print an open parenthesis, arg1 in quotes, then arg2 normally
.\"	(for trailing punctuation) and then a closing parenthesis.
.\"
.\"	# Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\"	# Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
.   ie !"\\$2"" .TP \\n()Cu
.   el          .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1	\\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
.\"	# define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
.\"	# BS - start boxed text
.\"	# ^y = starting y location
.\"	# ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\"	# BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\"	Draw four-sided box normally, but don't draw top of
.\"	box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\"	# VS - start vertical sidebar
.\"	# ^Y = starting y location
.\"	# ^v = 1 (for troff;  for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
.\"	# VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
.\"	# Special macro to handle page bottom:  finish off current
.\"	# box/sidebar if in box/sidebar mode, then invoked standard
.\"	# page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\"	Draw three-sided box if this is the box's first page,
.\"	draw two sides but no top otherwise.
.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
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
.\"	# DS - begin display
.de DS
.RS
.nf
.sp
..
.\"	# DE - end display
.de DE
.fi
.RE
.sp
..
.\"	# SO - start of list of standard options
.de SO
'ie '\\$1'' .ds So \\fBoptions\\fR
'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
.\"	# SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\*(So manual entry for details on the standard options.
..
.\"	# OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name:	\\fB\\$1\\fR
Database Name:	\\fB\\$2\\fR
Database Class:	\\fB\\$3\\fR
.fi
.IP
..
.\"	# CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\"	# CE - end code excerpt
.de CE
.fi
.RE
..
.\"	# UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
.\"	# QW - apply quotation marks to word
.de QW
.ie '\\*(lq'"' ``\\$1''\\$2
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\$2
..
.\"	# PQ - apply parens and quotation marks to word
.de PQ
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
.\"" fix emacs highlighting
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
..
.\"	# QR - quoted range
.de QR
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
..
.\"	# MT - "empty" string
.de MT
.QW ""
..
.BS
.SH NAME
critcl_use \- Using Critcl
.SH DESCRIPTION
.PP
\fIC Runtime In Tcl\fR, or \fICriTcl\fR , is a system for compiling C code
embedded in Tcl on the fly and either loading the resulting objects into Tcl for
immediate use or packaging them for distribution\&.  Use \fICriTcl\fR to improve
performance by rewriting in C those routines that are performance bottlenecks\&.
.PP
This document is a (hopefully) gentle introduction to Critcl by way of a
series of small examples\&.
.PP
Readers which came directly to this document through a search
or similar, and are thus in need of an overview of the whole system,
are advised to read the \fIIntroduction To CriTcl\fR first\&.
.PP
The examples here cover both how to embed C into Tcl with it,
and how to build the distributable packages\&.
As such the intended audience are both writers of packages with
embedded C, and people building such packages\&.
To make things easier the two themes each have their own section in
this document, enabling all readers to quickly skip the part they are
not interested in\&.
.PP
The sources of Critcl, should you have gotten them, contain
several larger examples show-casing various aspects of the
system\&. These demonstration packages can all be found in the
sub-directory "\fIexamples/\fR" of the sources\&.
.SH "EMBEDDING C"
This is the section for developers writing, or wishing to write, a
package embedding C into Tcl via critcl\&.
.PP
I guess that we are allowed to asssume that you, gentle reader, are
here because you have written some Tcl code which is not fast enough
(any more) and you wish to make it "go faster" by replacing parts (or
all) of it with speedy C\&.
.PP
Another, and I believe reasonable assumption to make would be that you
have already investigated and ruled out or done things like changes to
data structures and algorithms which reduce O(n*n) work to O (n*log n),
O(n), or even O(1)\&.
Of course, nothing prevents you from forging ahead here even if you
have not done such\&. Still, even in that case I would recommend that
you consider investigating this line of making your code go faster as
well\&.
.PP
Now, with these introductory words out of the way, lets jump into the
meat of things\&.
.SS "A SIMPLE PROCEDURE"
Starting simple, let us assume that the Tcl code in question is
something like
.CS


    proc math {x y z} {
        return [expr {(sin($x)*rand())/$y**log($z)}]
    }

.CE
with the expression pretending to be something very complex and
slow\&. Converting this to C we get:
.CS


    critcl::cproc math {double x double y double z} double {
        double up   = rand () * sin (x);
        double down = pow(y, log (z));
        return up/down;
    }

.CE
Notable about this translation:
.IP [1]
All the arguments got type information added to them, here
"double"\&.  Like in C the type precedes the argument name\&. Other
than that it is pretty much a Tcl dictionary, with keys and
values swapped\&.
.IP [2]
We now also have to declare the type of the result, here
"double", again\&.
.IP [3]
The reference manpage lists all the legal C types supported as
arguments and results\&.
.PP
.SS "CUSTOM TYPES, INTRODUCTION"
When writing bindings to external libraries \fBcritcl::cproc\fR is
usually the most convenient way of writing the lower layers\&. This is
however hampered by the fact that critcl on its own only supports a
few standard (arguably the most import) standard types, whereas the
functions we wish to bind most certainly will use much more, specific
to the library's function\&.
.PP
The critcl commands \fBargtype\fR, \fBresulttype\fR and their
adjuncts are provided to help here, by allowing a developer to extend
critcl's type system with custom conversions\&.
.PP
This and the three following sections will demonstrate this,
from trivial to complex\&.
.PP
The most trivial use is to create types which are aliases of
existing types, standard or other\&. As an alias it simply copies and
uses the conversion code from the referenced types\&.
.PP
Our example is pulled from an incomplete project of mine, a
binding to \fIJeffrey Kegler\fR's \fIlibmarpa\fR library managing
Earley parsers\&. Several custom types simply reflect the typedef's done
by the library, to make the \fBcritcl::cproc\fRs as self-documenting
as the underlying library functions themselves\&.
.CS


    critcl::argtype Marpa_Symbol_ID     = int
    critcl::argtype Marpa_Rule_ID       = int
    critcl::argtype Marpa_Rule_Int      = int
    critcl::argtype Marpa_Rank          = int
    critcl::argtype Marpa_Earleme       = int
    critcl::argtype Marpa_Earley_Set_ID = int

    \&.\&.\&.

    method sym-rank: proc {
        Marpa_Symbol_ID sym
        Marpa_Rank      rank
    } Marpa_Rank {
        return marpa_g_symbol_rank_set (instance->grammar, sym, rank);
    }

    \&.\&.\&.

.CE
.SS "CUSTOM TYPES, SEMI-TRIVIAL"
A more involved custom argument type would be to map from Tcl strings
to some internal representation, like an integer code\&.
.PP
The first example is taken from the \fBtclyaml\fR package,
a binding to the \fBlibyaml\fR library\&. In a few places we have to
map readable names for block styles, scalar styles, etc\&. to the
internal enumeration\&.
.CS


    critcl::argtype yaml_sequence_style_t {
        if (!encode_sequence_style (interp, @@, &@A)) return TCL_ERROR;
    }

    \&.\&.\&.

    critcl::ccode {
        static const char* ty_block_style_names [] = {
            "any", "block", "flow", NULL
        };

        static int
        encode_sequence_style (Tcl_Interp* interp, Tcl_Obj* style,
                               yaml_sequence_style_t* estyle)
        {
            int value;
            if (Tcl_GetIndexFromObj (interp, style, ty_block_style_names,
                                     "sequence style", 0, &value) != TCL_OK) {
                return 0;
            }
            *estyle = value;
            return 1;
        }
    }

    \&.\&.\&.

    method sequence_start proc {
        pstring anchor
        pstring tag
        int implicit
        yaml_sequence_style_t style
    } ok {
        /* Syntax: <instance> seq_start <anchor> <tag> <implicit> <style> */
        \&.\&.\&.
    }

    \&.\&.\&.

.CE
It should be noted that this code precedes the advent of the
supporting generator package \fBcritcl::emap\fR\&. using the
generator the definition of the mapping becomes much simpler:
.CS


    critcl::emap::def yaml_sequence_style_t {
        any   0
        block 1
        flow  2
    }

.CE
Note that the generator will not only provide the conversions, but
also define the argument and result types needed for their use by
\fBcritcl::cproc\fR\&.
Another example of such a semi-trivial argument type can be found in
the \fBCRIMP\fR package, which defines a \fBTcl_ObjType\fR for
\fIimage\fR values\&. This not only provides a basic argument type for
any image, but also derived types which check that the image has a
specific format\&. Here we see for the first time non-integer arguments,
and the need to define the C types used for variables holding the C
level value, and the type of function parameters (Due to C promotion
rules we may need different types)\&.
.CS


    critcl::argtype image {
        if (crimp_get_image_from_obj (interp, @@, &@A) != TCL_OK) {
            return TCL_ERROR;
        }
    } crimp_image* crimp_image*

    \&.\&.\&.

        set map [list <<type>> $type]
        critcl::argtype image_$type [string map $map {
            if (crimp_get_image_from_obj (interp, @@, &@A) != TCL_OK) {
                return TCL_ERROR;
            }
            if (@A->itype != crimp_imagetype_find ("crimp::image::<<type>>")) {
                Tcl_SetObjResult (interp,
                                  Tcl_NewStringObj ("expected image type <<type>>",
                                                    -1));
                return TCL_ERROR;
            }
        }] crimp_image* crimp_image*

    \&.\&.\&.

.CE
.SS "CUSTOM TYPES, SUPPORT STRUCTURES"
The adjunct command \fBcritcl::argtypesupport\fR is for when the
conversion needs additional definitions, for example a helper
structure\&.
.PP
An example of this can be found among the standard types of
critcl itself, the \fBpstring\fR type\&. This type provides the C
function with not only the string pointer, but also the string length,
and the \fBTcl_Obj*\fR this data came from\&. As \fBcritcl::cproc\fR's
calling conventions allow us only one argument for the data of the
parameter a structure is needed to convey these three pieces of
information\&.
.PP
Thus the argument type is defined as
.CS


    critcl::argtype pstring {
        @A\&.s = Tcl_GetStringFromObj(@@, &(@A\&.len));
        @A\&.o = @@;
    } critcl_pstring critcl_pstring

    critcl::argtypesupport pstring {
        typedef struct critcl_pstring {
            Tcl_Obj*    o;
            const char* s;
            int         len;
        } critcl_pstring;
    }

.CE
.PP
In the case of such a structure being large we may wish to
allocate it on the heap instead of having it taking space on the
stack\&. If we do that we need another adjunct command,
\fBcritcl::argtyperelease\fR\&. This command specifies the code required
to release dynamically allocated resources when the worker function
returns, before the shim returns to the caller in Tcl\&.
To keep things simple our example is synthetic, a modification of
\fBpstring\fR above, to demonstrate the technique\&. An actual, but
more complex example is the code to support the variadic \fIargs\fR
argument of \fBcritcl::cproc\fR\&.
.CS


    critcl::argtype pstring {
        @A = (critcl_pstring*) ckalloc(sizeof(critcl_pstring));
        @A->s = Tcl_GetStringFromObj(@@, &(@A->len));
        @A->o = @@;
    } critcl_pstring* critcl_pstring*

    critcl::argtypesupport pstring {
        typedef struct critcl_pstring {
            Tcl_Obj*    o;
            const char* s;
            int         len;
        } critcl_pstring;
    }

    critcl::argtyperelease pstring {
        ckfree ((char*)) @A);
    }

.CE
Note, the above example shows only the most simple case of an
allocated argument, with a conversion that cannot fail (namely, string
retrieval)\&. If the conversion can fail then either the allocation has
to be defered to happen only on successful conversion, or the
conversion code has to release the allocated memory itself in the
failure path, because it will never reach the code defined via
\fBcritcl::argtyperelease\fR in that case\&.
.SS "CUSTOM TYPES, RESULTS"
All of the previous sections dealt with argument conversions,
i\&.e\&. going from Tcl into C\&.
Custom result types are for the reverse direction, from C to Tcl\&.
This is usually easier, as most of the time errors should not be
possible\&. Supporting structures, or allocating them on the heap are
not really required and therefore not supported\&.
.PP
The example of a result type shown below was pulled from
\fBKineTcl\fR\&. It is a variant of the builtin result type
\fBTcl_Obj*\fR, aka \fBobject\fR\&. The builtin conversion assumes
that the object returned by the function has a refcount of 1 (or
higher), with the function having held the reference, and releases
that reference after placing the value into the interp result\&. The
conversion below on the other hand assumes that the value has a
refcount of 0 and thus that decrementing it is forbidden, lest it be
released much to early, and crashing the system\&.
.CS


    critcl::resulttype KTcl_Obj* {
        if (rv == NULL) { return TCL_ERROR; }
        Tcl_SetObjResult(interp, rv);
        /* No refcount adjustment */
        return TCL_OK;
    } Tcl_Obj*

.CE
This type of definition is also found in \fBMarpa\fR and recent
hacking hacking on \fBCRIMP\fR introduced it there as well\&. Which
is why this definition became a builtin type starting with version
3\&.1\&.16, under the names \fBTcl_Obj*0\fR and \fBobject0\fR\&.
.PP
Going back to errors and their handling, of course, if a
function we are wrapping signals them in-band, then the conversion of
such results has to deal with that\&. This happens for example in
\fBKineTcl\fR, where we find
.CS


    critcl::resulttype XnStatus {
        if (rv != XN_STATUS_OK) {
            Tcl_AppendResult (interp, xnGetStatusString (rv), NULL);
            return TCL_ERROR;
        }
        return TCL_OK;
    }

    critcl::resulttype XnDepthPixel {
        if (rv == ((XnDepthPixel) -1)) {
            Tcl_AppendResult (interp,
                              "Inheritance error: Not a depth generator",
                              NULL);
            return TCL_ERROR;
        }
        Tcl_SetObjResult (interp, Tcl_NewIntObj (rv));
        return TCL_OK;
    }

.CE
.SS "HANDLING A VARIABLE NUMBER OF ARGUMENTS"
In \fBA Simple Procedure\fR we demonstrated how easy a
translation to C can be\&. Is it still as easy when we introduce
something moderately complex like handling a variable number of
arguments ? A feature which is needed to handle commands with options
and optional arguments ?
.PP
Well, starting with version 3\&.1\&.16 \fBcritcl::cproc\fR does
have full support for optional arguments, \fIargs\fR-style variadics,
and default values, extending its range to everything covered by the
builtin \fBproc\fR\&. The only thing not truly supported are options
(i\&.e\&. flag arguments) of any kind\&.
.PP
For the moment, and the example, let us pretend that we can use
\fBcritcl::cproc\fR only if the number of arguments is fully known
beforehand, i\&.e\&. at the time of declaration\&.
Then we have to use \fBcritcl::ccommand\fR to handle the translation
of the procedure shown below:
.CS


    proc math {args} {
        set sum 0
        foreach y $args { set sum [expr {$sum + $y}] }
        return $sum
    }

.CE
.PP
Its advantage: Access to the low-level C arguments representing
the Tcl arguments of the command\&. Full control over argument
conversion, argument validation, etc\&.
.PP
Its disadvantage: Access to the low-level C arguments
representing the Tcl arguments of the command\&. Assuming the burden of
having to write argument conversion, argument validation, etc\&. Where
\fBcritcl::cproc\fR handles the task of converting from Tcl to C
values (for arguments) and back (for the result), with
\fBcritcl::command\fR it is the developer who has to write all this
code\&.
.PP
Under our restriction the translation of the example is:
.CS


    critcl::ccommand math {cd ip oc ov} {
        double sum = 0;
        double y;

        oc --;
        while (oc) {
            if (Tcl_GetDoubleFromObj (ip, ov[oc], &y) != TCL_OK) {
                return TCL_ERROR;
            }
            sum += y;
            oc --;
        }

        Tcl_SetObjResult (ip, Tcl_NewDoubleObj (sum));
        return TCL_OK:
    }

.CE
Notable about this translation:
.IP [1]
As promised/threatened, all the conversions between the Tcl and
C domains are exposed, and the developer should know her way
around Tcl's C API\&.
.IP [2]
The four arguments "cd ip oc ov" are our names for the
low-level arguments holding
.RS
.IP [1]
ClientData (reference)
.IP [2]
Tcl_Interp (reference)
.IP [3]
Number of arguments, and
.IP [4]
Array of argument values, each a Tcl_Obj*\&.
.RE
.IP
This list of arguments, while not optional in itself, is allowed to be
empty, and/or to contain empty strings as argument names\&. If we do
that critcl will supply standard names for the missing pieces, namely:
.RS
.IP [1]
clientdata
.IP [2]
interp
.IP [3]
objc
.IP [4]
objv
.RE
.PP
.PP
Now, letting go of our pretenses regarding the limitations of
\fBcritcl::cproc\fR, due to the support it does have for
\fIargs\fR-style variadics (since version 3\&.1\&.16) we can write a much
simpler translation:
.CS


    critcl::cproc math {double args} double {
        double sum = 0;

        args\&.c --;
        while (args\&.c) {
            sum += args\&.v[args\&.c];
            args\&.c --;
        }
        return sum;
    }

.CE
.SS "DATA AS A TCL COMMAND"
Here we assume that we have a Tcl procedure which returns a fixed
string\&. In the final product we are going to C to hide this string
from the casual user\&.
.CS


    proc somedata {} {
	return {\&.\&.\&. A large blob of characters \&.\&.\&.}
    }

.CE
The translation of this is simple and easy:
.CS


    package require critcl

    critcl::cdata somedata {\&.\&.\&. A large blob of characters \&.\&.\&.}

.CE
There is nothing really notable here\&.
.SS "BLOCKS OF ARBITRARY C"
Often just defining Tcl commands in C, as demonstrated in the sections
\fBA Simple Procedure\fR,
\fBHandling A Variable Number Of Arguments\fR, and
\fBData As A Tcl Command\fR
is not really enough\&.
For example we may have several of our new C commands using the same
code over and over, and we wish avoid this duplication\&. Or we wish to
pull in declarations and definitions from some external library\&.
.PP
In both cases we require the ability to embed an unstructured block of
C code which can contain whatever we want, defines, functions,
includes, etc\&. without being directly tied to Tcl commands\&.
The command \fBcritcl::code\fR provides us with exactly that\&.
As our example now an excerpt taken from real code, the top of the
"\fIsha1c\&.tcl\fR" critcl file in the \fIsha1\fR module of
\fITcllib\fR:
.CS


    critcl::ccode {
        #include "sha1\&.h"
        #include <stdlib\&.h>
        #include <assert\&.h>

        static
        Tcl_ObjType sha1_type; /* fast internal access representation */

        static void
        sha1_free_rep(Tcl_Obj* obj)
        {
            SHA1_CTX* mp = (SHA1_CTX*) obj->internalRep\&.otherValuePtr;
            Tcl_Free(mp);
        }

        \&.\&.\&.
    }

.CE
We see here the beginning of the C code defining a custom
\fITcl_ObjType\fR holding the data of a SHA1 context used during the
incremental calculation of sha1 hashes\&.
.SS "CONSTANT VALUES"
While one might believe that there is no need for commands which
returns constant values that is not true\&. Commands reporting on
compile-time configuration, like version numbers, available features,
etc\&. are at least one use case for such commands\&.
.PP
The reason for creating critcl commands to support them ?
Convenience to the user, yes, but further than that, the ability to
optimize the internals, i\&.e\&. the generated code\&.
.PP
A \fBcproc\fR would be easy to write, but incurs overhead due
to a superfluous work function\&. A \fBccommand\fR has no overhead,
except that of the user having to write the argument checking and
result conversion\&.
.PP
Using \fBcritcl::cconst\fR is both convenient and without code
overhead\&.
Our example is a function found in package \fBtcl-linenoise\fR,
that is, if \fBcconst\fR had existed at the time of writing\&. It
returns a configuration value reporting to the policy layer if an
extended mode for hidden input is available from the bound
\fBlinenoise\fR, or not\&.
.CS


    critcl::cconst linenoise::hidden_extended boolean 1

.CE
.SS "LIFTING CONSTANTS"
When writing a critcl-based package to make a third-party library
available to scripts we do not only have to make the relevant
functions available as commands, often we also have to know all
the various constants, flags, etc\&. these functions take\&.
.PP
Rather than writing such magic numbers directly we would
greatly prefer to use symbolic names instead\&.
Instead of providing one or more commands to list and map the magic
numbers to strings critcl \fIonly\fR provides a single command which
allows the export of C defines and enumeration values, mapping them to
Tcl variables of the given names, whose values are the associated
magic numbers\&.
.PP
This is good enough because the developers of the third-party
library were very likely like us and wanted to use symbolic names
instead of magic numbers\&. Which in C are declared as via defines and
enumeration types\&. We just have to \fIlift\fR them up\&.
.PP
Our example comes from \fBcryptkit\fR, a Tcl binding to
\fBcryptlib\fR, a cryptography library\&.
The command
.CS


    critcl::cdefines CRYPT_* ::crypt

.CE
maps all Cryptlib specific #defines and enums into the namespace
\fB::crypt\fR, telling critcl to create aliases to the symbols\&.
.PP
Similarly
.CS


    critcl::cdefines {
        NULL
        TRUE
        FALSE
        TCL_OK
        TCL_ERROR
    } ::crypt

.CE
maps the listed defines into the namespace \fB::crypt\fR\&.
.PP
An \fIimportant\fR thing to note:
These commands \fIdo not create\fR the defines in the C level\&. They
only lift pre-existing material\&.
Which can come from the headers of the third-party library, the usual
case, but also from \fBBlocks of arbitrary C\fR\&.
.PP
A corrollary to the above: What is not where, cannot be
lifted\&. All listed names and patterns which have no actual C code
declaring them are ignored, i\&.e\&. not mapped\&.
.SS "FINDING HEADER FILES"
A notable thing in the example shown in the section about
\fBBlocks of arbitrary C\fR is the
.CS


    #include "sha1\&.h"

.CE
statement\&. Where does this header come from ?
Looking at the Tcllib module we will find that the header is actually
a sibling to the "\fIsha1c\&.tcl\fR" file containing the embedded C code\&.
However, \fBcritcl\fR does not know that\&. It has to be told\&.
While without that knowledge it will invoke the compiler just fine,
the compilation will fail because the header is not on the include
paths used by the compiler, and therefore will not be found\&.
.PP
For this we have the \fBcritcl::cheaders\fR command\&. It enables us to
either tell the compiler the path(s) where the required headers can be
found, using
.CS


    critcl::cheaders -I/path/to/headers/

.CE
or to tell it directly which headers we are using and where they live:
.CS


    critcl::cheaders sha1\&.h

.CE
And now critcl knows that "\fIsha1\&.h\fR" is important, and that it
lives besides the "\fI\&.critcl\fR" file which referenced it (because of
the relative path used)\&.
\fINote\fR that this doesn't absolve us of the need to "#include" the
header through a \fBcritcl::ccode\fR block\&. This only tells critcl
where it lives so that it can configure the compiler with the proper
include paths to actually find it on use\&.
.PP
Further note that a C development environment is usually
configured to find all the system headers, obviating the need for a
\fBcritcl::cheaders\fR declaration when such are used\&. For these a
plain "#include" in a \fBcritcl::ccode\fR block is good enough\&.
In other words, the second form of invoking \fBcritcl::cheaders\fR is
pretty much only for headers which accompany the "\fI\&.critcl\fR" file\&.
.SS "SEPARATE C SOURCES"
In all of the examples shown so far the C code was fully embedded in a
"\fI\&.critcl\fR" file\&. However, if the C part is large it can make sense
to break it out of the "\fI\&.critcl\fR" file into one or more separate
proper "\fI\&.c\fR" file(s)\&.
.PP
The \fBcritcl::csources\fR command can then be used to make
this code known to the original "\fI\&.critcl\fR" file again\&.
This command accepts the paths to the "\fI\&.c\fR" files as arguments,
and glob patterns as well\&.
Our example comes from the \fBstruct::graph\fR package in
Tcllib\&.
Its core C functions are in separate files, and the "\fI\&.critcl\fR"
code then makes them known via:
.CS


namespace eval ::struct {
    # Supporting code for the main command\&.
    critcl::cheaders graph/*\&.h
    critcl::csources graph/*\&.c

    \&.\&.\&.
}

.CE
which tells critcl that these files are in the subdirectory
"\fIgraph\fR" relative to the location of "\fIgraph_c\&.tcl\fR", which is
the relevant "\fI\&.critcl\fR" file\&.
.PP
This example also demonstrates again the use of
\fBcritcl::cheaders\fR, which we also saw in section
\fBFinding header files\fR\&.
.SS "FINDING EXTERNAL LIBRARIES"
When creating a package exposing some third-party library to Tcl
\fBFinding header files\fR is only the first part, to enable
failure-free compilation\&. We also have to find the library/ies
themselves so that they can be linked to our package\&. This is
described here\&. The last issue, \fBLifting constants\fR from C
to Tcl for the use by scripts is handled in a separate section and
example\&.
.PP
The relevant command is \fBcritcl::clibraries\fR\&. Its basic
semantics are like that of \fBcritcl::cheaders\fR, i\&.e\&. It enables us
to tell the linker the path(s) where the required libraries can be
found, using
.CS


    critcl::clibraries -L/path/to/libraries/

.CE
name them
.CS


    critcl::clibraries -lfoo

.CE
or tell it directly which libraries we are using and where they live:
.CS


    critcl::clibraries /path/to/library/foo\&.so

.CE
This last way of using should be avoided however, as it intermingles
searching and naming, plus the name is platform dependent\&.
.PP
For OS X we additionally have the \fBcritcl::framework\fR
command which enables us to name the frameworks used by our package\&.
Note that this command can be used unconditionally\&. If the build
target is not OS X it is ignored\&.
.SS "CUSTOMIZING THE COMPILE AND LINK STEPS"
The commands \fBcritcl::cflags\fR and \fBcritcl::ldflags\fR enable you
to provide custom options to the compile and link phases for a
"\fI\&.critcl\fR" file\&.
.PP
This usually becomes necessary if the C code in question comes
from an external library we are writing a Tcl binding for, with
multiple configurations to select, non-standard header locations, and
other things\&.
Among the latter, especially platform-specific settings, for example
byteorder\&.
.PP
This makes \fBcritcl::check\fR an important adjunct command, as
this is the API for \fBChecking The Environment\fR, and then
selecting the compile & link flags to use\&.
.PP
\fII currently have no specific example to demonstrate these commands\&.\fR
.SS "HAVING BOTH C AND TCL FUNCTIONALITY"
Often enough only pieces of a package require recoding in C to boost
the whole system\&. Or, alternatively, the package in question consists
of a low-level layer C with a Tcl layer above encoding policies and
routing to the proper low-level calls, creating a nicer (high-level)
API to the low-level functionality, etc\&.
.PP
For all of this we have to be able to write a package which
contains both C and Tcl, nevermind the fact the C parts are embedded
in Tcl\&.
.PP
The easiest way to structure such a package is to have several
files, each with a different duty\&. First, a "\fI\&.critcl\fR" file
containing the embedded C, and second one or more "\fI\&.tcl\fR" files
providing the Tcl parts\&.
Then use the \fBcritcl::tsources\fR command in the "\fI\&.critcl\fR" file
to link the two parts together, declaring the "\fI\&.tcl\fR" files as
necessary companions of the C part\&.
.CS


    package require critcl

    critcl::tsources your-companion\&.tcl ; # Companion file to use

    \&.\&.\&. embedded C via critcl commands \&.\&.\&.

.CE
With a declaration as shown above the companion file will be
automatically \fBsource\fRd when the C parts are made available, thus
making the Tcl parts available as well\&.
.SS "USING C WITH TCL FUNCTIONALITY AS FALLBACK"
There is one special case of
\fBHaving both C and Tcl functionality\fR
which deserves its own section\&.
.PP
The possibility of not having the fast C code on some platform,
and using a slower Tcl implementation of the functionality\&. In other
words, a fallback which keeps the package working in the face of
failure to build the C parts\&. A more concrete example of this would be
a module implementing the SHA hash, in both C and Tcl, and using the
latter if and only if the C implementation is not available\&.
.PP
There two major possibilities in handling such a situation\&.
.IP [1]
Keep all the pieces separated\&. In that scenario our concrete
example would be spread over three packages\&. Two low-level packages
\fBsha::c\fR and \fBsha::tcl\fR containing the two
implementations of the algorithm, and, thirdly, a coordinator package
\fBsha\fR which loads either of them, based on availability\&.
.sp
The Tcllib bundle of packages contains a number of packages
structured in this manner, mostly in the \fIstruct\fR module\&.
.sp
Writing the C and Tcl parts should be simple by now, with all
the examples we had so far\&. The only non-trivial part is the
coordinator, and even that if and only if we wish to make it easy to
write a testsuite which can check both branches, C, and Tcl without
gymnastics\&. So, the most basic coordinator would be
.CS


    set sha::version 1
    if {[catch {
        package require sha::c $sha::version
    }]} {
        package require sha::tcl $sha::version
    }
    package provide sha $sha::version

.CE
.IP
It tries to load the C implementation first, and falls back to the Tcl
implementation if that fails\&. The code as is assumes that both
implementations create exactly the same command names, leaving the
caller unaware of the choice of implementations\&.
.sp
A concrete example of this scheme can be found in Tcllib's
\fBmd5\fR package\&. While it actually uses ythe \fBTrf\fR as
its accelerator, and not a critcl-based package the principle is the
same\&. It also demonstrates the need for additional glue code when the
C implementation doesn't exactly match the signature and semantics of
the Tcl implementation\&.
.sp
This basic coordinator can be easily extended to try more than
two packages to get the needed implementation\&. for example, the C
implementation may not just exist in a sha::c package, but also
bundled somewhere else\&. Tcllib, for example, has a tcllibc package
which bundles all the C parts of its packages which have them in a
single binary\&.
.sp
Another direction to take it in is to write code which allows
the loading of multiple implementations at the same time, and then
switching between them at runtime\&. Doing this requires effort to keep
the implementations out of each others way, i\&.e\&. they cannot provide
the same command names anymore, and a more complex coordinator as
well, which is able to map from the public command names to whatever
is provided by the implementation\&.
.sp
The main benefit of this extension is that it makes testing the
two different implementations easier, simply run through the same set
of tests multiple times, each time with different implementation
active\&. The disadvantage is the additional complexity of the
coordinator's internals\&. As a larger example of this technique here is
the coordinator "\fImodules/struct/queue\&.tcl\fR" handling the C and Tcl
implementations of Tcllib's \fBstruct::queue\fR package:
.CS


    # queue\&.tcl --
    #       Implementation of a queue data structure for Tcl\&.

    package require Tcl 8\&.4
    namespace eval ::struct::queue {}

    ## Management of queue implementations\&.

    # ::struct::queue::LoadAccelerator --
    #       Loads a named implementation, if possible\&.

    proc ::struct::queue::LoadAccelerator {key} {
        variable accel
        set r 0
        switch -exact -- $key {
            critcl {
                # Critcl implementation of queue requires Tcl 8\&.4\&.
                if {![package vsatisfies [package provide Tcl] 8\&.4]} {return 0}
                if {[catch {package require tcllibc}]} {return 0}
                set r [llength [info commands ::struct::queue_critcl]]
            }
            tcl {
                variable selfdir
                if {
                    [package vsatisfies [package provide Tcl] 8\&.5] &&
                    ![catch {package require TclOO}]
                } {
                    source [file join $selfdir queue_oo\&.tcl]
                } else {
                    source [file join $selfdir queue_tcl\&.tcl]
                }
                set r 1
            }
            default {
                return -code error "invalid accelerator/impl\&. package $key: must be one of [join [KnownImplementations] {, }]"
            }
        }
        set accel($key) $r
        return $r
    }

    # ::struct::queue::SwitchTo --
    #       Activates a loaded named implementation\&.

    proc ::struct::queue::SwitchTo {key} {
        variable accel
        variable loaded

        if {[string equal $key $loaded]} {
            # No change, nothing to do\&.
            return
        } elseif {![string equal $key ""]} {
            # Validate the target implementation of the switch\&.

            if {![info exists accel($key)]} {
                return -code error "Unable to activate unknown implementation \\"$key\\""
            } elseif {![info exists accel($key)] || !$accel($key)} {
                return -code error "Unable to activate missing implementation \\"$key\\""
            }
        }

        # Deactivate the previous implementation, if there was any\&.

        if {![string equal $loaded ""]} {
            rename ::struct::queue ::struct::queue_$loaded
        }

        # Activate the new implementation, if there is any\&.

        if {![string equal $key ""]} {
            rename ::struct::queue_$key ::struct::queue
        }

        # Remember the active implementation, for deactivation by future
        # switches\&.

        set loaded $key
        return
    }

    # ::struct::queue::Implementations --
    #       Determines which implementations are
    #       present, i\&.e\&. loaded\&.

    proc ::struct::queue::Implementations {} {
        variable accel
        set res {}
        foreach n [array names accel] {
            if {!$accel($n)} continue
            lappend res $n
        }
        return $res
    }

    # ::struct::queue::KnownImplementations --
    #       Determines which implementations are known
    #       as possible implementations\&.

    proc ::struct::queue::KnownImplementations {} {
        return {critcl tcl}
    }

    proc ::struct::queue::Names {} {
        return {
            critcl {tcllibc based}
            tcl    {pure Tcl}
        }
    }

    ## Initialization: Data structures\&.

    namespace eval ::struct::queue {
        variable  selfdir [file dirname [info script]]
        variable  accel
        array set accel   {tcl 0 critcl 0}
        variable  loaded  {}
    }

    ## Initialization: Choose an implementation,
    ## most preferred first\&. Loads only one of the
    ## possible implementations\&. And activates it\&.

    namespace eval ::struct::queue {
        variable e
        foreach e [KnownImplementations] {
            if {[LoadAccelerator $e]} {
                SwitchTo $e
                break
            }
        }
        unset e
    }

    ## Ready

    namespace eval ::struct {
        # Export the constructor command\&.
        namespace export queue
    }

    package provide struct::queue 1\&.4\&.2

.CE
.IP
In this implementation the coordinator renames the commands of the
low-level packages to the public commands, making the future dispatch
as fast as if the commands had these names anyway, but also forcing a
spike of bytecode recompilation if switching is ever done at the
runtime of an application, and not just used for testing, and possibly
disrupting introspection by the commands, especially if they move
between different namespaces\&.
.sp
A different implementation would be to provide the public
commands as procedures which consult a variable to determine which of
the loaded implementations is active, and then call on its
commands\&. This doesn't disrupt introspection, nor does it trigger
bytecode recompilation on switching\&. But it takes more time to
dispatch to the actual implementation, in every call of the public API
for the package in question\&.
.sp
A concrete example of this scheme can be found in Tcllib's
\fBcrc32\fR package\&.
.IP [2]
Mix the pieces together\&. Please note that while I am describing
how to make this work I strongly prefer and recommend to use the
previously shown approach using separate files/packages\&. It is much
easier to understand and maintain\&. With this warning done, lets go
into the nuts and bolts\&.
.sp
If we care only about mode "compile & run" things are easy:
.CS


    package require critcl

    if {![critcl::compiling]} {
        proc mycommand {\&.\&.\&.} {
            \&.\&.\&.
        }

    } else {
        critcl::cproc mycommand {\&.\&.\&.} {
            \&.\&.\&.
        }
    }

.CE
.IP
The command \fBcritcl::compiling\fR tells us whether we have a
compiler available or not, and in the latter case we implement our
command in Tcl\&.
.sp
Now what happens when we invoke mode "generate package" ?
\&.\&.\&. compiler failure \&.\&.\&.
\&.\&.\&. ok   - C code - everything fine
\&.\&.\&. fail - no package ? or just no C code ? declare self as tsource, to be used ?
\&.\&.\&. platform-specific C/Tcl -- uuid\&.
.PP
.SS "UNLAZY PACKAGES"
By default critcl is a bit inconsistent between modes "compile & run"
and "generate package"\&. The result of the latter is a standard Tcl
package which loads and sources all of its files immediately when it
is required\&. Whereas "compile & run" defers actual compilation,
linking, and loading until the first time one of the declared commands
is actually used, making this very lazy\&.
.PP
This behaviour can be quite unwanted if Tcl companion files, or
other users of the C commands use introspection to determine the
features they have available\&. Just using [\fBinfo commands\fR]
doesn't cut it, the \fBauto_index\fR array has to be checked as well,
making things quite inconvenient for the users\&.
.PP
To fix this issue at the source, instead of in each user, be it
inside of the package itself, or other packages, we have the command
\fBcritcl::load\fR\&.
Used as the last command in a "\fI\&.critcl\fR" file it forces the
compile, link, and load trinity, ensuring that all C commands are
available immediately\&.
.CS


    package require critcl

    \&.\&.\&. Declare C procedures, commands, etc\&.

    critcl::load ; # Force build and loading\&.

.CE
Note that is not allowed, nor possible to use critcl commands
declaring anything after \fBcritcl::load\fR has been called\&. I\&.e\&., code like
.CS


    package require critcl

    \&.\&.\&. Declare C procedures, commands, etc\&.

    critcl::load ; # Force build and loading\&.

    \&.\&.\&. More declarations of C code, \&.\&.\&.
    critcl::code { \&.\&.\&. }

.CE
will result in an error\&. The only package-related commands still
allowed are
.IP [1]
\fBcritcl::done\fR
.IP [2]
\fBcritcl::failed\fR
.IP [3]
\fBcritcl::load\fR
.PP
as these only query information, namely the build status, and are
protected against multiple calls\&.
.SH "CHECKING YOUR C"
As said several times, by default critcl defers the compile and link
steps for a file until it is needed, i\&.e\&. the first command of the
"\fI\&.critcl\fR" file in question is actually invoked\&.
.PP
This not only has the effect of lazily loading the package's
functionality, but also, when developing using mode "compile & run",
of us not seeing any errors in our code until we are actually trying
to run some demonstration\&.
.PP
If we do not wish to have such a delay we have to be able to
force at least the execution of the compile step\&.
.PP
The command \fBcritcl::failed\fR is exactly that\&. When called
it forcibly builds the C code for the "\fI\&.critcl\fR" file it is part
of, and returns a boolean vlaue signaling failure (\fBtrue\fR), or
success (\fBfalse\fR)\&.
.CS


    package require critcl

    \&.\&.\&. Declare C procedures, commands, etc\&.

    if {[critcl::failed]} {
        \&.\&.\&. signal error
    }

.CE
It is related and similar to \fBcritcl::load\fR, the command to
overcome the lazy loading, as shown in section
\fBUnlazy Packages\fR\&.
.PP
Like it is not allowed, nor possible to use critcl commands
declaring anything after \fBcritcl::failed\fR has been called, making
it pretty much the last critcl command in a "\fI\&.critcl\fR" file\&.
Code like
.CS


    package require critcl

    \&.\&.\&. Declare C procedures, commands, etc\&.

    if {[critcl::failed]} { \&.\&.\&. }

    \&.\&.\&. More declarations of C code, \&.\&.\&.
    critcl::code { \&.\&.\&. }

.CE
will result in an error\&. The only package-related commands still
allowed are
.IP [1]
\fBcritcl::done\fR
.IP [2]
\fBcritcl::failed\fR
.IP [3]
\fBcritcl::load\fR
.PP
as these only query information, namely the build status, and are
protected against multiple calls\&.
.SS "WHICH TCL ?"
When building the shared library from the embedded C sources one of
the things critcl does for us is to provide the Tcl headers,
especially the stubs declarations\&.
.PP
By default these are the Tcl 8\&.4 headers and stubs, which
covers 90% of the cases\&. What when the package in question is meant
for use with Tcl 8\&.5 or higher, using C-level features of this version
of Tcl\&.
.PP
Use the \fBcritcl::tcl\fR command to declare to critcl the
minimum version of Tcl required to operate the package\&. This can be
either \fB8\&.4\fR, \fB8\&.5\fR, or \fB8\&.6\fR, and critcl then
supplies the proper headers and stubs\&.
.CS


    package require critcl
    critcl::tcl 8\&.5

    \&.\&.\&. Declare your code \&.\&.\&.

.CE
.SS "MAKING A WIDGET"
\&.\&.\&. requires compiling against the Tk headers, and linking with Tk's
stubs\&. For our convenience we have a simple, single command to
activate all the necessary machinery, with critcl supplying the header
files and stubs C code, instead of having to make it work on our own
via \fBcritcl::cflags\fR, \fBcritcl::ldflags\fR,
\fBcritcl::cheaders\fR, \fBcritcl::csources\fR\&.
.PP
This command is \fBcritcl::tk\fR\&.
.CS


    package require critcl
    critcl::tk ; # And now critcl knows to put in the Tk headers and other support\&.

    \&.\&.\&. Declare your code \&.\&.\&.

.CE
Please note that this doesn't release you from the necessity of
learning Tk's C API and how to use it to make a widget work\&. Sorry\&.
.SS "CHECKING THE ENVIRONMENT"
\&.\&.\&. may be necessary when creating a binding to some third-party
library\&. The headers for this library may be found in non-standard
locations, ditto for the library/ies itself\&. We may not have the
headers and/or library on the build host\&. Types with
platform-dependent sizes and definitions\&. Endianness issues\&. Any number
of things\&.
.PP
TEA-based packages can use \fBautoconf\fR and various
predefined macros to deal with all this\&.
We have the \fIPower Of Tcl (tm)\fR and \fBcritcl::check\fR\&.
.PP
This command takes a piece of C code as argument, like
\fBcritcl::ccode\fR\&. Instead of saving it for later it however tries
to compile it immediately, using the current settings, and then
returns a boolean value reporting on the success (\fBtrue\fR) or
failure (\fBfalse\fR)\&. From there we can then branch to different
declarations\&.
.PP
As example let us check for the existence of some header
"\fIFOO\&.h\fR":
.CS


    package require critcl

    if {[critcl::check {
        #include <FOO\&.h>
    }]} {
        \&.\&.\&. Code for when FOO\&.h is present\&.
    } else {
        \&.\&.\&. Code for when FOO\&.h is not present\&.
    }

.CE
Should we, on the other hand, wish to search for the header ourselves,
in non-standard locations we have the full power of Tcl available,
i\&.e\&. loops, the \fBfile\fR and \fBglob\fR commands, etc\&., which can
then be followed by a \fBcritcl::cheader\fR command to declare the
location we found (See also \fBFinding header files\fR)\&.
.PP
A nice extension to critcl would be a package collecting
pocedures for common tasks like that, sort of like an
\fBautoconf\fR for Tcl\&. \fBcritcl::config\fR seems to be nice
name for such a package\&.
.PP
Obvious adjunct commands which can be driven by results from
\fBcritcl::check\fR are
.TP
\fBcritcl::cflags\fR
.TP
\fBcritcl::cheaders\fR
.TP
\fBcritcl::clibraries\fR
.TP
\fBcritcl::framework\fR
.TP
\fBcritcl::ldflags\fR
.PP
.PP
Less obvious, yet still valid are also
.TP
\fBcritcl::ccode\fR
.TP
\fBcritcl::ccommand\fR
.TP
\fBcritcl::cdata\fR
.TP
\fBcritcl::cproc\fR
.TP
\fBcritcl::csources\fR
.TP
\fBcritcl::ctsources\fR
.PP
and pretty much everything else you can imagine\&.
.SS "LICENSE INVOKED"
When writing packages it is always good manners to provide prospective
users with the license the package is under, so that they can decide
whether they truly want to use the package, or not\&.
.PP
As critcl-based packages often consist of only a single file a
nice way of doing that is to embed the license in that file\&. By using
a critcl command, namely \fBcritcl::license\fR this information is
then also available to the critcl application, which can put it into a
standard location, i\&.e\&. "\fIlicense\&.terms\fR", of the generated
packages\&.
.PP
\fII currently have no specific example to demonstrate the command\&.\fR
.SH "BUILDING CRITCL PACKAGES"
This is the section for developers having to generate packages from
"\fI\&.critcl\fR" files, i\&.e binaries for deployment,
.SS "GETTING HELP \&.\&.\&."
\&.\&.\&. Is easy\&. Running
.CS


    critcl -help

.CE
prints the basics of using the application to \fBstdout\fR\&.
.SS "PRE-FILLING THE RESULT CACHE"
The default mode of the \fBcritcl\fR application is to take a series
of "\fI\&.critcl\fR" files, build their binaries, and leave them behind
in the result cache\&. When the files are later actually used the
compile and link steps can be skipped, leading to shorter load times\&.
.PP
The command line for this is
.CS


    critcl foo\&.tcl

.CE
or, to process multiple files
.CS


    critcl foo\&.tcl bar\&.tcl \&.\&.\&.

.CE
One thing to be aware of, should \fBcritcl\fR find that the cache
already contains the results for the input files, no building will be
done\&. If you are sure that these results are outdated use the option
\fB-force\fR to force(sic!) \fBcritcl\fR to rebuild the binaries\&.
.CS


    critcl -force foo\&.tcl

.CE
For debugging purposes it may be handy to see the generated
intermediate "\fI\&.c\fR" files as well\&. Their removal from the cache can
be prevented by specifying the option \fB-keep\fR\&.
.CS


    critcl -keep foo\&.tcl

.CE
These can be combined, of course\&.
.SS "BUILDING A PACKAGE"
To build the binary package for a "\fI\&.critcl\fR" file, instead of
\fBPre-Filling The Result Cache\fR, simply specify the option
\fB-pkg\fR\&.
.CS


    critcl -pkg foo\&.tcl

.CE
This will geneate a package named \fBfoo\fR\&.
A simpler alternative to the above is
.CS


    critcl -pkg foo

.CE
The application will automatically assume that the input file to look
for is "\fIfoo\&.tcl\fR"\&.
.PP
But what when the name of the input file is not the name of the
package to build ? This we can handle as well:
.CS


    critcl -pkg foo bar\&.tcl

.CE
The argument \fBfoo\fR specifies the name, and "\fIbar\&.tcl\fR" is
the file to process\&.
.PP
Going back to the very first example, it is of course possible to use
an absolute path to specify the file to process:
.CS


    critcl -pkg /path/to/foo\&.tcl

.CE
The package name derived from that is still \fBfoo\fR\&.
.SS "BUILDING AND INSTALLING A PACKAGE"
Here we assume that you know the basics of how to build a package\&.
If not, please read section \fBBuilding A Package\fR first\&.
.PP
By default \fBcritcl\fR will place all newly-made packages in the
subdirectory "\fIlib\fR" of the current working directory\&.
I\&.e\&. running
.CS


    critcl -pkg foo

.CE
will create the directory "\fIlib/foo\fR" which contains all the files
of the package\&.
.PP
When this behaviour is unwanted the option \fB-libdir\fR is available,
allowing the explicit specification of the destination location to use\&.
.CS


    critcl -pkg -libdir /path/to/packages foo

.CE
A common use might be to not only build the package in question, but
to also immediately install it directly in the path where the user's
\fBtclsh\fR will be able to find it\&.
Assuming, for example, that the \fBtclsh\fR in question is installed
at "\fI/path/to/bin/tclsh\fR", with the packages searched for under
"\fI/path/to/lib\fR" ([\fBinfo library\fR]), the command
.CS


    critcl -pkg -libdir /path/to/lib foo

.CE
will build the package and place it in the directory
"\fI/path/to/lib/foo\fR"\&.
.SS "BUILDING FOR DEBUGGING"
Here we assume that you know the basics of how to build a package\&.
If not, please read section \fBBuilding A Package\fR first\&.
.PP
An important issue, when there is trouble with the package, debugging
becomes necessary a evil\&.
Critcl supports this through the \fB-debug\fR option\&.
Using it enables various build modes which help with that\&.
.PP
For example, to activate the Tcl core's built-in memory debugging
subsystem build your package with
.CS


    critcl -pkg -debug memory foo

.CE
The resulting binary for package \fBfoo\fR will use Tcl's
debug-enabled (de)allocation functions, making them visible to Tcl's
\fBmemory\fR command\&. This of course assumes that the Tcl core used
was also built for memory debugging\&.
.PP
Further, built your package with
.CS


    critcl -pkg -debug symbols foo

.CE
to see the \fBfoo\fR's symbols (types, functions, variables, etc\&.)
when inspecting a "\fIcore\fR" file it is involved in with a symbolic
debugger,
.PP
To activate both memory debugging and symbols use either
.CS


    critcl -pkg -debug all foo

.CE
or
.CS


    critcl -pkg -debug symbols -debug memory foo

.CE
.SS "RETARGETING THE BINARIES"
The configuration settings \fBcritcl\fR uses to drive the compiler,
linker, etc\&. are by default selected based on the platform it is run
on, to generate binaries which properly work on this platform\&.
.PP
There is one main use-case for overriding this selection, which is
done with the option \fB-target\fR:
.IP [1]
Cross-compilation\&. The building of binaries for a platform T
while critcl actually runs on platform B\&.
The standard configuration of \fBcritcl\fR currently has settings for
two cross-compilation targets\&. So, to build 32bit Windows binaries on
a Linux host which has the Xmingw cross-compilation development
environment installed use
.CS


    critcl -pkg -target mingw32 foo

.CE
.IP
Similarly, building a package for use on ARM processors while critcl
is running in an Intel environment use
.CS


    critcl -pkg -target linux-arm foo

.CE
.IP
Note that both configurations assume that the cross-compiling
compiler, linke, etc\&. are found first in the \fBPATH\fR\&.
.PP
.SS "CUSTOM CONFIGURATIONS"
The compiler configurations coming with \fBcritcl\fR currently
cover all hosts having \fBgcc\fR installed (the foremost among
these are Linux and OS X), plus the native compilers of the more
common unix-like operating systems, i\&.e\&. Solaris, HP-UX, and AIX, and,
on the non-unix side, Windows\&.
.PP
Developers using operating systems and compilers outside of this range
will either have to install a \fBgcc\fR-based development
environment, i\&.e\&. get into the covered range, or write their own
custom configuration and then tell \fBcritcl\fR about it\&.
.PP
The latter is the easier part, given that \fBcritcl\fR supports the
option \fB-config\fR whose argument is the path to the file
containing the custom configuration(s)\&. I\&.e\&.
.CS


    critcl -config /path/to/config \&.\&.\&.

.CE
will run \fBcritcl\fR with the custom configuration in
"\fI/path/to/config\fR", with the other options and arguments as
explained in previous sections\&. Depending on the choice of name for
the new configuration(s) this may or may not require a
\fB-target\fR option to select the configuration needed\&.
.PP
For the former, the writing of the custom configuration, the reader is
refered to the section "Configuration Internals" of the
\fICriTcl Package Reference\fR for the necessary details\&.
This is an advanced topic pretty much out of scope for this tutorial
beyond what was already said\&.
.SS "CUSTOM HEADER PATH"
Sometimes the use of \fBcritcl::headers\fR might not be enough for a
package to find its headers\&. Maybe they are outside of the paths
checked by the setup code\&.
To help the application recognizes the option \fB-I\fR which allows
the user to supply a single additional include path to use during the
build phase of the package\&.
.PP
Simply use
.CS


    critcl -I /path/to/header \&.\&.\&.

.CE
and the specified header will be handed to the package to be built\&.
.SS "INTROSPECTION OF TARGETS AND CONFIGURATIONS"
To see a list containing the names of all the available
configurations, run
.CS


    critcl -targets

.CE
The configuration settings for either the default or user-chosen
target can be inspected on \fBstdout\fR with
.CS


    critcl -show

.CE
and
.CS


    critcl -show -target TARGET

.CE
The raw contents of the configuration file used by \fBcritcl\fR
are dumped to \fBstdout\fR with
.CS


    critcl -showall

.CE
All of the above can of course be combined with custom configuration
files\&.
.SH AUTHORS
Jean Claude Wippler, Steve Landers, Andreas Kupries
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain
bugs and other problems\&.
Please report them at \fIhttps://github\&.com/andreas-kupries/critcl/issues\fR\&.
Ideas for enhancements you may have for either package, application,
and/or the documentation are also very welcome and should be reported
at \fIhttps://github\&.com/andreas-kupries/critcl/issues\fR as well\&.
.SH KEYWORDS
C code, Embedded C Code, code generator, compile & run, compiler, dynamic code generation, dynamic compilation, generate package, linker, on demand compilation, on-the-fly compilation
.SH CATEGORY
Glueing/Embedded C code
.SH COPYRIGHT
.nf
Copyright (c) Jean-Claude Wippler
Copyright (c) Steve Landers
Copyright (c) 2011-2018 Andreas Kupries

.fi
