1/*
2 * tclexpat.c --
3 *
4 *	TclXML driver for James Clark's expat XML parser
5 *
6 * Copyright (c) 1998-2003 Steve Ball, Zveno Pty Ltd
7 *
8 * Zveno Pty Ltd makes this software and associated documentation
9 * available free of charge for any purpose.  You may make copies
10 * of the software but you must include all of this notice on any copy.
11 *
12 * Zveno Pty Ltd does not warrant that this software is error free
13 * or fit for any purpose.  Zveno Pty Ltd disclaims any liability for
14 * all claims, expenses, losses, damages and costs any user may incur
15 * as a result of using, copying or modifying the software.
16 *
17 * $Id: tclexpat.c,v 1.15 2003/02/25 04:09:00 balls Exp $
18 *
19 */
20
21#include <tcl.h>
22#include "tclxml.h"
23#include <xmlparse.h>
24
25#undef TCL_STORAGE_CLASS
26#define TCL_STORAGE_CLASS DLLEXPORT
27
28/*
29 * The structure below is used to refer to an expat parser object.
30 */
31
32typedef struct TclExpatInfo {
33  XML_Parser parser;		/* The expat parser structure */
34  Tcl_Interp *interp;		/* Interpreter for this instance */
35
36  TclXML_Info *xmlinfo;		/* Generic data structure */
37
38} TclExpatInfo;
39
40/*
41 * Prototypes for procedures defined later in this file:
42 */
43
44static ClientData TclExpatCreate _ANSI_ARGS_((Tcl_Interp *interp,
45                    TclXML_Info *xmlinfo));
46static ClientData TclExpatCreateEntityParser _ANSI_ARGS_((
47                    Tcl_Interp *interp, ClientData clientData));
48static int	TclExpatDelete _ANSI_ARGS_((ClientData clientData));
49static int	TclExpatParse _ANSI_ARGS_((ClientData clientData,
50                    char *data, int len, int final));
51static int	TclExpatConfigure _ANSI_ARGS_((ClientData clientdata,
52                    int objc, Tcl_Obj *CONST objv[]));
53static int	TclExpatCget _ANSI_ARGS_((ClientData clientData,
54                    int objc, Tcl_Obj *CONST objv[]));
55static int	TclExpatGet _ANSI_ARGS_((ClientData clientData,
56                    int objc, Tcl_Obj *CONST objv[]));
57
58static void	TclExpatElementStartHandler _ANSI_ARGS_((
59	            void *userData,
60		    const XML_Char *name,
61		    const XML_Char **atts));
62static void	TclExpatElementEndHandler _ANSI_ARGS_((
63                    void *userData,
64		    const XML_Char *name));
65static void	TclExpatCharacterDataHandler _ANSI_ARGS_((
66                    void *userData,
67		    const XML_Char *s,
68		    int len));
69static void	TclExpatProcessingInstructionHandler _ANSI_ARGS_((
70                    void *userData,
71		    const XML_Char *target,
72		    const XML_Char *data));
73static void	TclExpatDefaultHandler _ANSI_ARGS_((
74                    void *userData,
75		    const XML_Char *s,
76		    int len));
77static void	TclExpatUnparsedDeclHandler _ANSI_ARGS_((
78		    void *userData,
79		    const XML_Char *entityName,
80		    const XML_Char *base,
81		    const XML_Char *systemId,
82		    const XML_Char *publicId,
83		    const XML_Char *notationName));
84static void	TclExpatNotationDeclHandler _ANSI_ARGS_((
85		    void *userData,
86		    const XML_Char *notationName,
87		    const XML_Char *base,
88		    const XML_Char *systemId,
89		    const XML_Char *publicId));
90static void	TclExpatCommentHandler _ANSI_ARGS_((
91		    void *userData,
92		    const XML_Char *data));
93static int	TclExpatNotStandaloneHandler _ANSI_ARGS_((
94		    void *userData));
95static void	TclExpatStartCdataSectionHandler _ANSI_ARGS_((
96		    void *userData));
97static void	TclExpatEndCdataSectionHandler _ANSI_ARGS_((
98		    void *userData));
99static void	TclExpatElementDeclHandler _ANSI_ARGS_((
100		    void *userData,
101		    const XML_Char *name,
102		    XML_Char ***contentspec));
103static void	TclExpatAttlistDeclHandler _ANSI_ARGS_((
104		    void *userData,
105		    const XML_Char *name,
106		    XML_Char ***attributes));
107static void	TclExpatStartDoctypeDeclHandler _ANSI_ARGS_((
108		    void *userData,
109		    const XML_Char *doctypeName));
110static void	TclExpatEndDoctypeDeclHandler _ANSI_ARGS_((
111		    void *userData));
112
113static int	TclExpatExternalEntityRefHandler _ANSI_ARGS_((
114     XML_Parser parser,
115     const XML_Char *context,
116     const XML_Char *base,
117     const XML_Char *systemId,
118     const XML_Char *publicId));
119static int	TclExpatUnknownEncodingHandler _ANSI_ARGS_((
120     void *encodingHandlerData,
121     const XML_Char *name,
122     XML_Encoding *info
123));
124
125EXTERN int	Tclexpat_Init _ANSI_ARGS_((Tcl_Interp *interp));
126
127/*
128 *----------------------------------------------------------------------------
129 *
130 * Tclexpat_Init --
131 *
132 *	Initialisation routine for loadable module
133 *
134 * Results:
135 *	None.
136 *
137 * Side effects:
138 *	Registers xerces XML parser.
139 *
140 *----------------------------------------------------------------------------
141 */
142
143int
144Tclexpat_Init (interp)
145     Tcl_Interp *interp; /* Interpreter to initialise. */
146{
147  TclXML_ParserClassInfo *classinfo;
148
149#ifdef USE_TCL_STUBS
150  if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
151    return TCL_ERROR;
152  }
153#endif
154#ifdef USE_TCLXML_STUBS
155  if (TclXML_InitStubs(interp, TCLXML_VERSION, 1) == NULL) {
156    return TCL_ERROR;
157  }
158#endif
159
160  classinfo = (TclXML_ParserClassInfo *) ckalloc(sizeof(TclXML_ParserClassInfo));
161  classinfo->name = Tcl_NewStringObj("expat", -1);
162  classinfo->create = TclExpatCreate;
163  classinfo->createCmd = NULL;
164  classinfo->createEntity = TclExpatCreateEntityParser;
165  classinfo->createEntityCmd = NULL;
166  classinfo->parse = TclExpatParse;
167  classinfo->parseCmd = NULL;
168  classinfo->configure = TclExpatConfigure;
169  classinfo->configureCmd = NULL;
170  classinfo->get = TclExpatGet;
171  classinfo->getCmd = NULL;
172  classinfo->destroy = TclExpatDelete;
173  classinfo->destroyCmd = NULL;
174  classinfo->reset = NULL;
175  classinfo->resetCmd = NULL;
176
177  if (TclXML_RegisterXMLParser(interp, classinfo) != TCL_OK) {
178    Tcl_SetResult(interp, "unable to register parser", NULL);
179    return TCL_ERROR;
180  }
181
182  if (Tcl_PkgProvide(interp, "xml::expat", TCLXML_VERSION) != TCL_OK) {
183    return TCL_ERROR;
184  }
185
186  return TCL_OK;
187}
188
189/*
190 *----------------------------------------------------------------------------
191 *
192 * TclExpatCreate --
193 *
194 *	Create an expat parser instance.
195 *
196 * Results:
197 *	Standard Tcl result.
198 *
199 * Side effects:
200 *	This creates an expat parser.
201 *
202 *----------------------------------------------------------------------------
203 */
204
205static ClientData
206TclExpatCreate(interp, xmlinfo)
207     Tcl_Interp *interp;
208     TclXML_Info *xmlinfo;
209{
210  TclExpatInfo *expat;
211
212  /*
213   * Create the data structures for this parser.
214   */
215
216  if (!(expat = (TclExpatInfo *) ckalloc(sizeof(TclExpatInfo)))) {
217    ckfree((char *)expat);
218    Tcl_SetResult(interp, "unable to create parser", NULL);
219    return NULL;
220  }
221  expat->interp = interp;
222  expat->xmlinfo = xmlinfo;
223
224  if (!(expat->parser = XML_ParserCreate(NULL))) {
225    Tcl_SetResult(interp, "unable to create expat parser", NULL);
226    ckfree((char *)expat);
227    return NULL;
228  }
229
230  /*
231   * Set all handlers for the parser.
232   */
233
234  XML_SetElementHandler(expat->parser, TclExpatElementStartHandler,
235			TclExpatElementEndHandler);
236  XML_SetCharacterDataHandler(expat->parser, TclExpatCharacterDataHandler);
237  XML_SetProcessingInstructionHandler(expat->parser,
238	  TclExpatProcessingInstructionHandler);
239  XML_SetDefaultHandler(expat->parser, TclExpatDefaultHandler);
240
241  XML_SetUnparsedEntityDeclHandler(expat->parser,
242	  TclExpatUnparsedDeclHandler);
243  XML_SetNotationDeclHandler(expat->parser, TclExpatNotationDeclHandler);
244
245  XML_SetExternalEntityRefHandler(expat->parser,
246	  TclExpatExternalEntityRefHandler);
247
248  XML_SetUnknownEncodingHandler(expat->parser, TclExpatUnknownEncodingHandler,
249	  (void *) xmlinfo);
250
251  /* Added by ericm@scriptics.com, 1999.6.25 */
252  /* Tell expat to use the TclExpat comment handler */
253  XML_SetCommentHandler(expat->parser, TclExpatCommentHandler);
254
255  /* Tell expat to use the TclExpat "not standalone" handler */
256  XML_SetNotStandaloneHandler(expat->parser, TclExpatNotStandaloneHandler);
257
258#ifdef TCLXML_CDATASECTIONS
259  /* Tell expat to use the TclExpat CdataSection handlers */
260  XML_SetCdataSectionHandler(expat->parser, TclExpatStartCdataSectionHandler,
261	  TclExpatEndCdataSectionHandler);
262#endif /* TCLXML_CDATASECTIONS */
263
264  /* Tell expat to use the TclExpat Element decl handler */
265  XML_SetElementDeclHandler(expat->parser, TclExpatElementDeclHandler);
266
267  /* Tell expat to use the TclExpat Attlist decl handler */
268  XML_SetAttlistDeclHandler(expat->parser, TclExpatAttlistDeclHandler);
269
270  /* Tell expat to use the TclExpat DOCTYPE decl handlers */
271  XML_SetDoctypeDeclHandler(expat->parser,
272	  TclExpatStartDoctypeDeclHandler,
273	  TclExpatEndDoctypeDeclHandler);
274
275  XML_SetUserData(expat->parser, (void *) expat);
276
277  return (ClientData) expat;
278}
279
280/*
281 *----------------------------------------------------------------------
282 *
283 * TclExpatCreateEntity --
284 *
285 *	Create an expat entity parser, based on the original
286 *      parser referred to by parent.
287 *
288 * Results:
289 *	New external entity parser created and initialized.
290 *
291 * Side effects:
292 *	The TclExpatInfo struct pointed to by expat is modified.
293 *
294 *----------------------------------------------------------------------
295 */
296
297static ClientData
298TclExpatCreateEntityParser(interp, clientData)
299     Tcl_Interp *interp;
300     ClientData clientData;
301{
302  TclExpatInfo *parent = (TclExpatInfo *) clientData;
303  TclExpatInfo *expat;
304
305  if (!(expat = (TclExpatInfo *) ckalloc(sizeof(TclExpatInfo)))) {
306    ckfree((char *)expat);
307    Tcl_SetResult(interp, "unable to create parser", NULL);
308    return NULL;
309  }
310  expat->interp = parent->interp;
311  expat->xmlinfo = parent->xmlinfo;
312
313    if (!(expat->parser = XML_ExternalEntityParserCreate(parent->parser,
314	    (XML_Char *) Tcl_GetUnicode(parent->xmlinfo->context), NULL))) {
315	Tcl_SetResult(interp, "unable to create expat external entity parser",
316		NULL);
317	return NULL;
318    }
319
320    XML_SetUserData(expat->parser, (void *) expat);
321    return (ClientData) expat;
322}
323
324/*
325 *----------------------------------------------------------------------------
326 *
327 * TclExpatDelete --
328 *
329 *	Destroy the expat parser structure.
330 *
331 * Results:
332 *	None.
333 *
334 * Side effects:
335 *	Frees any memory allocated for the XML parser.
336 *
337 *----------------------------------------------------------------------------
338 */
339
340static int
341TclExpatDelete(clientData)
342     ClientData clientData;
343{
344  TclExpatInfo *expat = (TclExpatInfo *) clientData;
345
346  XML_ParserFree(expat->parser);
347  ckfree((char *)expat);
348
349  return TCL_OK;
350}
351
352/*
353 *----------------------------------------------------------------------------
354 *
355 * TclExpatParse --
356 *
357 *	Wrapper to invoke expat parser and check return result.
358 *
359 * Results:
360 *     TCL_OK if no errors, TCL_ERROR otherwise.
361 *
362 * Side effects:
363 *     Sets interpreter result as appropriate.
364 *
365 *----------------------------------------------------------------------------
366 */
367
368static int
369TclExpatParse(clientData, data, len, final)
370     ClientData clientData;
371     char *data;
372     int len;
373{
374  TclExpatInfo *expat = (TclExpatInfo *) clientData;
375  int result;
376  char s[255];
377
378  result = XML_Parse(expat->parser,
379		     data, len,
380		     final);
381
382  if (!result) {
383    Tcl_ResetResult(expat->interp);
384    sprintf(s, "%d", XML_GetCurrentLineNumber(expat->parser));
385    Tcl_AppendResult(expat->interp, "error \"",
386	    XML_ErrorString(XML_GetErrorCode(expat->parser)),
387	    "\" at line ", s, " character ", NULL);
388    sprintf(s, "%d", XML_GetCurrentColumnNumber(expat->parser));
389    Tcl_AppendResult(expat->interp, s, NULL);
390
391    return TCL_ERROR;
392  }
393
394  return TCL_OK;
395}
396
397/*
398 *----------------------------------------------------------------------------
399 *
400 * TclExpatConfigure --
401 *
402 *	Implements instance command for expat class objects.
403 *
404 * Results:
405 *	Depends on the method.
406 *
407 * Side effects:
408 *	Depends on the method.
409 *
410 *----------------------------------------------------------------------------
411 */
412
413static int
414TclExpatConfigure (clientData, objc, objv)
415     ClientData clientData;
416     int objc;
417     Tcl_Obj *CONST objv[];
418{
419  TclExpatInfo *expat = (TclExpatInfo *) clientData;
420
421  static CONST84 char *switches[] = {
422    "-baseurl",
423    "-defaultexpandinternalentities",
424    "-paramentityparsing",
425    (char *) NULL
426  };
427  enum switches {
428    EXPAT_BASE,
429    EXPAT_DEFAULTEXPANDINTERNALENTITIES,
430    EXPAT_PARAMENTITYPARSING,
431  };
432  static CONST84 char *paramEntityParsingValues[] = {
433      "always",
434      "never",
435      "notstandalone"
436  };
437  enum paramEntityParsingValues {
438      EXPAT_PARAMENTITYPARSINGALWAYS,
439      EXPAT_PARAMENTITYPARSINGNEVER,
440      EXPAT_PARAMENTITYPARSINGNOTSTANDALONE
441  };
442
443  int index, value, bool;
444  Tcl_Obj *CONST *objPtr = objv;
445
446  while (objc > 1) {
447    if (Tcl_GetIndexFromObj(expat->interp, objPtr[0], switches,
448			    "switch", 0, &index) != TCL_OK) {
449      Tcl_ResetResult(expat->interp);
450      return TCL_OK;
451    }
452    switch ((enum switches) index) {
453
454      case EXPAT_BASE:			/* -base */
455
456	if (XML_SetBase(expat->parser, (const XML_Char*)Tcl_GetString(objPtr[1])) == 0) {
457	  Tcl_SetResult(expat->interp, "unable to set base URL", NULL);
458	  return TCL_ERROR;
459	}
460	break;
461
462      case EXPAT_DEFAULTEXPANDINTERNALENTITIES:
463
464        /* -defaultexpandinternalentities */
465	/* ericm@scriptics */
466	if (Tcl_GetBooleanFromObj(expat->interp, objPtr[1], &bool) != TCL_OK) {
467	  return TCL_ERROR;
468	}
469
470        XML_SetDefaultExpandInternalEntities(expat->parser, bool);
471
472	break;
473
474      case EXPAT_PARAMENTITYPARSING: /* -paramentityparsing */
475	  /* ericm@scriptics */
476	  if (Tcl_GetIndexFromObj(expat->interp, objPtr[1], paramEntityParsingValues,
477		  "value", 0, &value) != TCL_OK) {
478	      return TCL_ERROR;
479	  }
480	  switch ((enum paramEntityParsingValues) value) {
481	      case EXPAT_PARAMENTITYPARSINGALWAYS:
482		  XML_SetParamEntityParsing(expat->parser,
483			  XML_PARAM_ENTITY_PARSING_ALWAYS);
484		  break;
485	      case EXPAT_PARAMENTITYPARSINGNEVER:
486		  XML_SetParamEntityParsing(expat->parser,
487			  XML_PARAM_ENTITY_PARSING_NEVER);
488		  break;
489	      case EXPAT_PARAMENTITYPARSINGNOTSTANDALONE:
490		  XML_SetParamEntityParsing(expat->parser,
491			  XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
492		  break;
493	  }
494	  break;
495
496    default:
497      return TCL_OK;
498	  break;
499
500    }
501
502    objPtr += 2;
503    objc -= 2;
504
505  }
506
507  return TCL_OK;
508}
509
510/*
511 *----------------------------------------------------------------------------
512 *
513 * TclExpatGet --
514 *
515 *	Returns runtime parser information, depending on option
516 *      ericm@scriptics.com, 1999.6.28
517 *
518 * Results:
519 *	Option value.
520 *
521 * Side effects:
522 *	None.
523 *
524 *----------------------------------------------------------------------------
525 */
526
527static int
528TclExpatGet (clientData, objc, objv)
529     ClientData clientData;
530     int objc;
531     Tcl_Obj *CONST objv[];
532{
533  TclExpatInfo *expat = (TclExpatInfo *) clientData;
534  static CONST84 char *switches[] = {
535    "-specifiedattributecount",
536    "-currentbytecount",
537    "-currentlinenumber",
538    "-currentcolumnnumber",
539    "-currentbyteindex",
540    (char *) NULL
541  };
542  enum switches {
543    EXPAT_SPECIFIEDATTRCOUNT,
544    EXPAT_CURRENTBYTECOUNT,
545    EXPAT_CURRENTLINENUMBER,
546    EXPAT_CURRENTCOLUMNNUMBER,
547    EXPAT_CURRENTBYTEINDEX
548  };
549  int index, doParse = 0;
550  Tcl_Obj *resultPtr;
551
552  if (objc > 1) {
553    Tcl_SetResult(expat->interp, "Only one value may be requested at a time",
554		  TCL_STATIC);
555    return TCL_ERROR;
556  }
557
558  if (Tcl_GetIndexFromObj(expat->interp, objv[0], switches,
559			  "switch", 0, &index) != TCL_OK) {
560    return TCL_ERROR;
561  }
562
563  resultPtr = Tcl_GetObjResult(expat->interp);
564
565  switch ((enum switches) index) {
566
567    case EXPAT_SPECIFIEDATTRCOUNT:
568
569      Tcl_SetIntObj(resultPtr, XML_GetSpecifiedAttributeCount(expat->parser));
570      return TCL_OK;
571      break;
572
573    case EXPAT_CURRENTBYTECOUNT:
574
575      Tcl_SetIntObj(resultPtr, XML_GetCurrentByteCount(expat->parser));
576      return TCL_OK;
577      break;
578
579    case EXPAT_CURRENTLINENUMBER:
580
581      Tcl_SetIntObj(resultPtr, XML_GetCurrentLineNumber(expat->parser));
582      return TCL_OK;
583      break;
584
585    case EXPAT_CURRENTCOLUMNNUMBER:
586
587      Tcl_SetIntObj(resultPtr, XML_GetCurrentColumnNumber(expat->parser));
588      return TCL_OK;
589      break;
590
591    case EXPAT_CURRENTBYTEINDEX:
592
593      Tcl_SetLongObj(resultPtr, XML_GetCurrentByteIndex(expat->parser));
594      return TCL_OK;
595      break;
596
597    default:
598
599      return TCL_ERROR;
600      break;
601  }
602
603  return TCL_ERROR;
604}
605
606/*
607 *----------------------------------------------------------------------------
608 *
609 * TclExpat*Handler --
610 *
611 *	Called by expat for various document features.
612 *
613 * Results:
614 *	None.
615 *
616 * Side Effects:
617 *	Event passed to TclXML generic layer.
618 *
619 *----------------------------------------------------------------------------
620 */
621
622static void TclExpatElementStartHandler(userdata, name, atts)
623     void *userdata;
624     const XML_Char *name;
625     const XML_Char **atts;
626{
627  TclExpatInfo *expat = (TclExpatInfo *) userdata;
628  Tcl_Obj *attListObj;
629  int count;
630
631  attListObj = Tcl_NewListObj(0, NULL);
632  for (count = 0; atts[count]; count += 2) {
633    Tcl_ListObjAppendElement(NULL, attListObj, Tcl_NewStringObj((XML_Char*)atts[count], -1));
634    Tcl_ListObjAppendElement(NULL, attListObj, Tcl_NewStringObj((XML_Char*)atts[count + 1], -1));
635  }
636
637  TclXML_ElementStartHandler(
638        expat->xmlinfo,
639	Tcl_NewStringObj((XML_Char*)name, -1),
640	attListObj);
641}
642
643static void TclExpatElementEndHandler(userdata, name)
644     void *userdata;
645     const XML_Char *name;
646{
647  TclExpatInfo *expat = (TclExpatInfo *) userdata;
648
649  TclXML_ElementEndHandler(
650        expat->xmlinfo,
651	Tcl_NewStringObj((XML_Char*)name, -1));
652}
653
654static void TclExpatCharacterDataHandler(userdata, s, len)
655     void *userdata;
656     const XML_Char *s;
657     int len;
658{
659  TclExpatInfo *expat = (TclExpatInfo *) userdata;
660
661  TclXML_CharacterDataHandler(
662        expat->xmlinfo,
663	Tcl_NewStringObj((XML_Char*)s, len));
664}
665
666static void TclExpatProcessingInstructionHandler(userdata, target, data)
667     void *userdata;
668     const XML_Char *target;
669     const XML_Char *data;
670{
671  TclExpatInfo *expat = (TclExpatInfo *) userdata;
672
673  TclXML_ProcessingInstructionHandler(
674        expat->xmlinfo,
675	Tcl_NewStringObj((XML_Char*)target, -1),
676	Tcl_NewStringObj((XML_Char*)data, -1));
677}
678
679static void TclExpatDefaultHandler(userdata, s, len)
680     void *userdata;
681     const XML_Char *s;
682     int len;
683{
684  TclExpatInfo *expat = (TclExpatInfo *) userdata;
685
686  TclXML_DefaultHandler(
687        expat->xmlinfo,
688	Tcl_NewStringObj((XML_Char*)s, len));
689}
690
691static void TclExpatUnparsedDeclHandler(userdata, entityName, base, systemId, publicId, notationName)
692     void *userdata;
693     const XML_Char *entityName;
694     const XML_Char *base;
695     const XML_Char *systemId;
696     const XML_Char *publicId;
697     const XML_Char *notationName;
698{
699  TclExpatInfo *expat = (TclExpatInfo *) userdata;
700
701  TclXML_UnparsedDeclHandler(
702        expat->xmlinfo,
703	Tcl_NewStringObj((XML_Char*)entityName, -1),
704	Tcl_NewStringObj((XML_Char*)base, -1),
705	Tcl_NewStringObj((XML_Char*)systemId, -1),
706	Tcl_NewStringObj((XML_Char*)publicId, -1),
707	Tcl_NewStringObj((XML_Char*)notationName, -1)
708	);
709}
710
711static void TclExpatNotationDeclHandler(userdata, notationName, base, systemId, publicId)
712     void *userdata;
713     const XML_Char *notationName;
714     const XML_Char *base;
715     const XML_Char *systemId;
716     const XML_Char *publicId;
717{
718  TclExpatInfo *expat = (TclExpatInfo *) userdata;
719
720  TclXML_NotationDeclHandler(
721        expat->xmlinfo,
722	Tcl_NewStringObj((XML_Char*)notationName, -1),
723	Tcl_NewStringObj((XML_Char*)base, -1),
724	Tcl_NewStringObj((XML_Char*)systemId, -1),
725	Tcl_NewStringObj((XML_Char*)publicId, -1)
726	);
727}
728
729static void TclExpatCommentHandler(userdata, data)
730     void *userdata;
731     const XML_Char *data;
732{
733  TclExpatInfo *expat = (TclExpatInfo *) userdata;
734
735  TclXML_CommentHandler(
736        expat->xmlinfo,
737	Tcl_NewStringObj((XML_Char*)data, -1));
738}
739
740static int TclExpatNotStandaloneHandler(userdata)
741     void *userdata;
742{
743  TclExpatInfo *expat = (TclExpatInfo *) userdata;
744
745  return TclXML_NotStandaloneHandler(expat->xmlinfo);
746}
747
748static void TclExpatStartCdataSectionHandler(userdata)
749     void *userdata;
750{
751  TclExpatInfo *expat = (TclExpatInfo *) userdata;
752
753  /*
754   * TclXML makes no distinction between PCDATA and CDATA
755   */
756}
757
758static void
759TclExpatEndCdataSectionHandler(userdata)
760     void *userdata;
761{
762  TclExpatInfo *expat = (TclExpatInfo *) userdata;
763
764  /*
765   * TclXML makes no distinction between PCDATA and CDATA
766   */
767}
768
769/*
770 *----------------------------------------------------------------------------
771 *
772 * TclExpatExternalEntityRefHandler --
773 *
774 *	Called by expat for processing external entity references.
775 *
776 * Results:
777 *	None.
778 *
779 * Side Effects:
780 *	Callback script is invoked.
781 *
782 *----------------------------------------------------------------------------
783 */
784
785static int
786TclExpatExternalEntityRefHandler(parser, context, base, systemId, publicId)
787     XML_Parser parser;
788     const XML_Char *context;
789     const XML_Char *base;
790     const XML_Char *systemId;
791     const XML_Char *publicId;
792{
793  TclExpatInfo *expat = (TclExpatInfo *) XML_GetUserData(parser);
794
795  TclXML_ExternalEntityRefHandler(
796        (ClientData) expat->xmlinfo,
797	Tcl_NewStringObj((XML_Char*)context, -1),
798	Tcl_NewStringObj((XML_Char*)base, -1),
799	Tcl_NewStringObj((XML_Char*)systemId, -1),
800	Tcl_NewStringObj((XML_Char*)publicId, -1));
801
802  return 1;
803}
804
805/*
806 *----------------------------------------------------------------------------
807 *
808 * TclExpatUnknownEncodingHandler --
809 *
810 *	Called by parser instance for processing a reference to a character in an
811 *	unknown encoding.
812 *
813 * Results:
814 *	None.
815 *
816 * Side Effects:
817 *	Callback script is invoked.
818 *
819 *----------------------------------------------------------------------------
820 */
821
822static int
823TclExpatUnknownEncodingHandler(encodingHandlerData, name, info)
824     void *encodingHandlerData;
825     const XML_Char *name;
826     XML_Encoding *info;
827{
828  int result;
829
830  result = TclXML_UnknownEncodingHandler(
831                 encodingHandlerData,
832		 Tcl_NewStringObj((XML_Char*)name, -1),
833		 (ClientData) info);
834
835  return result;
836}
837
838static void TclExpatElementDeclHandler(userdata, name, contentspec)
839     void *userdata;
840     const XML_Char *name;
841     XML_Char ***contentspec;
842{
843  TclExpatInfo *expat = (TclExpatInfo *) userdata;
844  Tcl_Obj *contentspecObj;
845  int count;
846
847  contentspecObj = Tcl_NewListObj(0, NULL);
848  for (count = 0; contentspec[0][count] != NULL; count++) {
849    Tcl_ListObjAppendElement(expat->interp, contentspecObj, Tcl_NewStringObj(contentspec[0][count], -1));
850  }
851
852  TclXML_ElementDeclHandler(
853        expat->xmlinfo,
854	Tcl_NewStringObj((XML_Char*)name, -1),
855	contentspecObj);
856}
857
858static void TclExpatAttlistDeclHandler(userdata, name, attributes)
859     void *userdata;
860     const XML_Char *name;
861     XML_Char ***attributes;
862{
863  TclExpatInfo *expat = (TclExpatInfo *) userdata;
864  Tcl_Obj *attdefnObj;
865  int count;
866
867  attdefnObj = Tcl_NewListObj(0, NULL);
868  for (count = 0; (*attributes)[count] != NULL; count++) {
869    Tcl_ListObjAppendElement(expat->interp, attdefnObj, Tcl_NewStringObj((*attributes)[count], -1));
870  }
871
872  TclXML_AttlistDeclHandler(
873        expat->xmlinfo,
874	Tcl_NewStringObj((XML_Char*)name, -1),
875	attdefnObj);
876}
877
878static void TclExpatStartDoctypeDeclHandler(userdata, name)
879     void *userdata;
880     const XML_Char *name;
881{
882  TclExpatInfo *expat = (TclExpatInfo *) userdata;
883
884  TclXML_StartDoctypeDeclHandler(
885        expat->xmlinfo,
886	Tcl_NewStringObj((XML_Char*)name, -1));
887}
888
889static void TclExpatEndDoctypeDeclHandler(userdata)
890     void *userdata;
891{
892  TclExpatInfo *expat = (TclExpatInfo *) userdata;
893
894  TclXML_EndDoctypeDeclHandler(expat->xmlinfo);
895}
896