Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch parser-defaultcurrent Excluding Merge-Ins

This is equivalent to a diff from ac03b8c44e to d501542ab8

2015-04-01
22:12
Added new expat parser cmd method currentmarkup. check-in: 2b183ffd3f user: rolf tags: trunk
21:46
Added lokal clean-up to every test (as it should be) and removed general clean-up, which was interfered by other test helper procs. Closed-Leaf check-in: d501542ab8 user: rolf tags: parser-defaultcurrent
21:35
Corrected typo. check-in: 6f3daefad3 user: rolf tags: parser-defaultcurrent
18:12
Plugged memory leaks in case of defective XPath expressions. check-in: 6cae756100 user: rolf tags: trunk
00:44
Merged from trunk. check-in: 9a616f0d21 user: rolf tags: parser-defaultcurrent
2015-03-26
11:29
Enforce value range for -indentAttrs value. check-in: ac03b8c44e user: rolf tags: trunk
01:23
Added option -indentAttrs to the domDoc/domNode method asXML. check-in: 3245a04ed5 user: rolf tags: trunk

Changes to doc/expat.xml.

583
584
585
586
587
588
589










590
591
592
593
594
595
596
          <desc><p>Return the current configuration value option for the
parser.</p> 
          <p>If the -handlerset option is used, the configuration for the
named handler set is returned.</p>
          </desc>
        </commanddef>











        <commanddef>
          <command><cmd>parser</cmd> <method>free</method></command>

          <desc><p>Deletes the parser and the parser command. A parser cannot
be freed from within one of its handler callbacks (neither directly nor
indirectly) and will raise a tcl error in this case.</p></desc>
        </commanddef>







>
>
>
>
>
>
>
>
>
>







583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
          <desc><p>Return the current configuration value option for the
parser.</p> 
          <p>If the -handlerset option is used, the configuration for the
named handler set is returned.</p>
          </desc>
        </commanddef>

        <commanddef>
          <command><cmd>parser</cmd> <method>currentmarkup</method></command>

          <desc><p>Returns the current markup as found in the XML, if
          called from within one of its markup event handler script
          (-elementstartcommand, -elementendcommand, -commentcommand
          and -processinginstructioncommand). Otherwise it return the
          empty string.</p></desc>
        </commanddef>

        <commanddef>
          <command><cmd>parser</cmd> <method>free</method></command>

          <desc><p>Deletes the parser and the parser command. A parser cannot
be freed from within one of its handler callbacks (neither directly nor
indirectly) and will raise a tcl error in this case.</p></desc>
        </commanddef>

Changes to generic/tclexpat.c.

549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581

582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
    }
    
    /*
     * Set handlers for the parser to routines in this module.
     */

    XML_SetElementHandler(expat->parser,
                          (XML_StartElementHandler) TclGenExpatElementStartHandler,
                          (XML_EndElementHandler) TclGenExpatElementEndHandler);
    XML_SetNamespaceDeclHandler(expat->parser,
                                (XML_StartNamespaceDeclHandler) TclGenExpatStartNamespaceDeclHandler,
                                (XML_EndNamespaceDeclHandler) TclGenExpatEndNamespaceDeclHandler);
    XML_SetCharacterDataHandler(expat->parser,
                                (XML_CharacterDataHandler) TclGenExpatCharacterDataHandler);
    XML_SetProcessingInstructionHandler(expat->parser,
                                        (XML_ProcessingInstructionHandler) TclGenExpatProcessingInstructionHandler);
    XML_SetDefaultHandlerExpand(expat->parser,
                                (XML_DefaultHandler) TclGenExpatDefaultHandler);
    
    XML_SetNotationDeclHandler(expat->parser,
                               (XML_NotationDeclHandler) TclGenExpatNotationDeclHandler);
    XML_SetExternalEntityRefHandler(expat->parser,
                                    (XML_ExternalEntityRefHandler) TclGenExpatExternalEntityRefHandler);
    XML_SetUnknownEncodingHandler(expat->parser,
                                  (XML_UnknownEncodingHandler) TclGenExpatUnknownEncodingHandler,
                                  (void *) expat);
    
    
    XML_SetCommentHandler(expat->parser, TclGenExpatCommentHandler);
    
    XML_SetNotStandaloneHandler(expat->parser, TclGenExpatNotStandaloneHandler);
    
    XML_SetCdataSectionHandler(expat->parser, TclGenExpatStartCdataSectionHandler,

                               TclGenExpatEndCdataSectionHandler);
    
    XML_SetElementDeclHandler(expat->parser, TclGenExpatElementDeclHandler);
    
    XML_SetAttlistDeclHandler(expat->parser, TclGenExpatAttlistDeclHandler);
    
    XML_SetDoctypeDeclHandler(expat->parser,
                              TclGenExpatStartDoctypeDeclHandler,
                              TclGenExpatEndDoctypeDeclHandler);
    
    XML_SetXmlDeclHandler (expat->parser, TclGenExpatXmlDeclHandler);
    
    XML_SetEntityDeclHandler (expat->parser,
                              TclGenExpatEntityDeclHandler);
    if (expat->noexpand) {
        XML_SetDefaultHandlerExpand(expat->parser, NULL);
        XML_SetDefaultHandler(expat->parser,
                              (XML_DefaultHandler) TclGenExpatDefaultHandler);
    } else {
        XML_SetDefaultHandler(expat->parser, NULL);
        XML_SetDefaultHandlerExpand(expat->parser,
                              (XML_DefaultHandler) TclGenExpatDefaultHandler);
    }
    
    XML_SetUserData(expat->parser, (void *) expat);
    
    return TCL_OK;
}








