expatapi(3)

πŸ“¦
version 0.9.6 Β· 2 versions
  • 0.9.6 Β· fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, opensuse-leap 16.0 (latest)
  • 0.8.2 Β· fedora 43
, in fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, opensuse-leap 16.0

πŸ’– expatapi β€” bestie edition πŸ’–

okay so this is expatapi(3), a page from the Tcl manual, and it's literally about the C-level plumbing that lets you bolt your own event handlers onto tDOM's Tcl expat parser objects. grab a snack, we're going in 🫢


✨ NAME ✨

CheckExpatParserObj, CHandlerSetInstall, CHandlerSetRemove, CHandlerSetCreate, CHandlerSetGetUserData, GetExpatInfo β€” these are the functions that create, install and remove expat parser object extensions. (yes CHandlerSetGet lives here too, she's just not in the roll call, we'll meet her down in DESCRIPTION πŸ’…)


πŸ¦‹ SYNOPSIS πŸ¦‹

#include <tclexpat.h>

int
CheckExpatParserObj (interp, nameObj)

int
CHandlerSetInstall (interp, expatObj, handlerSet)

int
CHandlerSetRemove (interp, expatObj, handlerSetName)

CHandlerSet*
CHandlerSetCreate (handlerSetName)

CHandlerSet*
CHandlerSetGet (interp, expatObj, handlerSetName)

void*
CHandlerSetGetUserData (interp, expatObj, handlerSetName)

TclGenExpatInfo*
GetExpatInfo (interp, expatObj)

🌸 ARGUMENTS 🌸

  • Tcl_Interp *interp (in) β€” the interpreter that's holding the expat parser object. she's the main character, everything happens in her.
  • Tcl_Obj *expatObj (in) β€” a Tcl Object holding the command name of the expat parser object you wanna query or modify.
  • char *handlerSetName (in) β€” the identifier of the handler set. like her @ handle but for C structs.
  • CHandlerSet *handlerSet (in) β€” a pointer to a C handler set.
  • Tcl_Obj *nameObj β€” a Tcl Object holding the name of a expat parser object.

πŸ‘‘ DESCRIPTION πŸ‘‘

the functions on this page let you add C level coded event handlers to a tDOM Tcl expat parser object. and here's the slay part: one single tDOM Tcl expat parser object can have several Tcl scripts and C functions attached to one specific event. when that event happens, the Tcl scripts go first, then the C functions for that event get called in turn. order matters, bestie, it's giving a little queue 🌈

a tDOM Tcl expat parser extension is literally just an ordinary Tcl extension β€” loaded like every other Tcl extension, no special treatment. the one requirement? it must install at least one new Tcl Level command that manipulates a tDOM Tcl expat parser object. that's the whole vibe check.

a C level handler set is a data structure like this:

typedef struct CHandlerSet {
    struct CHandlerSet *nextHandlerSet;
    char *name;                     /* refname of the handler set */
    int ignoreWhiteCDATAs;          /* ignore 'white' CDATA sections */

    void *userData;                 /* Handler set specific Data Structure;
                                       the C handler set extension has to
                                       malloc the needed structure in his
                                       init func and has to provide a
                                       cleanup func (to free it). */

    CHandlerSet_userDataReset        resetProc;
    CHandlerSet_userDataFree         freeProc;

    /* C func for element start */
    XML_StartElementHandler          elementstartcommand;
    /* C func for element end */
    XML_EndElementHandler            elementendcommand;
    /* C func for character data */
    XML_CharacterDataHandler         datacommand;
    /* C func for namespace decl start */
    XML_StartNamespaceDeclHandler    startnsdeclcommand;
    /* C func for namespace decl end */
    XML_EndNamespaceDeclHandler      endnsdeclcommand;
    /* C func for processing instruction */
    XML_ProcessingInstructionHandler picommand;
    /* C func for default data */
    XML_DefaultHandler               defaultcommand;
    /* C func for unparsed entity declaration */
    XML_NotationDeclHandler          notationcommand;
    /* C func for external entity */
    XML_ExternalEntityRefHandler     externalentitycommand;
    /* C func for unknown encoding */
    XML_UnknownEncodingHandler       unknownencodingcommand;
    /* C func for comments */
    XML_CommentHandler               commentCommand;
    /* C func for "not standalone" docs */
    XML_NotStandaloneHandler         notStandaloneCommand;
    /* C func for CDATA section start */
    XML_StartCdataSectionHandler     startCdataSectionCommand;
    /* C func for CDATA section end */
    XML_EndCdataSectionHandler       endCdataSectionCommand;
    /* C func for !ELEMENT decl's */
    XML_ElementDeclHandler           elementDeclCommand;
    /* C func for !ATTLIST decl's */
    XML_AttlistDeclHandler           attlistDeclCommand;
    /* C func for !DOCTYPE decl's */
    XML_StartDoctypeDeclHandler      startDoctypeDeclCommand;
    /* C func for !DOCTYPE decl ends */
    XML_EndDoctypeDeclHandler        endDoctypeDeclCommand;
    /* C func for !ENTITY decls's */
    XML_EntityDeclHandler            entityDeclCommand;
} CHandlerSet;

