1 2#include <tcl.h> 3#include <string.h> 4#include <expat.h> 5#include <tclexpat.h> 6 7/* 8 * Beginning with 8.4, Tcl API is CONST'ified 9 */ 10#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION <= 3) 11# define CONST84 12#endif 13 14 15typedef struct simpleCounter 16{ 17 int elementCounter; 18} simpleCounter; 19 20static char example_usage[] = 21 "Usage example <expat parser obj> <subCommand>, where subCommand can be: \n" 22 " enable \n" 23 " getresult \n" 24 " remove \n" 25 ; 26 27 28 29/* 30 *---------------------------------------------------------------------------- 31 * 32 * ExampleElementStartCommand -- 33 * 34 * This procedure is called for every element start event 35 * while parsing XML Data with an "example" enabled tclexpat 36 * parser. 37 * 38 * Results: 39 * None. 40 * 41 * Side effects: 42 * Uses the "userData" field as int and increments it by every call. 43 * 44 *---------------------------------------------------------------------------- 45 */ 46 47void 48ExampleElementStartCommand (userData, name, atts) 49 void *userData; 50 const char *name; 51 const char **atts; 52{ 53 simpleCounter *counter = (simpleCounter*) userData; 54 55 counter->elementCounter++; 56} 57 58 59/* 60 *---------------------------------------------------------------------------- 61 * 62 * ExampleResetProc 63 * 64 * Called for C handler set specific reset actions in case of 65 * parser reset. 66 * 67 * Results: 68 * None. 69 * 70 * Side effects: 71 * Resets the "userData" of the C handler set parser extension. 72 * 73 *---------------------------------------------------------------------------- 74 */ 75 76void 77ExampleResetProc (interp, userData) 78 Tcl_Interp *interp; 79 void *userData; 80{ 81 simpleCounter *counter = (simpleCounter*) userData; 82 83 counter->elementCounter = 0; 84} 85 86 87 88/* 89 *---------------------------------------------------------------------------- 90 * 91 * ExampleFreeProc 92 * 93 * Called for C handler set specific cleanup in case of parser 94 * delete. 95 * 96 * Results: 97 * None. 98 * 99 * Side effects: 100 * C handler set specific userData gets free'd. 101 * 102 *---------------------------------------------------------------------------- 103 */ 104 105void 106ExampleFreeProc (interp, userData) 107 Tcl_Interp *interp; 108 void *userData; 109{ 110 free (userData); 111} 112 113 114/* 115 *---------------------------------------------------------------------------- 116 * 117 * TclExampleObjCmd -- 118 * 119 * This procedure is invoked to process the "example" command. 120 * 121 * Results: 122 * A standard Tcl result. 123 * 124 * Side effects: 125 * The expat parser object provided as argument is enhanced by 126 * by the "example" handler set. 127 * 128 *---------------------------------------------------------------------------- 129 */ 130 131int 132TclExampleObjCmd(dummy, interp, objc, objv) 133 ClientData dummy; 134 Tcl_Interp *interp; 135 int objc; 136 Tcl_Obj *CONST objv[]; 137{ 138 char *method; 139 CHandlerSet *handlerSet; 140 int methodIndex, result; 141 simpleCounter *counter; 142 143 144 static CONST84 char *exampleMethods[] = { 145 "enable", "getresult", "remove", 146 NULL 147 }; 148 enum exampleMethod { 149 m_enable, m_getresult, m_remove 150 }; 151 152 if (objc != 3) { 153 Tcl_WrongNumArgs (interp, 1, objv, example_usage); 154 return TCL_ERROR; 155 } 156 157 if (!CheckExpatParserObj (interp, objv[1])) { 158 Tcl_SetResult (interp, "First argument has to be a expat parser object", NULL); 159 return TCL_ERROR; 160 } 161 162 method = Tcl_GetStringFromObj (objv[2], NULL); 163 if (Tcl_GetIndexFromObj (interp, objv[2], exampleMethods, "method", 0, 164 &methodIndex) != TCL_OK) 165 { 166 Tcl_SetResult (interp, example_usage, NULL); 167 return TCL_ERROR; 168 } 169 170 switch ((enum exampleMethod) methodIndex) { 171 case m_enable: 172 counter = (simpleCounter *) malloc (sizeof (simpleCounter)); 173 counter->elementCounter = 0; 174 175 handlerSet = CHandlerSetCreate ("example"); 176 handlerSet->userData = counter; 177 handlerSet->resetProc = ExampleResetProc; 178 handlerSet->freeProc = ExampleFreeProc; 179 handlerSet->elementstartcommand = ExampleElementStartCommand; 180 181 result = CHandlerSetInstall (interp, objv[1], handlerSet); 182 if (result == 1) { 183 /* This should not happen if CheckExpatParserObj() is used. */ 184 Tcl_SetResult (interp, "argument has to be a expat parser object", NULL); 185 return TCL_ERROR; 186 } 187 if (result == 2) { 188 Tcl_SetResult (interp, "there is already a C handler set with this name installed", NULL); 189 /* In error case malloc'ed memory should be free'ed */ 190 free (handlerSet->name); 191 Tcl_Free ( (char *) handlerSet); 192 return TCL_ERROR; 193 } 194 return TCL_OK; 195 case m_getresult: 196 counter = CHandlerSetGetUserData (interp, objv[1], "example"); 197 Tcl_SetIntObj (Tcl_GetObjResult (interp), counter->elementCounter); 198 return TCL_OK; 199 case m_remove: 200 result = CHandlerSetRemove (interp, objv[1], "example"); 201 if (result == 1) { 202 /* This should not happen if CheckExpatParserObj() is used. */ 203 Tcl_SetResult (interp, "argument has to be a expat parser object", NULL); 204 return TCL_ERROR; 205 } 206 if (result == 2) { 207 Tcl_SetResult (interp, "expat parser obj hasn't a C handler set named \"example\"", NULL); 208 return TCL_ERROR; 209 } 210 return TCL_OK; 211 default: 212 Tcl_SetResult (interp, "unknown method", NULL); 213 return TCL_ERROR; 214 } 215 216} 217 218/* 219 *---------------------------------------------------------------------------- 220 * 221 * Example_Init -- 222 * 223 * Initialization routine for loadable module 224 * 225 * Results: 226 * None. 227 * 228 * Side effects: 229 * Defines "example" enhancement command for expat parser obj 230 * 231 *---------------------------------------------------------------------------- 232 */ 233 234int 235Example_Init (interp) 236 Tcl_Interp *interp; 237{ 238 Tcl_PkgRequire (interp, "expat", "2.0", 0); 239 Tcl_CreateObjCommand (interp, "example", TclExampleObjCmd, NULL, NULL ); 240 Tcl_PkgProvide (interp, "example", "1.0"); 241} 242 243