|
|

|
|

|

|
|
<
<

|

|

|

<
<

<
|
|
|
>

<

<

<



<

<



<

|

<

|







549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565


566
567
568
569
570
571
572


573

574
575
576
577
578

579

580

581
582
583

584

585
586
587

588
589
590

591
592
593
594
595
596
597
598
599
    }
    
    /*
     * Set handlers for the parser to routines in this module.
     */

    XML_SetElementHandler(expat->parser,
                          TclGenExpatElementStartHandler,
                          TclGenExpatElementEndHandler);
    XML_SetNamespaceDeclHandler(expat->parser,
                                TclGenExpatStartNamespaceDeclHandler,
                                TclGenExpatEndNamespaceDeclHandler);
    XML_SetCharacterDataHandler(expat->parser,
                                TclGenExpatCharacterDataHandler);
    XML_SetProcessingInstructionHandler(expat->parser,
                                        TclGenExpatProcessingInstructionHandler);
    XML_SetDefaultHandlerExpand(expat->parser, TclGenExpatDefaultHandler);


    XML_SetNotationDeclHandler(expat->parser,
                               TclGenExpatNotationDeclHandler);
    XML_SetExternalEntityRefHandler(expat->parser,
                                    TclGenExpatExternalEntityRefHandler);
    XML_SetUnknownEncodingHandler(expat->parser,
                                  TclGenExpatUnknownEncodingHandler,
                                  (void *) expat);


    XML_SetCommentHandler(expat->parser, TclGenExpatCommentHandler);

    XML_SetNotStandaloneHandler(expat->parser, 
                                TclGenExpatNotStandaloneHandler);
    XML_SetCdataSectionHandler(expat->parser, 
                               TclGenExpatStartCdataSectionHandler,
                               TclGenExpatEndCdataSectionHandler);

    XML_SetElementDeclHandler(expat->parser, TclGenExpatElementDeclHandler);

    XML_SetAttlistDeclHandler(expat->parser, TclGenExpatAttlistDeclHandler);

    XML_SetDoctypeDeclHandler(expat->parser,
                              TclGenExpatStartDoctypeDeclHandler,
                              TclGenExpatEndDoctypeDeclHandler);

    XML_SetXmlDeclHandler (expat->parser, TclGenExpatXmlDeclHandler);

    XML_SetEntityDeclHandler (expat->parser,
                              TclGenExpatEntityDeclHandler);
    if (expat->noexpand) {

        XML_SetDefaultHandler(expat->parser,
                              TclGenExpatDefaultHandler);
    } else {

        XML_SetDefaultHandlerExpand(expat->parser,
                                    TclGenExpatDefaultHandler);
    }
    
    XML_SetUserData(expat->parser, (void *) expat);
    
    return TCL_OK;
}

644
645
646
647
648
649
650












