the types and arguments of those event functions (the XML_* ones) are exactly the same as the expat lib handler functions, and they're described in detail in expat.h β€” go look there, i'm not retyping expat's whole lore πŸ’€. your extension only has to provide the handler functions it actually needs. leaving unused handler slots untouched is perfectly OK β€” CHandlerSetCreate initializes them all to NULL for you. so you can be a minimalist, it's fine.

the name of this structure is what identifies the handler set. that's her whole identity fr fr.

if the flag ignoreWhiteCDATAs is set, then element content that contains only whitespace does not get reported through the datacommand. bye bye, blank noise 🧚

the userData element points to the handler set specific data. the event handler functions get called with this pointer as their userData argument. very much a "carry your own snacks" situation.

resetProc and freeProc must have arguments that match the type

void (Tcl_Interp *interp, void *userData)

resetProc gets called when the parser is reset with <parserObj> reset, and it should do whatever cleanup and reinitializing is needed to get the C handler set ready for a new XML document. freeProc gets called if the parser is deleted, and it should do memory cleanup and whatever else. don't skip these, bestie, that's how you leak 🫠

CHandlerSetCreate creates a C handler set, gives it the name name, and initializes every other element to NULL.

CHandlerSetInstall adds the handlerSet to the parser expatObj. the parser has to be a tDOM Tcl expat parser object in the interpreter interp. the name of the C handler set has to be unique for that parser. return values:

  • 0 β€” success, we ate πŸ’…
  • 1 β€” if expatObj isn't a parser object in the interpreter interp
  • 2 β€” if this parser already has a C handler set with the handlerSet name

CHandlerSetRemove removes the C handler set referenced by handlerSetName from the parser expatObj. the parser has to be a tDOM Tcl expat parser object in the interpreter interp. CHandlerSetRemove calls the freeProc function of the C handler set structure, removes the handler set from the C handler set list, and frees the handler structure. return values:

  • 0 β€” success
  • 1 β€” if expatObj isn't a parser object in the interpreter interp
  • 2 β€” if this parser hasn't got a C handler set named handlerSetName

CheckExpatParserObj returns 1 if nameObj is a tDOM Tcl expat parser object in the interpreter interp, otherwise it returns 0. example:

int
TclExampleObjCmd(dummy, interp, objc, objv)
     ClientData dummy;
     Tcl_Interp *interp;
     int objc;
     Tcl_Obj *const objv[];
{
    char          *method;
    CHandlerSet   *handlerSet;
    int            methodIndex, result;
    simpleCounter *counter;

    static 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;
    }
    /* ... */

CHandlerSetGet returns a pointer to the C handler Set referenced by the name handlerSetName of the parser object expatObj. expatObj has to be an expat parser object in the interpreter interp. returns NULL in case of error. (there she is πŸ‘‘)

CHandlerSetGetUserData returns a pointer to the userData of the C handler set referenced by the name handlerSetName of the parser object expatObj. expatObj has to be an expat parser object in the interpreter interp. returns NULL in case of error.

GetExpatInfo is a lil helper function that returns a pointer to the TclGenExpatInfo structure of the tDOM Tcl expat parser object expatObj. the expatObj has to be a tDOM Tcl expat parser object in the interpreter interp. this is most useful when you wanna set the application status of the parser object.

want receipts? see the simple but full functionally example in the extensions/example dir, or the more complex example tnc in the extensions/tnc dir (that one's a simple DTD validation extension). go look, they're iconic ✨


πŸŽ€ SEE ALSO πŸŽ€

expat


⭐ KEYWORDS ⭐

C handler set


okay that's the whole page, you're officially expat-api-pilled πŸ¦‹ this was expatapi(3) from Tcl β€” the footer's just the name Tcl and the page tag expatapi(3), no cap. go forth and handle those events, bestie, you're gonna slay πŸ’–πŸ’…

πŸ“¦ where this page comes from