#include <tdom.h>
#include <string.h>
/*
* Beginning with 8.4, Tcl API is CONST'ified
*/
#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION <= 3)
# define CONST84
#endif
extern char *Tdom_InitStubs (Tcl_Interp *interp, char *version, int exact);
typedef struct simpleCounter
{
int elementCounter;
} simpleCounter;
static char example_usage[] =
"Usage example <expat parser obj> <subCommand>, where subCommand can be: \n"
" enable \n"
" getresult \n"
" remove \n"
;
/*
*----------------------------------------------------------------------------
*
* ExampleElementStartCommand --
*
* This procedure is called for every element start event
* while parsing XML Data with an "example" enabled tclexpat
* parser.
*
* Results:
* None.
*
* Side effects:
* Uses the "userData" field as int and increments it by every call.
*
*----------------------------------------------------------------------------
*/
void
ExampleElementStartCommand (userData, name, atts)
void *userData;
const char *name;
const char **atts;
{
simpleCounter *counter = (simpleCounter*) userData;
counter->elementCounter++;
}
/*
*----------------------------------------------------------------------------
*
* ExampleResetProc
*
* Called for C handler set specific reset actions in case of
* parser reset.
*
* Results:
* None.
*
* Side effects:
* Resets the "userData" of the C handler set parser extension.
*
*----------------------------------------------------------------------------
*/
void
ExampleResetProc (interp, userData)
Tcl_Interp *interp;
void *userData;
{
simpleCounter *counter = (simpleCounter*) userData;
counter->elementCounter = 0;
}
/*
*----------------------------------------------------------------------------
*
* ExampleFreeProc
*
* Called for C handler set specific cleanup in case of parser
* delete.
*
* Results:
* None.
*
* Side effects:
* C handler set specific userData gets free'd.
*
*----------------------------------------------------------------------------
*/
void
ExampleFreeProc (interp, userData)
Tcl_Interp *interp;
void *userData;
{
free (userData);
}
/*
*----------------------------------------------------------------------------
*
* TclExampleObjCmd --
*
* This procedure is invoked to process the "example" command.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* The expat parser object provided as argument is enhanced by
* by the "example" handler set.
*
*----------------------------------------------------------------------------
*/
int
TclExampleObjCmd(dummy, interp, objc, objv)
ClientData dummy;
Tcl_Interp *interp;
int objc;
Tcl_Obj *CONST objv[];
{
CHandlerSet *handlerSet;
int methodIndex, result;
simpleCounter *counter;
static CONST84 char *exampleMethods[] = {
"enable", "getresult", "remove",
NULL
};
enum exampleMethod {
m_enable, m_getresult, m_remove
};
if (objc != 3) {
Tcl_WrongNumArgs (interp, 1, objv, example_usage);
return TCL_ERROR;
}
if (!CheckExpatParserObj (interp, objv[1])) {
Tcl_SetResult (interp, "First argument has to be a expat parser object", NULL);
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj (interp, objv[2], exampleMethods, "method", 0,
&methodIndex) != TCL_OK)
{
Tcl_SetResult (interp, example_usage, NULL);
return TCL_ERROR;
}
switch ((enum exampleMethod) methodIndex) {
case m_enable:
counter = (simpleCounter *) malloc (sizeof (simpleCounter));
counter->elementCounter = 0;
handlerSet = CHandlerSetCreate ("example");
handlerSet->userData = counter;
handlerSet->resetProc = ExampleResetProc;
handlerSet->freeProc = ExampleFreeProc;
handlerSet->elementstartcommand = ExampleElementStartCommand;
result = CHandlerSetInstall (interp, objv[1], handlerSet);
if (result == 1) {
/* This should not happen if CheckExpatParserObj() is used. */
Tcl_SetResult (interp, "argument has to be a expat parser object", NULL);
return TCL_ERROR;
}
if (result == 2) {
Tcl_SetResult (interp, "there is already a C handler set with this name installed", NULL);
/* In error case malloc'ed memory should be free'ed */
free (handlerSet->name);
Tcl_Free ( (char *) handlerSet);
return TCL_ERROR;
}
return TCL_OK;
case m_getresult:
counter = CHandlerSetGetUserData (interp, objv[1], "example");
Tcl_SetIntObj (Tcl_GetObjResult (interp), counter->elementCounter);
return TCL_OK;
case m_remove:
result = CHandlerSetRemove (interp, objv[1], "example");
if (result == 1) {
/* This should not happen if CheckExpatParserObj() is used. */
Tcl_SetResult (interp, "argument has to be a expat parser object", NULL);
return TCL_ERROR;
}
if (result == 2) {
Tcl_SetResult (interp, "expat parser obj hasn't a C handler set named \"example\"", NULL);
return TCL_ERROR;
}
return TCL_OK;
default:
Tcl_SetResult (interp, "unknown method", NULL);
return TCL_ERROR;
}
}
/*
*----------------------------------------------------------------------------
*
* Example_Init --
*
* Initialization routine for loadable module
*
* Results:
* None.
*
* Side effects:
* Defines "example" enhancement command for expat parser obj
*
*----------------------------------------------------------------------------
*/
int
Example_Init (interp)
Tcl_Interp *interp;
{
#ifdef USE_TCL_STUBS
if (Tcl_InitStubs(interp, "8", 0) == NULL) {
return TCL_ERROR;
}
#endif
#ifdef USE_TDOM_STUBS
if (Tdom_InitStubs(interp, "0.8", 0) == NULL) {
return TCL_ERROR;
}
#endif
Tcl_PkgRequire (interp, "tdom", "0.8.0", 0);
Tcl_CreateObjCommand (interp, "example", TclExampleObjCmd, NULL, NULL );
Tcl_PkgProvide (interp, "example", "1.0");
return TCL_OK;
}