651
652
653
654
655
656
657
  XML_ParserFree(expat->parser);
  expat->parser = NULL;
}

/*
 *----------------------------------------------------------------------------
 *












































 * TclExpatInstanceCmd --
 *
 *	Implements instance command for expat class objects.
 *
 * Results:
 *	Depends on the method.
 *







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
  XML_ParserFree(expat->parser);
  expat->parser = NULL;
}

/*
 *----------------------------------------------------------------------------
 *
 * CurrentmarkupCommand --
 *
 *	Set as defaultHandler prior to XML_Currentmarkup() call.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Stores the markup context in expapt->currentmarkup.
 *
 *----------------------------------------------------------------------------
 */
static void
CurrentmarkupCommand(userData, s, len)
     void *userData;
     CONST char *s;
     int len;
{
    TclGenExpatInfo *expat = (TclGenExpatInfo *) userData;

    if (expat->status != TCL_OK) {
        return;
    }
  
    if (expat->cdata) {
        /* TclGenExpatCharacterDataHandler() was called and
         * initialized expat->cdata, but expat->cdata isn't reset by
         * TclExpatDispatchPCDATA(), so we're called from
         * -characterdatacommand and return the empty string by
         * definition. */
        expat->currentmarkup = NULL;
        expat->currentmarkuplen = 0;
        return;
    }
    expat->currentmarkup = s;
    expat->currentmarkuplen = len;
    return;
}



/*
 *----------------------------------------------------------------------------
 *
 * TclExpatInstanceCmd --
 *
 *	Implements instance command for expat class objects.
 *
 * Results:
 *	Depends on the method.
 *
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
     Tcl_Obj *CONST objv[];
{
  TclGenExpatInfo *expat = (TclGenExpatInfo *) clientData;
  char *data;
  int len = 0, optionIndex, result = TCL_OK;

  static CONST84 char *options[] = {
      "configure", "cget", "free", "get",
      "parse", "parsechannel", "parsefile", "reset", NULL
  };
  enum options {
      EXPAT_CONFIGURE, EXPAT_CGET, EXPAT_FREE, EXPAT_GET,
      EXPAT_PARSE, EXPAT_PARSECHANNEL, EXPAT_PARSEFILE, EXPAT_RESET
  };


  if (objc < 2) {
      Tcl_SetResult (interp, 
                     "wrong # args: should be \"parserCmd method ?arg ...?\"",







|



|







702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
     Tcl_Obj *CONST objv[];
{
  TclGenExpatInfo *expat = (TclGenExpatInfo *) clientData;
  char *data;
  int len = 0, optionIndex, result = TCL_OK;

  static CONST84 char *options[] = {
      "configure", "cget", "currentmarkup", "free", "get",
      "parse", "parsechannel", "parsefile", "reset", NULL
  };
  enum options {
      EXPAT_CONFIGURE, EXPAT_CGET, EXPAT_CURRENTMARKUP, EXPAT_FREE, EXPAT_GET,
      EXPAT_PARSE, EXPAT_PARSECHANNEL, EXPAT_PARSEFILE, EXPAT_RESET
  };


  if (objc < 2) {
      Tcl_SetResult (interp, 
                     "wrong # args: should be \"parserCmd method ?arg ...?\"",
706
707
708
709
710
711
712






























713
714
715
716
717
718
719
        break;

    case EXPAT_CGET:

        CheckArgs (3,5,2, "?-handlerset handlersetname? switch");
        result = TclExpatCget(interp, expat, objc - 2, objv + 2);
        break;































    case EXPAT_FREE:

        CheckArgs (2,2,1,"");

        if (expat->parsingState > 1) {
            Tcl_SetResult (interp, "parser freeing not allowed from within "







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
        break;

    case EXPAT_CGET:

        CheckArgs (3,5,2, "?-handlerset handlersetname? switch");
        result = TclExpatCget(interp, expat, objc - 2, objv + 2);
        break;

    case EXPAT_CURRENTMARKUP:

        CheckArgs (2,2,1, "");
        if (expat->parsingState < 2) {
            Tcl_ResetResult(expat->interp);
            break;
        }
        
        XML_SetDefaultHandlerExpand(expat->parser,
                                    CurrentmarkupCommand);
        XML_DefaultCurrent(expat->parser);
        if (expat->currentmarkuplen) {
            Tcl_SetObjResult(expat->interp, 
                             Tcl_NewStringObj(expat->currentmarkup,
                                              expat->currentmarkuplen));
        } else {
            Tcl_ResetResult(expat->interp);
        }
        expat->currentmarkup = NULL;
        expat->currentmarkuplen = 0;
        if (expat->noexpand) {
            XML_SetDefaultHandler(expat->parser,
                                  TclGenExpatDefaultHandler);
        } else {
            XML_SetDefaultHandlerExpand(expat->parser,
                                        TclGenExpatDefaultHandler);
        }
        result = TCL_OK;
        break;

    case EXPAT_FREE:

        CheckArgs (2,2,1,"");

        if (expat->parsingState > 1) {
            Tcl_SetResult (interp, "parser freeing not allowed from within "
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
	Tcl_IncrRefCount(activeTclHandlerSet->elementstartcommand);
        rc = Tcl_GetCommandInfo(interp, Tcl_GetString(objPtr[1]), &cmdInfo);
        if (rc && cmdInfo.isNativeObjectProc) {
            activeTclHandlerSet->elementstartObjProc = cmdInfo.objProc;
            activeTclHandlerSet->elementstartclientData 
                = cmdInfo.objClientData;
        } else {
            /* hmoreau 22 May 2003 */
            activeTclHandlerSet->elementstartObjProc = NULL;
        }
	break;

      case EXPAT_ELEMENTENDCMD:		/* -elementendcommand */

        CheckDefaultTclHandlerSet;
	if (activeTclHandlerSet->elementendcommand != NULL) {
	  Tcl_DecrRefCount(activeTclHandlerSet->elementendcommand);
	}

	activeTclHandlerSet->elementendcommand = objPtr[1];
	Tcl_IncrRefCount(activeTclHandlerSet->elementendcommand);
        rc = Tcl_GetCommandInfo(interp, Tcl_GetString(objPtr[1]), &cmdInfo);
        if (rc && cmdInfo.isNativeObjectProc) {
            activeTclHandlerSet->elementendObjProc = cmdInfo.objProc;
            activeTclHandlerSet->elementendclientData = cmdInfo.objClientData;
        } else {
            /* hmoreau 22 May 2003 */
            activeTclHandlerSet->elementendObjProc = NULL;
        }
	break;

      case EXPAT_STARTNAMESPACEDECLCMD:	/* -startnamespacedeclcommand */

        CheckDefaultTclHandlerSet;







<


















<







1238
1239
1240
1241
1242
1243
1244

1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262

1263
1264
1265
1266
1267
1268
1269
	Tcl_IncrRefCount(activeTclHandlerSet->elementstartcommand);
        rc = Tcl_GetCommandInfo(interp, Tcl_GetString(objPtr[1]), &cmdInfo);
        if (rc && cmdInfo.isNativeObjectProc) {
            activeTclHandlerSet->elementstartObjProc = cmdInfo.objProc;
            activeTclHandlerSet->elementstartclientData 
                = cmdInfo.objClientData;
        } else {

            activeTclHandlerSet->elementstartObjProc = NULL;
        }
	break;

      case EXPAT_ELEMENTENDCMD:		/* -elementendcommand */

        CheckDefaultTclHandlerSet;
	if (activeTclHandlerSet->elementendcommand != NULL) {
	  Tcl_DecrRefCount(activeTclHandlerSet->elementendcommand);
	}

	activeTclHandlerSet->elementendcommand = objPtr[1];
	Tcl_IncrRefCount(activeTclHandlerSet->elementendcommand);
        rc = Tcl_GetCommandInfo(interp, Tcl_GetString(objPtr[1]), &cmdInfo);
        if (rc && cmdInfo.isNativeObjectProc) {
            activeTclHandlerSet->elementendObjProc = cmdInfo.objProc;
            activeTclHandlerSet->elementendclientData = cmdInfo.objClientData;
        } else {

            activeTclHandlerSet->elementendObjProc = NULL;
        }
	break;

      case EXPAT_STARTNAMESPACEDECLCMD:	/* -startnamespacedeclcommand */

        CheckDefaultTclHandlerSet;
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
	activeTclHandlerSet->datacommand = objPtr[1];
	Tcl_IncrRefCount(activeTclHandlerSet->datacommand);
        rc = Tcl_GetCommandInfo (interp, Tcl_GetString(objPtr[1]), &cmdInfo);
        if (rc && cmdInfo.isNativeObjectProc) {
            activeTclHandlerSet->datacommandObjProc = cmdInfo.objProc;
            activeTclHandlerSet->datacommandclientData = cmdInfo.objClientData;
        } else {
            /* hmoreau 22 May 2003 */
            activeTclHandlerSet->datacommandObjProc = NULL;
        }
	break;

      case EXPAT_PICMD:			/* -processinginstructioncommand */

        CheckDefaultTclHandlerSet;







<







1298
1299
1300
1301
1302
1303
1304

1305
1306
1307
1308
1309
1310
1311
	activeTclHandlerSet->datacommand = objPtr[1];
	Tcl_IncrRefCount(activeTclHandlerSet->datacommand);
        rc = Tcl_GetCommandInfo (interp, Tcl_GetString(objPtr[1]), &cmdInfo);
        if (rc && cmdInfo.isNativeObjectProc) {
            activeTclHandlerSet->datacommandObjProc = cmdInfo.objProc;
            activeTclHandlerSet->datacommandclientData = cmdInfo.objClientData;
        } else {

            activeTclHandlerSet->datacommandObjProc = NULL;
        }
	break;

      case EXPAT_PICMD:			/* -processinginstructioncommand */

        CheckDefaultTclHandlerSet;
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
        break;

    case EXPAT_NOEXPAND:
        if (Tcl_GetBooleanFromObj (interp, objv[1], &bool) != TCL_OK) {
            return TCL_ERROR;
        }
        if (bool) {
            XML_SetDefaultHandlerExpand(expat->parser, NULL);
            XML_SetDefaultHandler(expat->parser,
                        (XML_DefaultHandler) TclGenExpatDefaultHandler);
        }
        else {
            XML_SetDefaultHandler(expat->parser, NULL);
            XML_SetDefaultHandlerExpand(expat->parser,
                        (XML_DefaultHandler) TclGenExpatDefaultHandler);
        }
        expat->noexpand = bool;
        break;

    }

    objPtr += 2;







<
|
|
<
|
<
|
|







1564
1565
1566
1567
1568
1569
1570

1571
1572

1573

1574
1575
1576
1577
1578
1579
1580
1581
1582
        break;

    case EXPAT_NOEXPAND:
        if (Tcl_GetBooleanFromObj (interp, objv[1], &bool) != TCL_OK) {
            return TCL_ERROR;
        }
        if (bool) {

            XML_SetDefaultHandler( expat->parser,
                                   TclGenExpatDefaultHandler);

        } else {

            XML_SetDefaultHandlerExpand( expat->parser,
                                         TclGenExpatDefaultHandler);
        }
        expat->noexpand = bool;
        break;

    }

    objPtr += 2;
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
              activeCHandlerSet->datacommand (activeCHandlerSet->userData,
                                              s, len);
          }
      }
      activeCHandlerSet = activeCHandlerSet->nextHandlerSet;
  }
  Tcl_DecrRefCount (expat->cdata);
  expat->cdata = 0;
  return;
}


/*
 *----------------------------------------------------------------------------
 *







|







2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
              activeCHandlerSet->datacommand (activeCHandlerSet->userData,
                                              s, len);
          }
      }
      activeCHandlerSet = activeCHandlerSet->nextHandlerSet;
  }
  Tcl_DecrRefCount (expat->cdata);
  expat->cdata = NULL;
  return;
}


/*
 *----------------------------------------------------------------------------
 *

Changes to generic/tclexpat.h.

130
131
132
133
134
135
136


137
138
139
140
141
142
143
144
    int parsingState;           /* 0 == freshly (re-)initialized
                                   1 == initParserProcs called
                                   2 == parsing an input chunk */
    XML_Char nsSeparator;       
    int paramentityparsing;     
    int noexpand;
    int useForeignDTD;



    TclHandlerSet *firstTclHandlerSet;
    CHandlerSet *firstCHandlerSet;
} TclGenExpatInfo;

/*--------------------------------------------------------------------------
|   Function prototypes
|







>
>
|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
    int parsingState;           /* 0 == freshly (re-)initialized
                                   1 == initParserProcs called
                                   2 == parsing an input chunk */
    XML_Char nsSeparator;       
    int paramentityparsing;     
    int noexpand;
    int useForeignDTD;
    CONST char *currentmarkup;  /* Used to transfer data for method */
    int currentmarkuplen;       /* currentmarkup */
 
    TclHandlerSet *firstTclHandlerSet;
    CHandlerSet *firstCHandlerSet;
} TclGenExpatInfo;

/*--------------------------------------------------------------------------
|   Function prototypes
|

Changes to tests/parser.test.

9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24
25
#    parser-5.*: parse input from channel
#    parser-6.*: reuse parser 
#    parser-7.*: parser reset
#    parser-8.*: parser free
#    parser-9.*: parser parse
#    parser-10.*: return code 'return' from callback
#    parser-11.*: parser input from filename

#
# Copyright (c) 1999-2000 Zveno Pty Ltd.
# Copyright (c) 2002-2005 Rolf Ade
#
# $Id$

source [file join [file dir [info script]] loadtdom.tcl]

proc parray arrayName {
    upvar #0 $arrayName arr







>


|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#    parser-5.*: parse input from channel
#    parser-6.*: reuse parser 
#    parser-7.*: parser reset
#    parser-8.*: parser free
#    parser-9.*: parser parse
#    parser-10.*: return code 'return' from callback
#    parser-11.*: parser input from filename
#    parser-12.*: parser currentmarkup
#
# Copyright (c) 1999-2000 Zveno Pty Ltd.
# Copyright (c) 2002-2015 Rolf Ade
#
# $Id$

source [file join [file dir [info script]] loadtdom.tcl]

proc parray arrayName {
    upvar #0 $arrayName arr
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534

proc elementstart {args} {
    global parser

    $parser parse {<root>foo bar</root>}
}

test parser-9.1 {try to use the parser form within one of its callbacks} {
    set parser [expat -elementstartcommand elementstart]
    set result [catch {$parser parse <root>foo</root>} errMsg]
    lappend result $errMsg
    $parser free
    set result
} {1 {Parser already in use.}}

proc calledFromElementstart {args} {
    global parser

    $parser parse {<root>foo bar</root>}
}

proc elementstart {args} {
    calledFromElementstart
}

test parser-9.2 {try to use the parser form within one of its callbacks} {
    set parser [expat -elementstartcommand elementstart]
    set result [catch {$parser parse <root>foo</root>} errMsg]
    lappend result $errMsg
    $parser free
    set result
} {1 {Parser already in use.}}








|

















|







503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535

proc elementstart {args} {
    global parser

    $parser parse {<root>foo bar</root>}
}

test parser-9.1 {try to use the parser from within one of its callbacks} {
    set parser [expat -elementstartcommand elementstart]
    set result [catch {$parser parse <root>foo</root>} errMsg]
    lappend result $errMsg
    $parser free
    set result
} {1 {Parser already in use.}}

proc calledFromElementstart {args} {
    global parser

    $parser parse {<root>foo bar</root>}
}

proc elementstart {args} {
    calledFromElementstart
}

test parser-9.2 {try to use the parser from within one of its callbacks} {
    set parser [expat -elementstartcommand elementstart]
    set result [catch {$parser parse <root>foo</root>} errMsg]
    lappend result $errMsg
    $parser free
    set result
} {1 {Parser already in use.}}

578
579
580
581
582
583
584




























































































































585
586
587
588
589
590



























































591
592
593
594
    set parser [::xml::parser parser-11.1 -elementstartcommand Count]
    set file [file join [pwd] [file dir [info script]] data/books.xml]
    $parser parsefile $file
    set ::count
} {42}






























































































































foreach parser [info commands xmlparser*] {
    $parser free
}
foreach parser [info commands parser-*] {
    $parser free
}




























































# cleanup
::tcltest::cleanupTests
return







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
    set parser [::xml::parser parser-11.1 -elementstartcommand Count]
    set file [file join [pwd] [file dir [info script]] data/books.xml]
    $parser parsefile $file
    set ::count
} {42}


proc elementstart-12.1 {parser args} {
    global result
    append result [$parser currentmarkup]
}

proc elementend-12.1 {parser args} {
    global result
    append result [$parser currentmarkup]
}

test parser-12.1 {currentmarkup method} {
    catch {unset result}
    set result ""
    set p [expat parser-12.1 -noexpand]
    $p configure \
        -elementstartcommand [list elementstart-12.1 $p] \
        -elementendcommand [list elementend-12.1 $p]
    $p parse {<root rootatt="rootatt">text<a
        a_att1="a_att1"
        a_att2 = "a_att2"/><b>more text</b></root>}
    $p free
    set result
} {<root rootatt="rootatt"><a
        a_att1="a_att1"
        a_att2 = "a_att2"/><b></b></root>}

proc characterdata-12.2 {parser data} {
    global result
    append result [$parser currentmarkup]
}
test parser-12.2 {currentmarkup method} {
    catch {unset result}
    set result ""
    set p [expat parser-12.2]
    $p configure \
        -characterdatacommand [list characterdata-12.2 $p] 
    $p parse {<root rootatt="rootatt">text<a
        a_att1="a_att1"
        a_att2 = "a_att2"/><b>more text</b></root>}
    $p free
    set result
} {}

test parser-12.3 {currentmarkup method} {
    set p [expat parser-12.3]
    set result [$p currentmarkup]
    $p free
    set result
} {}

proc elementstart-12.4 {parser handlerset args} {
    global result
    append result "$handlerset: [$parser currentmarkup]\n"
}
proc elementend-12.4 {parser handlerset args} {
    global result
    append result "$handlerset: [$parser currentmarkup]\n"
}
test parser-12.4 {currentmarkup method - multiple handler set} {
    catch {unset result}
    set result ""
    set p [expat parser-12.4]
    $p configure \
        -elementstartcommand [list elementstart-12.4 $p default] \
        -elementendcommand [list elementend-12.4 $p default] \
        -handlerset "additional" \
        -elementstartcommand [list elementstart-12.4 $p "additional"] \
        -elementendcommand [list elementend-12.4 $p "additional"]
    $p parse {<root rootatt="rootatt">text<a
        a_att1="a_att1"
        a_att2 = "a_att2"/><b>more text</b></root>}
    $p free
    set result
} {default: <root rootatt="rootatt">
additional: <root rootatt="rootatt">
default: <a
        a_att1="a_att1"
        a_att2 = "a_att2"/>
additional: <a
        a_att1="a_att1"
        a_att2 = "a_att2"/>
default: 
additional: 
default: <b>
additional: <b>
default: </b>
additional: </b>
default: </root>
additional: </root>
}

proc elementstart-12.5 {parser args} {
    global result
    append result "[$parser currentmarkup]"
}
test parser-12.5 {currentmarkup method - empty element shortcut -elementstartcommand} {
    catch {unset result}
    set result ""
    set p [expat parser-12.5]
    $p configure \
        -elementstartcommand [list elementstart-12.5 $p] 
    $p parse {<root><elem/></root>}
    $p free
    set result
} {<root><elem/>}

proc elementend-12.6 {parser args} {
    global result
    if {[$parser currentmarkup] eq ""} {
        append result "<elementend called, but currentmarkup return empty string>"
    }
    append result "[$parser currentmarkup]"
}
test parser-12.6 {currentmarkup method - empty element shortcut -elementendcommand} {
    catch {unset result}
    set result ""
    set p [expat parser-12.6]
    $p configure \
        -elementendcommand [list elementend-12.6 $p] 
    $p parse {<root><elem/></root>}
    $p free
    set result
} {<elementend called, but currentmarkup return empty string></root>}
    
foreach parser [info commands xmlparser*] {
    $parser free
}
foreach parser [info commands parser-*] {
    $parser free
}

proc elementdeclcommand-12.7 {parser args} {
    global result
    append result "elementdeclcommand: [$parser currentmarkup]"
}

proc entitydeclcommand-12.7 {parser args} {
    global result
    append result "entitydeclcommand: [$parser currentmarkup]"
}

test parser-12.7 {currentmarkup method - not for doctype markup handler} {
    catch {unset result}
    set result ""
    set p [expat parser-12.7]
    $p configure \
        -elementdeclcommand [list elementdeclcommand-12.7 $p] \
        -entitydeclcommand [list entitydeclcommand-12.7 $p]
    $p parse {<!DOCTYPE test [
<!ELEMENT test (#PCDATA) >
<!ENTITY % xx '&#37;zz;'>
<!ENTITY % zz '&#60;!ENTITY tricky "error-prone" >' >
%xx;
]>
<test>This sample shows a &tricky; method.</test>}
    $p free
    set result
} {elementdeclcommand: entitydeclcommand: entitydeclcommand: }

proc pi-12.8 {parser args} {
    global result
    append result "pi: [$parser currentmarkup]"
}
test parser-12.8 {currentmarkup method - processing instruction} {
    catch {unset result}
    set result ""
    set p [expat parser-12.8]
    $p configure \
        -processinginstructioncommand [list pi-12.8 $p]
    $p parse {<doc><?xml-stylesheet type="text/xsl" href="style.xsl"?></doc>}
    $p free
    set result
} {pi: <?xml-stylesheet type="text/xsl" href="style.xsl"?>}

proc comment-12.9 {parser args} {
    global result
    append result "comment: [$parser currentmarkup]"
}
test parser-12.9 {currentmarkup method - comment} {
    catch {unset result}
    set result ""
    set p [expat parser-12.9]
    $p configure \
        -commentcommand [list comment-12.9 $p]
    $p parse {<doc><!-- A comment --></doc>}
    $p free
    set result
} {comment: <!-- A comment -->}


# cleanup
::tcltest::cleanupTests
return

Changes to tests/pi.test.

14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
proc PI {target data args} {
    lappend ::result $target $data
}

test pi-1.1 {PI} {
    set ::result {}

    catch {rename xml::pi-1.1 {}}
    set parser [xml::parser pi-1.1 \
	-processinginstructioncommand PI]
    $parser parse {<?xml version="1.0"?>
<!DOCTYPE Test>
<Test><?Test This is a processing instruction?></Test>
}

    set ::result
} {Test {This is a processing instruction}}

test pi-1.2 {PI: missing trailing ?} {
    set ::result {}

    catch {rename xml::pi-1.2 {}}
    set parser [xml::parser pi-1.2 \
	-processinginstructioncommand PI]
    set returncode [catch {$parser parse {<?xml version="1.0"?>
<!DOCTYPE Test>
<Test><?Test This is a syntax error></Test>
}} msg]

    list $returncode [regexp {error "unclosed token" at.+} $msg]
} {1 1}

test pi-2.1 {PI with special characters} {
    set ::result {}

    catch {rename xml::pi-2.1 {}}
    set parser [xml::parser pi-2.1 \
	-processinginstructioncommand PI]
    $parser parse {<?xml version="1.0"?>
<!DOCTYPE Test>
<Test><?Test [if !VMLRender]?></Test>
}

    set ::result
} {Test {[if !VMLRender]}}

foreach parser [info commands pi-*] {
    $parser free
}

# cleanup
::tcltest::cleanupTests
return







<






>






<






|






<






>



<
<
<
<



14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54
55
56




57
58
59
proc PI {target data args} {
    lappend ::result $target $data
}

test pi-1.1 {PI} {
    set ::result {}


    set parser [xml::parser pi-1.1 \
	-processinginstructioncommand PI]
    $parser parse {<?xml version="1.0"?>
<!DOCTYPE Test>
<Test><?Test This is a processing instruction?></Test>
}
    $parser free
    set ::result
} {Test {This is a processing instruction}}

test pi-1.2 {PI: missing trailing ?} {
    set ::result {}


    set parser [xml::parser pi-1.2 \
	-processinginstructioncommand PI]
    set returncode [catch {$parser parse {<?xml version="1.0"?>
<!DOCTYPE Test>
<Test><?Test This is a syntax error></Test>
}} msg]
    $parser free
    list $returncode [regexp {error "unclosed token" at.+} $msg]
} {1 1}

test pi-2.1 {PI with special characters} {
    set ::result {}


    set parser [xml::parser pi-2.1 \
	-processinginstructioncommand PI]
    $parser parse {<?xml version="1.0"?>
<!DOCTYPE Test>
<Test><?Test [if !VMLRender]?></Test>
}
    $parser free
    set ::result
} {Test {[if !VMLRender]}}





# cleanup
::tcltest::cleanupTests
return