Index: trunk/Delphes/Delphes-3.0.9/CREDITS
===================================================================
--- trunk/Delphes/Delphes-3.0.9/CREDITS	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/CREDITS	(revision 5)
@@ -0,0 +1,7 @@
+Delphes, a framework for fast simulation of a generic collider experiment
+
+Centre for Cosmology, Particle Physics and Phenomenology (CP3)
+Universite Catholique de Louvain (UCL)
+Louvain-la-Neuve, Belgium
+
+https://cp3.irmp.ucl.ac.be/projects/delphes/
Index: trunk/Delphes/Delphes-3.0.9/Makefile
===================================================================
--- trunk/Delphes/Delphes-3.0.9/Makefile	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/Makefile	(revision 5)
@@ -0,0 +1,1354 @@
+
+#
+# Makefile for ExRootAnalysis
+#
+# Author: P. Demin - UCL, Louvain-la-Neuve
+#
+# multi-platform configuration is taken from ROOT (root/test/Makefile.arch)
+#
+
+include doc/Makefile.arch
+
+ifeq ($(ARCH),macosx64)
+UNDEFOPT = dynamic_lookup
+endif
+
+SrcSuf = cc
+
+CXXFLAGS += $(ROOTCFLAGS) -Wno-write-strings -D_FILE_OFFSET_BITS=64 -DDROP_CGAL -I. -Iexternal -Iexternal/tcl
+DELPHES_LIBS = $(shell $(RC) --libs) -lEG $(SYSLIBS)
+DISPLAY_LIBS = $(shell $(RC) --evelibs) $(SYSLIBS)
+
+###
+
+DELPHES = libDelphes.$(DllSuf)
+DELPHESLIB = libDelphes.lib
+
+DISPLAY = libDelphesDisplay.$(DllSuf)
+DISPLAYLIB = libDelphesDisplay.lib
+
+VERSION = $(shell cat VERSION)
+DISTDIR = Delphes-$(VERSION)
+DISTTAR = $(DISTDIR).tar.gz
+
+all:
+
+
+DelphesLHEF$(ExeSuf): \
+	tmp/readers/DelphesLHEF.$(ObjSuf)
+
+tmp/readers/DelphesLHEF.$(ObjSuf): \
+	readers/DelphesLHEF.cpp \
+	modules/Delphes.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesLHEFReader.h \
+	external/ExRootAnalysis/ExRootTreeWriter.h \
+	external/ExRootAnalysis/ExRootTreeBranch.h \
+	external/ExRootAnalysis/ExRootProgressBar.h
+DelphesHepMC$(ExeSuf): \
+	tmp/readers/DelphesHepMC.$(ObjSuf)
+
+tmp/readers/DelphesHepMC.$(ObjSuf): \
+	readers/DelphesHepMC.cpp \
+	modules/Delphes.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesHepMCReader.h \
+	external/ExRootAnalysis/ExRootTreeWriter.h \
+	external/ExRootAnalysis/ExRootTreeBranch.h \
+	external/ExRootAnalysis/ExRootProgressBar.h
+DelphesSTDHEP$(ExeSuf): \
+	tmp/readers/DelphesSTDHEP.$(ObjSuf)
+
+tmp/readers/DelphesSTDHEP.$(ObjSuf): \
+	readers/DelphesSTDHEP.cpp \
+	modules/Delphes.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesSTDHEPReader.h \
+	external/ExRootAnalysis/ExRootTreeWriter.h \
+	external/ExRootAnalysis/ExRootTreeBranch.h \
+	external/ExRootAnalysis/ExRootProgressBar.h
+lhco2root$(ExeSuf): \
+	tmp/converters/lhco2root.$(ObjSuf)
+
+tmp/converters/lhco2root.$(ObjSuf): \
+	converters/lhco2root.cpp \
+	modules/Delphes.h \
+	classes/DelphesStream.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	external/ExRootAnalysis/ExRootTreeWriter.h \
+	external/ExRootAnalysis/ExRootTreeBranch.h \
+	external/ExRootAnalysis/ExRootProgressBar.h
+root2pileup$(ExeSuf): \
+	tmp/converters/root2pileup.$(ObjSuf)
+
+tmp/converters/root2pileup.$(ObjSuf): \
+	converters/root2pileup.cpp \
+	classes/DelphesClasses.h \
+	classes/DelphesPileUpWriter.h \
+	external/ExRootAnalysis/ExRootTreeReader.h \
+	external/ExRootAnalysis/ExRootProgressBar.h
+root2lhco$(ExeSuf): \
+	tmp/converters/root2lhco.$(ObjSuf)
+
+tmp/converters/root2lhco.$(ObjSuf): \
+	converters/root2lhco.cpp \
+	classes/DelphesClasses.h \
+	external/ExRootAnalysis/ExRootTreeReader.h \
+	external/ExRootAnalysis/ExRootProgressBar.h
+stdhep2pileup$(ExeSuf): \
+	tmp/converters/stdhep2pileup.$(ObjSuf)
+
+tmp/converters/stdhep2pileup.$(ObjSuf): \
+	converters/stdhep2pileup.cpp \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesSTDHEPReader.h \
+	classes/DelphesPileUpWriter.h \
+	external/ExRootAnalysis/ExRootTreeWriter.h \
+	external/ExRootAnalysis/ExRootTreeBranch.h \
+	external/ExRootAnalysis/ExRootProgressBar.h
+hepmc2pileup$(ExeSuf): \
+	tmp/converters/hepmc2pileup.$(ObjSuf)
+
+tmp/converters/hepmc2pileup.$(ObjSuf): \
+	converters/hepmc2pileup.cpp \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesHepMCReader.h \
+	classes/DelphesPileUpWriter.h \
+	external/ExRootAnalysis/ExRootTreeWriter.h \
+	external/ExRootAnalysis/ExRootTreeBranch.h \
+	external/ExRootAnalysis/ExRootProgressBar.h
+pileup2root$(ExeSuf): \
+	tmp/converters/pileup2root.$(ObjSuf)
+
+tmp/converters/pileup2root.$(ObjSuf): \
+	converters/pileup2root.cpp \
+	classes/DelphesStream.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesPileUpReader.h \
+	external/ExRootAnalysis/ExRootTreeWriter.h \
+	external/ExRootAnalysis/ExRootTreeBranch.h \
+	external/ExRootAnalysis/ExRootProgressBar.h
+EXECUTABLE =  \
+	DelphesLHEF$(ExeSuf) \
+	DelphesHepMC$(ExeSuf) \
+	DelphesSTDHEP$(ExeSuf) \
+	lhco2root$(ExeSuf) \
+	root2pileup$(ExeSuf) \
+	root2lhco$(ExeSuf) \
+	stdhep2pileup$(ExeSuf) \
+	hepmc2pileup$(ExeSuf) \
+	pileup2root$(ExeSuf)
+
+EXECUTABLE_OBJ =  \
+	tmp/readers/DelphesLHEF.$(ObjSuf) \
+	tmp/readers/DelphesHepMC.$(ObjSuf) \
+	tmp/readers/DelphesSTDHEP.$(ObjSuf) \
+	tmp/converters/lhco2root.$(ObjSuf) \
+	tmp/converters/root2pileup.$(ObjSuf) \
+	tmp/converters/root2lhco.$(ObjSuf) \
+	tmp/converters/stdhep2pileup.$(ObjSuf) \
+	tmp/converters/hepmc2pileup.$(ObjSuf) \
+	tmp/converters/pileup2root.$(ObjSuf)
+
+tmp/classes/ClassesDict.$(SrcSuf): \
+	classes/ClassesLinkDef.h \
+	classes/DelphesModule.h \
+	classes/DelphesFactory.h \
+	classes/SortableObject.h \
+	classes/DelphesClasses.h
+tmp/modules/ModulesDict.$(SrcSuf): \
+	modules/ModulesLinkDef.h \
+	modules/Delphes.h \
+	modules/FastJetFinder.h \
+	modules/ParticlePropagator.h \
+	modules/Efficiency.h \
+	modules/EnergySmearing.h \
+	modules/MomentumSmearing.h \
+	modules/Calorimeter.h \
+	modules/Isolation.h \
+	modules/UniqueObjectFinder.h \
+	modules/BTagging.h \
+	modules/TauTagging.h \
+	modules/TreeWriter.h \
+	modules/Merger.h \
+	modules/LeptonDressing.h \
+	modules/PileUpMerger.h \
+	modules/JetPileUpSubtractor.h \
+	modules/TrackPileUpSubtractor.h \
+	modules/ConstituentFilter.h \
+	modules/StatusPidFilter.h \
+	modules/Cloner.h \
+	modules/ExampleModule.h
+tmp/external/ExRootAnalysis/ExRootAnalysisDict.$(SrcSuf): \
+	external/ExRootAnalysis/ExRootAnalysisLinkDef.h \
+	external/ExRootAnalysis/ExRootTreeReader.h \
+	external/ExRootAnalysis/ExRootTreeWriter.h \
+	external/ExRootAnalysis/ExRootTreeBranch.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootUtilities.h \
+	external/ExRootAnalysis/ExRootClassifier.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootProgressBar.h \
+	external/ExRootAnalysis/ExRootConfReader.h \
+	external/ExRootAnalysis/ExRootTask.h
+DELPHES_DICT =  \
+	tmp/classes/ClassesDict.$(SrcSuf) \
+	tmp/modules/ModulesDict.$(SrcSuf) \
+	tmp/external/ExRootAnalysis/ExRootAnalysisDict.$(SrcSuf)
+
+DELPHES_DICT_OBJ =  \
+	tmp/classes/ClassesDict.$(ObjSuf) \
+	tmp/modules/ModulesDict.$(ObjSuf) \
+	tmp/external/ExRootAnalysis/ExRootAnalysisDict.$(ObjSuf)
+
+tmp/display/DisplayDict.$(SrcSuf): \
+	display/DisplayLinkDef.h \
+	display/DelphesDisplay.h \
+	display/DelphesCaloData.h
+DISPLAY_DICT =  \
+	tmp/display/DisplayDict.$(SrcSuf)
+
+DISPLAY_DICT_OBJ =  \
+	tmp/display/DisplayDict.$(ObjSuf)
+
+tmp/classes/DelphesHepMCReader.$(ObjSuf): \
+	classes/DelphesHepMCReader.$(SrcSuf) \
+	classes/DelphesHepMCReader.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesStream.h \
+	external/ExRootAnalysis/ExRootTreeBranch.h
+tmp/classes/DelphesLHEFReader.$(ObjSuf): \
+	classes/DelphesLHEFReader.$(SrcSuf) \
+	classes/DelphesLHEFReader.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesStream.h \
+	external/ExRootAnalysis/ExRootTreeBranch.h
+tmp/classes/DelphesFactory.$(ObjSuf): \
+	classes/DelphesFactory.$(SrcSuf) \
+	classes/DelphesFactory.h \
+	classes/DelphesClasses.h \
+	external/ExRootAnalysis/ExRootTreeBranch.h
+tmp/classes/DelphesFormula.$(ObjSuf): \
+	classes/DelphesFormula.$(SrcSuf) \
+	classes/DelphesFormula.h
+tmp/classes/DelphesSTDHEPReader.$(ObjSuf): \
+	classes/DelphesSTDHEPReader.$(SrcSuf) \
+	classes/DelphesSTDHEPReader.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	external/ExRootAnalysis/ExRootTreeBranch.h
+tmp/classes/DelphesStream.$(ObjSuf): \
+	classes/DelphesStream.$(SrcSuf) \
+	classes/DelphesStream.h
+tmp/classes/DelphesPileUpWriter.$(ObjSuf): \
+	classes/DelphesPileUpWriter.$(SrcSuf) \
+	classes/DelphesPileUpWriter.h
+tmp/classes/DelphesModule.$(ObjSuf): \
+	classes/DelphesModule.$(SrcSuf) \
+	classes/DelphesModule.h \
+	classes/DelphesFactory.h \
+	external/ExRootAnalysis/ExRootTreeReader.h \
+	external/ExRootAnalysis/ExRootTreeBranch.h \
+	external/ExRootAnalysis/ExRootTreeWriter.h \
+	external/ExRootAnalysis/ExRootResult.h
+tmp/classes/DelphesClasses.$(ObjSuf): \
+	classes/DelphesClasses.$(SrcSuf) \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/SortableObject.h
+tmp/classes/DelphesPileUpReader.$(ObjSuf): \
+	classes/DelphesPileUpReader.$(SrcSuf) \
+	classes/DelphesPileUpReader.h
+tmp/modules/LeptonDressing.$(ObjSuf): \
+	modules/LeptonDressing.$(SrcSuf) \
+	modules/LeptonDressing.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/modules/Efficiency.$(ObjSuf): \
+	modules/Efficiency.$(SrcSuf) \
+	modules/Efficiency.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/modules/UniqueObjectFinder.$(ObjSuf): \
+	modules/UniqueObjectFinder.$(SrcSuf) \
+	modules/UniqueObjectFinder.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/modules/ExampleModule.$(ObjSuf): \
+	modules/ExampleModule.$(SrcSuf) \
+	modules/ExampleModule.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/modules/ParticlePropagator.$(ObjSuf): \
+	modules/ParticlePropagator.$(SrcSuf) \
+	modules/ParticlePropagator.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/modules/EnergySmearing.$(ObjSuf): \
+	modules/EnergySmearing.$(SrcSuf) \
+	modules/EnergySmearing.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/modules/FastJetFinder.$(ObjSuf): \
+	modules/FastJetFinder.$(SrcSuf) \
+	modules/FastJetFinder.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/JetDefinition.hh \
+	external/fastjet/ClusterSequence.hh \
+	external/fastjet/Selector.hh \
+	external/fastjet/ClusterSequenceArea.hh \
+	external/fastjet/tools/JetMedianBackgroundEstimator.hh \
+	external/fastjet/plugins/SISCone/fastjet/SISConePlugin.hh \
+	external/fastjet/plugins/CDFCones/fastjet/CDFMidPointPlugin.hh \
+	external/fastjet/plugins/CDFCones/fastjet/CDFJetCluPlugin.hh
+tmp/modules/StatusPidFilter.$(ObjSuf): \
+	modules/StatusPidFilter.$(SrcSuf) \
+	modules/StatusPidFilter.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/modules/ConstituentFilter.$(ObjSuf): \
+	modules/ConstituentFilter.$(SrcSuf) \
+	modules/ConstituentFilter.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/modules/TauTagging.$(ObjSuf): \
+	modules/TauTagging.$(SrcSuf) \
+	modules/TauTagging.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/modules/Merger.$(ObjSuf): \
+	modules/Merger.$(SrcSuf) \
+	modules/Merger.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/modules/BTagging.$(ObjSuf): \
+	modules/BTagging.$(SrcSuf) \
+	modules/BTagging.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/modules/TreeWriter.$(ObjSuf): \
+	modules/TreeWriter.$(SrcSuf) \
+	modules/TreeWriter.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h \
+	external/ExRootAnalysis/ExRootTreeBranch.h
+tmp/modules/Delphes.$(ObjSuf): \
+	modules/Delphes.$(SrcSuf) \
+	modules/Delphes.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h \
+	external/ExRootAnalysis/ExRootConfReader.h \
+	external/ExRootAnalysis/ExRootTreeWriter.h
+tmp/modules/Calorimeter.$(ObjSuf): \
+	modules/Calorimeter.$(SrcSuf) \
+	modules/Calorimeter.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/modules/Isolation.$(ObjSuf): \
+	modules/Isolation.$(SrcSuf) \
+	modules/Isolation.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/modules/PileUpMerger.$(ObjSuf): \
+	modules/PileUpMerger.$(SrcSuf) \
+	modules/PileUpMerger.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	classes/DelphesPileUpReader.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/modules/TrackPileUpSubtractor.$(ObjSuf): \
+	modules/TrackPileUpSubtractor.$(SrcSuf) \
+	modules/TrackPileUpSubtractor.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/modules/Cloner.$(ObjSuf): \
+	modules/Cloner.$(SrcSuf) \
+	modules/Cloner.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/modules/JetPileUpSubtractor.$(ObjSuf): \
+	modules/JetPileUpSubtractor.$(SrcSuf) \
+	modules/JetPileUpSubtractor.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/modules/MomentumSmearing.$(ObjSuf): \
+	modules/MomentumSmearing.$(SrcSuf) \
+	modules/MomentumSmearing.h \
+	classes/DelphesClasses.h \
+	classes/DelphesFactory.h \
+	classes/DelphesFormula.h \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/external/ExRootAnalysis/ExRootFilter.$(ObjSuf): \
+	external/ExRootAnalysis/ExRootFilter.$(SrcSuf) \
+	external/ExRootAnalysis/ExRootFilter.h \
+	external/ExRootAnalysis/ExRootClassifier.h
+tmp/external/ExRootAnalysis/ExRootConfReader.$(ObjSuf): \
+	external/ExRootAnalysis/ExRootConfReader.$(SrcSuf) \
+	external/ExRootAnalysis/ExRootConfReader.h \
+	external/tcl/tcl.h
+tmp/external/ExRootAnalysis/ExRootTreeWriter.$(ObjSuf): \
+	external/ExRootAnalysis/ExRootTreeWriter.$(SrcSuf) \
+	external/ExRootAnalysis/ExRootTreeWriter.h \
+	external/ExRootAnalysis/ExRootTreeBranch.h
+tmp/external/ExRootAnalysis/ExRootResult.$(ObjSuf): \
+	external/ExRootAnalysis/ExRootResult.$(SrcSuf) \
+	external/ExRootAnalysis/ExRootResult.h \
+	external/ExRootAnalysis/ExRootUtilities.h
+tmp/external/ExRootAnalysis/ExRootTreeBranch.$(ObjSuf): \
+	external/ExRootAnalysis/ExRootTreeBranch.$(SrcSuf) \
+	external/ExRootAnalysis/ExRootTreeBranch.h
+tmp/external/ExRootAnalysis/ExRootTreeReader.$(ObjSuf): \
+	external/ExRootAnalysis/ExRootTreeReader.$(SrcSuf) \
+	external/ExRootAnalysis/ExRootTreeReader.h
+tmp/external/ExRootAnalysis/ExRootTask.$(ObjSuf): \
+	external/ExRootAnalysis/ExRootTask.$(SrcSuf) \
+	external/ExRootAnalysis/ExRootTask.h \
+	external/ExRootAnalysis/ExRootConfReader.h
+tmp/external/ExRootAnalysis/ExRootProgressBar.$(ObjSuf): \
+	external/ExRootAnalysis/ExRootProgressBar.$(SrcSuf) \
+	external/ExRootAnalysis/ExRootProgressBar.h
+tmp/external/ExRootAnalysis/ExRootUtilities.$(ObjSuf): \
+	external/ExRootAnalysis/ExRootUtilities.$(SrcSuf) \
+	external/ExRootAnalysis/ExRootUtilities.h
+tmp/external/fastjet/Dnn2piCylinder.$(ObjSuf): \
+	external/fastjet/Dnn2piCylinder.$(SrcSuf) \
+	external/fastjet/internal/Dnn2piCylinder.hh
+tmp/external/fastjet/GhostedAreaSpec.$(ObjSuf): \
+	external/fastjet/GhostedAreaSpec.$(SrcSuf) \
+	external/fastjet/GhostedAreaSpec.hh \
+	external/fastjet/Error.hh
+tmp/external/fastjet/ClusterSequenceActiveArea.$(ObjSuf): \
+	external/fastjet/ClusterSequenceActiveArea.$(SrcSuf) \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/ClusterSequence.hh \
+	external/fastjet/ClusterSequenceActiveArea.hh \
+	external/fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh
+tmp/external/fastjet/ClusterSequence_Delaunay.$(ObjSuf): \
+	external/fastjet/ClusterSequence_Delaunay.$(SrcSuf) \
+	external/fastjet/Error.hh \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/ClusterSequence.hh \
+	external/fastjet/internal/Dnn4piCylinder.hh \
+	external/fastjet/internal/Dnn3piCylinder.hh \
+	external/fastjet/internal/Dnn2piCylinder.hh
+tmp/external/fastjet/ClusterSequenceArea.$(ObjSuf): \
+	external/fastjet/ClusterSequenceArea.$(SrcSuf) \
+	external/fastjet/ClusterSequenceArea.hh
+tmp/external/fastjet/Voronoi.$(ObjSuf): \
+	external/fastjet/Voronoi.$(SrcSuf) \
+	external/fastjet/internal/Voronoi.hh
+tmp/external/fastjet/Selector.$(ObjSuf): \
+	external/fastjet/Selector.$(SrcSuf) \
+	external/fastjet/Selector.hh \
+	external/fastjet/GhostedAreaSpec.hh
+tmp/external/fastjet/ClusterSequence_TiledN2.$(ObjSuf): \
+	external/fastjet/ClusterSequence_TiledN2.$(SrcSuf) \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/ClusterSequence.hh \
+	external/fastjet/internal/MinHeap.hh
+tmp/external/fastjet/ClusterSequenceActiveAreaExplicitGhosts.$(ObjSuf): \
+	external/fastjet/ClusterSequenceActiveAreaExplicitGhosts.$(SrcSuf) \
+	external/fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh
+tmp/external/fastjet/LimitedWarning.$(ObjSuf): \
+	external/fastjet/LimitedWarning.$(SrcSuf) \
+	external/fastjet/LimitedWarning.hh
+tmp/external/fastjet/CompositeJetStructure.$(ObjSuf): \
+	external/fastjet/CompositeJetStructure.$(SrcSuf)
+tmp/external/fastjet/DnnPlane.$(ObjSuf): \
+	external/fastjet/DnnPlane.$(SrcSuf) \
+	external/fastjet/internal/DnnPlane.hh
+tmp/external/fastjet/ClusterSequence_DumbN3.$(ObjSuf): \
+	external/fastjet/ClusterSequence_DumbN3.$(SrcSuf) \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/ClusterSequence.hh
+tmp/external/fastjet/ClusterSequencePassiveArea.$(ObjSuf): \
+	external/fastjet/ClusterSequencePassiveArea.$(SrcSuf) \
+	external/fastjet/ClusterSequencePassiveArea.hh \
+	external/fastjet/ClusterSequenceVoronoiArea.hh
+tmp/external/fastjet/BasicRandom.$(ObjSuf): \
+	external/fastjet/BasicRandom.$(SrcSuf) \
+	external/fastjet/internal/BasicRandom.hh
+tmp/external/fastjet/ClusterSequenceAreaBase.$(ObjSuf): \
+	external/fastjet/ClusterSequenceAreaBase.$(SrcSuf) \
+	external/fastjet/ClusterSequenceAreaBase.hh
+tmp/external/fastjet/PseudoJetStructureBase.$(ObjSuf): \
+	external/fastjet/PseudoJetStructureBase.$(SrcSuf) \
+	external/fastjet/PseudoJetStructureBase.hh \
+	external/fastjet/Error.hh \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/ClusterSequence.hh \
+	external/fastjet/ClusterSequenceAreaBase.hh
+tmp/external/fastjet/ClusterSequence.$(ObjSuf): \
+	external/fastjet/ClusterSequence.$(SrcSuf) \
+	external/fastjet/Error.hh \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/ClusterSequence.hh \
+	external/fastjet/ClusterSequenceStructure.hh \
+	external/fastjet/version.hh
+tmp/external/fastjet/JetDefinition.$(ObjSuf): \
+	external/fastjet/JetDefinition.$(SrcSuf) \
+	external/fastjet/JetDefinition.hh \
+	external/fastjet/Error.hh \
+	external/fastjet/CompositeJetStructure.hh
+tmp/external/fastjet/Error.$(ObjSuf): \
+	external/fastjet/Error.$(SrcSuf) \
+	external/fastjet/Error.hh \
+	external/fastjet/config.h
+tmp/external/fastjet/RangeDefinition.$(ObjSuf): \
+	external/fastjet/RangeDefinition.$(SrcSuf) \
+	external/fastjet/RangeDefinition.hh
+tmp/external/fastjet/ClusterSequence_N2.$(ObjSuf): \
+	external/fastjet/ClusterSequence_N2.$(SrcSuf)
+tmp/external/fastjet/ClusterSequenceStructure.$(ObjSuf): \
+	external/fastjet/ClusterSequenceStructure.$(SrcSuf) \
+	external/fastjet/ClusterSequenceStructure.hh \
+	external/fastjet/Error.hh \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/ClusterSequence.hh \
+	external/fastjet/ClusterSequenceAreaBase.hh
+tmp/external/fastjet/Dnn4piCylinder.$(ObjSuf): \
+	external/fastjet/Dnn4piCylinder.$(SrcSuf) \
+	external/fastjet/internal/Dnn4piCylinder.hh
+tmp/external/fastjet/ClusterSequence1GhostPassiveArea.$(ObjSuf): \
+	external/fastjet/ClusterSequence1GhostPassiveArea.$(SrcSuf) \
+	external/fastjet/ClusterSequence1GhostPassiveArea.hh
+tmp/external/fastjet/MinHeap.$(ObjSuf): \
+	external/fastjet/MinHeap.$(SrcSuf) \
+	external/fastjet/internal/MinHeap.hh
+tmp/external/fastjet/PseudoJet.$(ObjSuf): \
+	external/fastjet/PseudoJet.$(SrcSuf) \
+	external/fastjet/Error.hh \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/ClusterSequence.hh \
+	external/fastjet/ClusterSequenceAreaBase.hh \
+	external/fastjet/CompositeJetStructure.hh
+tmp/external/fastjet/Dnn3piCylinder.$(ObjSuf): \
+	external/fastjet/Dnn3piCylinder.$(SrcSuf) \
+	external/fastjet/internal/Dnn3piCylinder.hh
+tmp/external/fastjet/ClusterSequence_CP2DChan.$(ObjSuf): \
+	external/fastjet/ClusterSequence_CP2DChan.$(SrcSuf) \
+	external/fastjet/ClusterSequence.hh \
+	external/fastjet/internal/ClosestPair2D.hh
+tmp/external/fastjet/ClusterSequenceVoronoiArea.$(ObjSuf): \
+	external/fastjet/ClusterSequenceVoronoiArea.$(SrcSuf) \
+	external/fastjet/ClusterSequenceVoronoiArea.hh \
+	external/fastjet/internal/Voronoi.hh
+tmp/external/fastjet/ClosestPair2D.$(ObjSuf): \
+	external/fastjet/ClosestPair2D.$(SrcSuf) \
+	external/fastjet/internal/ClosestPair2D.hh
+tmp/external/fastjet/FunctionOfPseudoJet.$(ObjSuf): \
+	external/fastjet/FunctionOfPseudoJet.$(SrcSuf)
+tmp/external/fastjet/AreaDefinition.$(ObjSuf): \
+	external/fastjet/AreaDefinition.$(SrcSuf) \
+	external/fastjet/AreaDefinition.hh
+tmp/external/fastjet/tools/CASubJetTagger.$(ObjSuf): \
+	external/fastjet/tools/CASubJetTagger.$(SrcSuf)
+tmp/external/fastjet/tools/TopTaggerBase.$(ObjSuf): \
+	external/fastjet/tools/TopTaggerBase.$(SrcSuf)
+tmp/external/fastjet/tools/BackgroundEstimatorBase.$(ObjSuf): \
+	external/fastjet/tools/BackgroundEstimatorBase.$(SrcSuf) \
+	external/fastjet/tools/BackgroundEstimatorBase.hh
+tmp/external/fastjet/tools/Subtractor.$(ObjSuf): \
+	external/fastjet/tools/Subtractor.$(SrcSuf) \
+	external/fastjet/tools/Subtractor.hh
+tmp/external/fastjet/tools/RestFrameNSubjettinessTagger.$(ObjSuf): \
+	external/fastjet/tools/RestFrameNSubjettinessTagger.$(SrcSuf)
+tmp/external/fastjet/tools/JetMedianBackgroundEstimator.$(ObjSuf): \
+	external/fastjet/tools/JetMedianBackgroundEstimator.$(SrcSuf) \
+	external/fastjet/tools/JetMedianBackgroundEstimator.hh
+tmp/external/fastjet/tools/MassDropTagger.$(ObjSuf): \
+	external/fastjet/tools/MassDropTagger.$(SrcSuf)
+tmp/external/fastjet/tools/JHTopTagger.$(ObjSuf): \
+	external/fastjet/tools/JHTopTagger.$(SrcSuf)
+tmp/external/fastjet/tools/GridMedianBackgroundEstimator.$(ObjSuf): \
+	external/fastjet/tools/GridMedianBackgroundEstimator.$(SrcSuf) \
+	external/fastjet/tools/GridMedianBackgroundEstimator.hh
+tmp/external/fastjet/tools/Filter.$(ObjSuf): \
+	external/fastjet/tools/Filter.$(SrcSuf) \
+	external/fastjet/tools/Filter.hh
+tmp/external/fastjet/tools/Pruner.$(ObjSuf): \
+	external/fastjet/tools/Pruner.$(SrcSuf) \
+	external/fastjet/tools/Pruner.hh \
+	external/fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh \
+	external/fastjet/Selector.hh
+tmp/external/fastjet/plugins/ATLASCone/ATLASConePlugin.$(ObjSuf): \
+	external/fastjet/plugins/ATLASCone/ATLASConePlugin.$(SrcSuf) \
+	external/fastjet/ClusterSequence.hh
+tmp/external/fastjet/plugins/ATLASCone/JetConeFinderTool.$(ObjSuf): \
+	external/fastjet/plugins/ATLASCone/JetConeFinderTool.$(SrcSuf)
+tmp/external/fastjet/plugins/ATLASCone/Jet.$(ObjSuf): \
+	external/fastjet/plugins/ATLASCone/Jet.$(SrcSuf)
+tmp/external/fastjet/plugins/ATLASCone/JetSplitMergeTool.$(ObjSuf): \
+	external/fastjet/plugins/ATLASCone/JetSplitMergeTool.$(SrcSuf)
+tmp/external/fastjet/plugins/NestedDefs/NestedDefsPlugin.$(ObjSuf): \
+	external/fastjet/plugins/NestedDefs/NestedDefsPlugin.$(SrcSuf) \
+	external/fastjet/ClusterSequence.hh
+tmp/external/fastjet/plugins/D0RunIICone/D0RunIIConePlugin.$(ObjSuf): \
+	external/fastjet/plugins/D0RunIICone/D0RunIIConePlugin.$(SrcSuf) \
+	external/fastjet/ClusterSequence.hh \
+	external/fastjet/Error.hh
+tmp/external/fastjet/plugins/TrackJet/TrackJetPlugin.$(ObjSuf): \
+	external/fastjet/plugins/TrackJet/TrackJetPlugin.$(SrcSuf) \
+	external/fastjet/ClusterSequence.hh
+tmp/external/fastjet/plugins/CDFCones/CDFMidPointPlugin.$(ObjSuf): \
+	external/fastjet/plugins/CDFCones/CDFMidPointPlugin.$(SrcSuf) \
+	external/fastjet/ClusterSequence.hh \
+	external/fastjet/Error.hh
+tmp/external/fastjet/plugins/CDFCones/MidPointAlgorithm.$(ObjSuf): \
+	external/fastjet/plugins/CDFCones/MidPointAlgorithm.$(SrcSuf)
+tmp/external/fastjet/plugins/CDFCones/CDFJetCluPlugin.$(ObjSuf): \
+	external/fastjet/plugins/CDFCones/CDFJetCluPlugin.$(SrcSuf) \
+	external/fastjet/ClusterSequence.hh
+tmp/external/fastjet/plugins/CDFCones/JetCluAlgorithm.$(ObjSuf): \
+	external/fastjet/plugins/CDFCones/JetCluAlgorithm.$(SrcSuf)
+tmp/external/fastjet/plugins/D0RunICone/D0RunIBaseConePlugin.$(ObjSuf): \
+	external/fastjet/plugins/D0RunICone/D0RunIBaseConePlugin.$(SrcSuf) \
+	external/fastjet/ClusterSequence.hh \
+	external/fastjet/Error.hh
+tmp/external/fastjet/plugins/SISCone/geom_2d.$(ObjSuf): \
+	external/fastjet/plugins/SISCone/geom_2d.$(SrcSuf)
+tmp/external/fastjet/plugins/SISCone/SISConePlugin.$(ObjSuf): \
+	external/fastjet/plugins/SISCone/SISConePlugin.$(SrcSuf) \
+	external/fastjet/ClusterSequence.hh
+tmp/external/fastjet/plugins/SISCone/siscone.$(ObjSuf): \
+	external/fastjet/plugins/SISCone/siscone.$(SrcSuf)
+tmp/external/fastjet/plugins/SISCone/hash.$(ObjSuf): \
+	external/fastjet/plugins/SISCone/hash.$(SrcSuf)
+tmp/external/fastjet/plugins/SISCone/quadtree.$(ObjSuf): \
+	external/fastjet/plugins/SISCone/quadtree.$(SrcSuf)
+tmp/external/fastjet/plugins/SISCone/area.$(ObjSuf): \
+	external/fastjet/plugins/SISCone/area.$(SrcSuf)
+tmp/external/fastjet/plugins/SISCone/momentum.$(ObjSuf): \
+	external/fastjet/plugins/SISCone/momentum.$(SrcSuf)
+tmp/external/fastjet/plugins/SISCone/reference.$(ObjSuf): \
+	external/fastjet/plugins/SISCone/reference.$(SrcSuf)
+tmp/external/fastjet/plugins/SISCone/ranlux.$(ObjSuf): \
+	external/fastjet/plugins/SISCone/ranlux.$(SrcSuf)
+tmp/external/fastjet/plugins/SISCone/protocones.$(ObjSuf): \
+	external/fastjet/plugins/SISCone/protocones.$(SrcSuf)
+tmp/external/fastjet/plugins/SISCone/split_merge.$(ObjSuf): \
+	external/fastjet/plugins/SISCone/split_merge.$(SrcSuf)
+tmp/external/fastjet/plugins/SISCone/vicinity.$(ObjSuf): \
+	external/fastjet/plugins/SISCone/vicinity.$(SrcSuf)
+tmp/external/fastjet/plugins/SISCone/siscone_error.$(ObjSuf): \
+	external/fastjet/plugins/SISCone/siscone_error.$(SrcSuf)
+tmp/external/fastjet/plugins/CMSIterativeCone/CMSIterativeConePlugin.$(ObjSuf): \
+	external/fastjet/plugins/CMSIterativeCone/CMSIterativeConePlugin.$(SrcSuf) \
+	external/fastjet/ClusterSequence.hh
+tmp/external/fastjet/plugins/GridJet/GridJetPlugin.$(ObjSuf): \
+	external/fastjet/plugins/GridJet/GridJetPlugin.$(SrcSuf) \
+	external/fastjet/ClusterSequence.hh
+tmp/external/fastjet/plugins/Jade/JadePlugin.$(ObjSuf): \
+	external/fastjet/plugins/Jade/JadePlugin.$(SrcSuf) \
+	external/fastjet/ClusterSequence.hh \
+	external/fastjet/NNH.hh
+tmp/external/fastjet/plugins/EECambridge/EECambridgePlugin.$(ObjSuf): \
+	external/fastjet/plugins/EECambridge/EECambridgePlugin.$(SrcSuf) \
+	external/fastjet/ClusterSequence.hh \
+	external/fastjet/NNH.hh
+DELPHES_OBJ =  \
+	tmp/classes/DelphesHepMCReader.$(ObjSuf) \
+	tmp/classes/DelphesLHEFReader.$(ObjSuf) \
+	tmp/classes/DelphesFactory.$(ObjSuf) \
+	tmp/classes/DelphesFormula.$(ObjSuf) \
+	tmp/classes/DelphesSTDHEPReader.$(ObjSuf) \
+	tmp/classes/DelphesStream.$(ObjSuf) \
+	tmp/classes/DelphesPileUpWriter.$(ObjSuf) \
+	tmp/classes/DelphesModule.$(ObjSuf) \
+	tmp/classes/DelphesClasses.$(ObjSuf) \
+	tmp/classes/DelphesPileUpReader.$(ObjSuf) \
+	tmp/modules/LeptonDressing.$(ObjSuf) \
+	tmp/modules/Efficiency.$(ObjSuf) \
+	tmp/modules/UniqueObjectFinder.$(ObjSuf) \
+	tmp/modules/ExampleModule.$(ObjSuf) \
+	tmp/modules/ParticlePropagator.$(ObjSuf) \
+	tmp/modules/EnergySmearing.$(ObjSuf) \
+	tmp/modules/FastJetFinder.$(ObjSuf) \
+	tmp/modules/StatusPidFilter.$(ObjSuf) \
+	tmp/modules/ConstituentFilter.$(ObjSuf) \
+	tmp/modules/TauTagging.$(ObjSuf) \
+	tmp/modules/Merger.$(ObjSuf) \
+	tmp/modules/BTagging.$(ObjSuf) \
+	tmp/modules/TreeWriter.$(ObjSuf) \
+	tmp/modules/Delphes.$(ObjSuf) \
+	tmp/modules/Calorimeter.$(ObjSuf) \
+	tmp/modules/Isolation.$(ObjSuf) \
+	tmp/modules/PileUpMerger.$(ObjSuf) \
+	tmp/modules/TrackPileUpSubtractor.$(ObjSuf) \
+	tmp/modules/Cloner.$(ObjSuf) \
+	tmp/modules/JetPileUpSubtractor.$(ObjSuf) \
+	tmp/modules/MomentumSmearing.$(ObjSuf) \
+	tmp/external/ExRootAnalysis/ExRootFilter.$(ObjSuf) \
+	tmp/external/ExRootAnalysis/ExRootConfReader.$(ObjSuf) \
+	tmp/external/ExRootAnalysis/ExRootTreeWriter.$(ObjSuf) \
+	tmp/external/ExRootAnalysis/ExRootResult.$(ObjSuf) \
+	tmp/external/ExRootAnalysis/ExRootTreeBranch.$(ObjSuf) \
+	tmp/external/ExRootAnalysis/ExRootTreeReader.$(ObjSuf) \
+	tmp/external/ExRootAnalysis/ExRootTask.$(ObjSuf) \
+	tmp/external/ExRootAnalysis/ExRootProgressBar.$(ObjSuf) \
+	tmp/external/ExRootAnalysis/ExRootUtilities.$(ObjSuf) \
+	tmp/external/fastjet/Dnn2piCylinder.$(ObjSuf) \
+	tmp/external/fastjet/GhostedAreaSpec.$(ObjSuf) \
+	tmp/external/fastjet/ClusterSequenceActiveArea.$(ObjSuf) \
+	tmp/external/fastjet/ClusterSequence_Delaunay.$(ObjSuf) \
+	tmp/external/fastjet/ClusterSequenceArea.$(ObjSuf) \
+	tmp/external/fastjet/Voronoi.$(ObjSuf) \
+	tmp/external/fastjet/Selector.$(ObjSuf) \
+	tmp/external/fastjet/ClusterSequence_TiledN2.$(ObjSuf) \
+	tmp/external/fastjet/ClusterSequenceActiveAreaExplicitGhosts.$(ObjSuf) \
+	tmp/external/fastjet/LimitedWarning.$(ObjSuf) \
+	tmp/external/fastjet/CompositeJetStructure.$(ObjSuf) \
+	tmp/external/fastjet/DnnPlane.$(ObjSuf) \
+	tmp/external/fastjet/ClusterSequence_DumbN3.$(ObjSuf) \
+	tmp/external/fastjet/ClusterSequencePassiveArea.$(ObjSuf) \
+	tmp/external/fastjet/BasicRandom.$(ObjSuf) \
+	tmp/external/fastjet/ClusterSequenceAreaBase.$(ObjSuf) \
+	tmp/external/fastjet/PseudoJetStructureBase.$(ObjSuf) \
+	tmp/external/fastjet/ClusterSequence.$(ObjSuf) \
+	tmp/external/fastjet/JetDefinition.$(ObjSuf) \
+	tmp/external/fastjet/Error.$(ObjSuf) \
+	tmp/external/fastjet/RangeDefinition.$(ObjSuf) \
+	tmp/external/fastjet/ClusterSequence_N2.$(ObjSuf) \
+	tmp/external/fastjet/ClusterSequenceStructure.$(ObjSuf) \
+	tmp/external/fastjet/Dnn4piCylinder.$(ObjSuf) \
+	tmp/external/fastjet/ClusterSequence1GhostPassiveArea.$(ObjSuf) \
+	tmp/external/fastjet/MinHeap.$(ObjSuf) \
+	tmp/external/fastjet/PseudoJet.$(ObjSuf) \
+	tmp/external/fastjet/Dnn3piCylinder.$(ObjSuf) \
+	tmp/external/fastjet/ClusterSequence_CP2DChan.$(ObjSuf) \
+	tmp/external/fastjet/ClusterSequenceVoronoiArea.$(ObjSuf) \
+	tmp/external/fastjet/ClosestPair2D.$(ObjSuf) \
+	tmp/external/fastjet/FunctionOfPseudoJet.$(ObjSuf) \
+	tmp/external/fastjet/AreaDefinition.$(ObjSuf) \
+	tmp/external/fastjet/tools/CASubJetTagger.$(ObjSuf) \
+	tmp/external/fastjet/tools/TopTaggerBase.$(ObjSuf) \
+	tmp/external/fastjet/tools/BackgroundEstimatorBase.$(ObjSuf) \
+	tmp/external/fastjet/tools/Subtractor.$(ObjSuf) \
+	tmp/external/fastjet/tools/RestFrameNSubjettinessTagger.$(ObjSuf) \
+	tmp/external/fastjet/tools/JetMedianBackgroundEstimator.$(ObjSuf) \
+	tmp/external/fastjet/tools/MassDropTagger.$(ObjSuf) \
+	tmp/external/fastjet/tools/JHTopTagger.$(ObjSuf) \
+	tmp/external/fastjet/tools/GridMedianBackgroundEstimator.$(ObjSuf) \
+	tmp/external/fastjet/tools/Filter.$(ObjSuf) \
+	tmp/external/fastjet/tools/Pruner.$(ObjSuf) \
+	tmp/external/fastjet/plugins/ATLASCone/ATLASConePlugin.$(ObjSuf) \
+	tmp/external/fastjet/plugins/ATLASCone/JetConeFinderTool.$(ObjSuf) \
+	tmp/external/fastjet/plugins/ATLASCone/Jet.$(ObjSuf) \
+	tmp/external/fastjet/plugins/ATLASCone/JetSplitMergeTool.$(ObjSuf) \
+	tmp/external/fastjet/plugins/NestedDefs/NestedDefsPlugin.$(ObjSuf) \
+	tmp/external/fastjet/plugins/D0RunIICone/D0RunIIConePlugin.$(ObjSuf) \
+	tmp/external/fastjet/plugins/TrackJet/TrackJetPlugin.$(ObjSuf) \
+	tmp/external/fastjet/plugins/CDFCones/CDFMidPointPlugin.$(ObjSuf) \
+	tmp/external/fastjet/plugins/CDFCones/MidPointAlgorithm.$(ObjSuf) \
+	tmp/external/fastjet/plugins/CDFCones/CDFJetCluPlugin.$(ObjSuf) \
+	tmp/external/fastjet/plugins/CDFCones/JetCluAlgorithm.$(ObjSuf) \
+	tmp/external/fastjet/plugins/D0RunICone/D0RunIBaseConePlugin.$(ObjSuf) \
+	tmp/external/fastjet/plugins/SISCone/geom_2d.$(ObjSuf) \
+	tmp/external/fastjet/plugins/SISCone/SISConePlugin.$(ObjSuf) \
+	tmp/external/fastjet/plugins/SISCone/siscone.$(ObjSuf) \
+	tmp/external/fastjet/plugins/SISCone/hash.$(ObjSuf) \
+	tmp/external/fastjet/plugins/SISCone/quadtree.$(ObjSuf) \
+	tmp/external/fastjet/plugins/SISCone/area.$(ObjSuf) \
+	tmp/external/fastjet/plugins/SISCone/momentum.$(ObjSuf) \
+	tmp/external/fastjet/plugins/SISCone/reference.$(ObjSuf) \
+	tmp/external/fastjet/plugins/SISCone/ranlux.$(ObjSuf) \
+	tmp/external/fastjet/plugins/SISCone/protocones.$(ObjSuf) \
+	tmp/external/fastjet/plugins/SISCone/split_merge.$(ObjSuf) \
+	tmp/external/fastjet/plugins/SISCone/vicinity.$(ObjSuf) \
+	tmp/external/fastjet/plugins/SISCone/siscone_error.$(ObjSuf) \
+	tmp/external/fastjet/plugins/CMSIterativeCone/CMSIterativeConePlugin.$(ObjSuf) \
+	tmp/external/fastjet/plugins/GridJet/GridJetPlugin.$(ObjSuf) \
+	tmp/external/fastjet/plugins/Jade/JadePlugin.$(ObjSuf) \
+	tmp/external/fastjet/plugins/EECambridge/EECambridgePlugin.$(ObjSuf)
+
+tmp/display/DelphesDisplay.$(ObjSuf): \
+	display/DelphesDisplay.$(SrcSuf) \
+	display/DelphesDisplay.h
+tmp/display/DelphesCaloData.$(ObjSuf): \
+	display/DelphesCaloData.$(SrcSuf) \
+	display/DelphesCaloData.h
+DISPLAY_OBJ =  \
+	tmp/display/DelphesDisplay.$(ObjSuf) \
+	tmp/display/DelphesCaloData.$(ObjSuf)
+
+tmp/external/tcl/tclObj.$(ObjSuf): \
+	external/tcl/tclObj.c
+tmp/external/tcl/tclUtil.$(ObjSuf): \
+	external/tcl/tclUtil.c
+tmp/external/tcl/tclAsync.$(ObjSuf): \
+	external/tcl/tclAsync.c
+tmp/external/tcl/tclPosixStr.$(ObjSuf): \
+	external/tcl/tclPosixStr.c
+tmp/external/tcl/tclCompile.$(ObjSuf): \
+	external/tcl/tclCompile.c
+tmp/external/tcl/tclHistory.$(ObjSuf): \
+	external/tcl/tclHistory.c
+tmp/external/tcl/tclResolve.$(ObjSuf): \
+	external/tcl/tclResolve.c
+tmp/external/tcl/tclParse.$(ObjSuf): \
+	external/tcl/tclParse.c
+tmp/external/tcl/tclVar.$(ObjSuf): \
+	external/tcl/tclVar.c
+tmp/external/tcl/tclIndexObj.$(ObjSuf): \
+	external/tcl/tclIndexObj.c
+tmp/external/tcl/tclCkalloc.$(ObjSuf): \
+	external/tcl/tclCkalloc.c
+tmp/external/tcl/tclListObj.$(ObjSuf): \
+	external/tcl/tclListObj.c
+tmp/external/tcl/tclHash.$(ObjSuf): \
+	external/tcl/tclHash.c
+tmp/external/tcl/tclCmdIL.$(ObjSuf): \
+	external/tcl/tclCmdIL.c
+tmp/external/tcl/tclStringObj.$(ObjSuf): \
+	external/tcl/tclStringObj.c
+tmp/external/tcl/tclAlloc.$(ObjSuf): \
+	external/tcl/tclAlloc.c
+tmp/external/tcl/tclCompExpr.$(ObjSuf): \
+	external/tcl/tclCompExpr.c
+tmp/external/tcl/tclLink.$(ObjSuf): \
+	external/tcl/tclLink.c
+tmp/external/tcl/tclCmdAH.$(ObjSuf): \
+	external/tcl/tclCmdAH.c
+tmp/external/tcl/panic.$(ObjSuf): \
+	external/tcl/panic.c
+tmp/external/tcl/tclBasic.$(ObjSuf): \
+	external/tcl/tclBasic.c
+tmp/external/tcl/tclPreserve.$(ObjSuf): \
+	external/tcl/tclPreserve.c
+tmp/external/tcl/tclGet.$(ObjSuf): \
+	external/tcl/tclGet.c
+tmp/external/tcl/tclNamesp.$(ObjSuf): \
+	external/tcl/tclNamesp.c
+tmp/external/tcl/tclProc.$(ObjSuf): \
+	external/tcl/tclProc.c
+tmp/external/tcl/tclExecute.$(ObjSuf): \
+	external/tcl/tclExecute.c
+tmp/external/tcl/tclCmdMZ.$(ObjSuf): \
+	external/tcl/tclCmdMZ.c
+TCL_OBJ =  \
+	tmp/external/tcl/tclObj.$(ObjSuf) \
+	tmp/external/tcl/tclUtil.$(ObjSuf) \
+	tmp/external/tcl/tclAsync.$(ObjSuf) \
+	tmp/external/tcl/tclPosixStr.$(ObjSuf) \
+	tmp/external/tcl/tclCompile.$(ObjSuf) \
+	tmp/external/tcl/tclHistory.$(ObjSuf) \
+	tmp/external/tcl/tclResolve.$(ObjSuf) \
+	tmp/external/tcl/tclParse.$(ObjSuf) \
+	tmp/external/tcl/tclVar.$(ObjSuf) \
+	tmp/external/tcl/tclIndexObj.$(ObjSuf) \
+	tmp/external/tcl/tclCkalloc.$(ObjSuf) \
+	tmp/external/tcl/tclListObj.$(ObjSuf) \
+	tmp/external/tcl/tclHash.$(ObjSuf) \
+	tmp/external/tcl/tclCmdIL.$(ObjSuf) \
+	tmp/external/tcl/tclStringObj.$(ObjSuf) \
+	tmp/external/tcl/tclAlloc.$(ObjSuf) \
+	tmp/external/tcl/tclCompExpr.$(ObjSuf) \
+	tmp/external/tcl/tclLink.$(ObjSuf) \
+	tmp/external/tcl/tclCmdAH.$(ObjSuf) \
+	tmp/external/tcl/panic.$(ObjSuf) \
+	tmp/external/tcl/tclBasic.$(ObjSuf) \
+	tmp/external/tcl/tclPreserve.$(ObjSuf) \
+	tmp/external/tcl/tclGet.$(ObjSuf) \
+	tmp/external/tcl/tclNamesp.$(ObjSuf) \
+	tmp/external/tcl/tclProc.$(ObjSuf) \
+	tmp/external/tcl/tclExecute.$(ObjSuf) \
+	tmp/external/tcl/tclCmdMZ.$(ObjSuf)
+
+external/fastjet/internal/ClosestPair2D.hh: \
+	external/fastjet/internal/ClosestPair2DBase.hh \
+	external/fastjet/internal/SearchTree.hh \
+	external/fastjet/internal/MinHeap.hh
+	@touch $@
+
+external/fastjet/ClusterSequence.hh: \
+	external/fastjet/internal/DynamicNearestNeighbours.hh \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/Error.hh \
+	external/fastjet/JetDefinition.hh \
+	external/fastjet/SharedPtr.hh \
+	external/fastjet/LimitedWarning.hh \
+	external/fastjet/FunctionOfPseudoJet.hh \
+	external/fastjet/ClusterSequenceStructure.hh
+	@touch $@
+
+external/fastjet/internal/MinHeap.hh: \
+	external/fastjet/internal/base.hh
+	@touch $@
+
+modules/EnergySmearing.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+modules/LeptonDressing.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+external/fastjet/internal/Voronoi.hh: \
+	external/fastjet/LimitedWarning.hh
+	@touch $@
+
+external/fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh: \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/ClusterSequenceAreaBase.hh \
+	external/fastjet/GhostedAreaSpec.hh \
+	external/fastjet/LimitedWarning.hh
+	@touch $@
+
+modules/ConstituentFilter.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+external/fastjet/JetDefinition.hh: \
+	external/fastjet/internal/numconsts.hh \
+	external/fastjet/PseudoJet.hh
+	@touch $@
+
+modules/Calorimeter.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+classes/DelphesModule.h: \
+	external/ExRootAnalysis/ExRootTask.h
+	@touch $@
+
+modules/Isolation.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+modules/Merger.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+modules/ExampleModule.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+external/fastjet/internal/Dnn2piCylinder.hh: \
+	external/fastjet/internal/DynamicNearestNeighbours.hh \
+	external/fastjet/internal/DnnPlane.hh \
+	external/fastjet/internal/numconsts.hh
+	@touch $@
+
+modules/JetPileUpSubtractor.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+external/fastjet/Selector.hh: \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/RangeDefinition.hh
+	@touch $@
+
+external/fastjet/Error.hh: \
+	external/fastjet/internal/base.hh
+	@touch $@
+
+modules/Efficiency.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+modules/TrackPileUpSubtractor.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+external/fastjet/tools/GridMedianBackgroundEstimator.hh: \
+	external/fastjet/tools/BackgroundEstimatorBase.hh
+	@touch $@
+
+external/fastjet/internal/DnnPlane.hh: \
+	external/fastjet/internal/Triangulation.hh \
+	external/fastjet/internal/DynamicNearestNeighbours.hh
+	@touch $@
+
+external/fastjet/ClusterSequenceArea.hh: \
+	external/fastjet/ClusterSequenceAreaBase.hh \
+	external/fastjet/ClusterSequenceActiveArea.hh \
+	external/fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh \
+	external/fastjet/ClusterSequencePassiveArea.hh \
+	external/fastjet/ClusterSequenceVoronoiArea.hh \
+	external/fastjet/AreaDefinition.hh
+	@touch $@
+
+external/fastjet/ClusterSequence1GhostPassiveArea.hh: \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/ClusterSequenceAreaBase.hh \
+	external/fastjet/ClusterSequenceActiveArea.hh
+	@touch $@
+
+modules/PileUpMerger.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+modules/Cloner.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+external/fastjet/PseudoJet.hh: \
+	external/fastjet/internal/numconsts.hh \
+	external/fastjet/internal/IsBase.hh \
+	external/fastjet/SharedPtr.hh \
+	external/fastjet/Error.hh \
+	external/fastjet/PseudoJetStructureBase.hh
+	@touch $@
+
+external/fastjet/tools/Pruner.hh: \
+	external/fastjet/ClusterSequence.hh \
+	external/fastjet/WrappedStructure.hh \
+	external/fastjet/tools/Transformer.hh
+	@touch $@
+
+external/fastjet/version.hh: \
+	external/fastjet/config.h
+	@touch $@
+
+modules/MomentumSmearing.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+modules/TauTagging.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+external/fastjet/GhostedAreaSpec.hh: \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/internal/BasicRandom.hh \
+	external/fastjet/Selector.hh \
+	external/fastjet/LimitedWarning.hh
+	@touch $@
+
+external/fastjet/internal/Dnn4piCylinder.hh: \
+	external/fastjet/internal/DynamicNearestNeighbours.hh \
+	external/fastjet/internal/DnnPlane.hh \
+	external/fastjet/internal/numconsts.hh
+	@touch $@
+
+modules/Delphes.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+modules/UniqueObjectFinder.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+external/fastjet/ClusterSequenceActiveArea.hh: \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/ClusterSequenceAreaBase.hh \
+	external/fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh
+	@touch $@
+
+modules/ParticlePropagator.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+external/fastjet/plugins/CDFCones/fastjet/CDFMidPointPlugin.hh: \
+	external/fastjet/JetDefinition.hh
+	@touch $@
+
+external/fastjet/RangeDefinition.hh: \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/Error.hh \
+	external/fastjet/LimitedWarning.hh
+	@touch $@
+
+external/fastjet/PseudoJetStructureBase.hh: \
+	external/fastjet/internal/base.hh
+	@touch $@
+
+external/fastjet/ClusterSequenceAreaBase.hh: \
+	external/fastjet/ClusterSequence.hh \
+	external/fastjet/LimitedWarning.hh \
+	external/fastjet/Selector.hh
+	@touch $@
+
+external/fastjet/ClusterSequenceVoronoiArea.hh: \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/AreaDefinition.hh \
+	external/fastjet/ClusterSequenceAreaBase.hh
+	@touch $@
+
+modules/BTagging.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+external/fastjet/internal/BasicRandom.hh: \
+	external/fastjet/internal/base.hh
+	@touch $@
+
+external/fastjet/plugins/CDFCones/fastjet/CDFJetCluPlugin.hh: \
+	external/fastjet/JetDefinition.hh \
+	external/fastjet/PseudoJet.hh
+	@touch $@
+
+external/ExRootAnalysis/ExRootTask.h: \
+	external/ExRootAnalysis/ExRootConfReader.h
+	@touch $@
+
+external/fastjet/tools/Subtractor.hh: \
+	external/fastjet/tools/Transformer.hh \
+	external/fastjet/tools/BackgroundEstimatorBase.hh
+	@touch $@
+
+external/fastjet/AreaDefinition.hh: \
+	external/fastjet/GhostedAreaSpec.hh
+	@touch $@
+
+external/fastjet/internal/Dnn3piCylinder.hh: \
+	external/fastjet/internal/DynamicNearestNeighbours.hh \
+	external/fastjet/internal/DnnPlane.hh \
+	external/fastjet/internal/numconsts.hh
+	@touch $@
+
+modules/TreeWriter.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+external/fastjet/ClusterSequenceStructure.hh: \
+	external/fastjet/internal/base.hh \
+	external/fastjet/SharedPtr.hh \
+	external/fastjet/PseudoJetStructureBase.hh
+	@touch $@
+
+modules/StatusPidFilter.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+external/fastjet/config.h: \
+	external/fastjet/config_win.h
+	@touch $@
+
+external/fastjet/LimitedWarning.hh: \
+	external/fastjet/internal/base.hh
+	@touch $@
+
+classes/DelphesClasses.h: \
+	classes/SortableObject.h
+	@touch $@
+
+external/fastjet/ClusterSequencePassiveArea.hh: \
+	external/fastjet/PseudoJet.hh \
+	external/fastjet/ClusterSequence1GhostPassiveArea.hh
+	@touch $@
+
+modules/FastJetFinder.h: \
+	classes/DelphesModule.h
+	@touch $@
+
+
+
+###
+
+all: $(DELPHES) $(EXECUTABLE)
+
+display: $(DISPLAY)
+
+$(DELPHES): $(DELPHES_DICT_OBJ) $(DELPHES_OBJ) $(TCL_OBJ)
+	@mkdir -p $(@D)
+	@echo ">> Building $@"
+ifeq ($(ARCH),aix5)
+	@$(MAKESHARED) $(OutPutOpt) $@ $(DELPHES_LIBS) -p 0 $^
+else
+ifeq ($(PLATFORM),macosx)
+# We need to make both the .dylib and the .so
+	@$(LD) $(SOFLAGS)$@ $(LDFLAGS) $^ $(OutPutOpt) $@ $(DELPHES_LIBS)
+ifneq ($(subst $(MACOSX_MINOR),,1234),1234)
+ifeq ($(MACOSX_MINOR),4)
+	@ln -sf $@ $(subst .$(DllSuf),.so,$@)
+endif
+endif
+else
+ifeq ($(PLATFORM),win32)
+	@bindexplib $* $^ > $*.def
+	@lib -nologo -MACHINE:IX86 $^ -def:$*.def $(OutPutOpt)$(DELPHESLIB)
+	@$(LD) $(SOFLAGS) $(LDFLAGS) $^ $*.exp $(DELPHES_LIBS) $(OutPutOpt)$@
+	@$(MT_DLL)
+else
+	@$(LD) $(SOFLAGS) $(LDFLAGS) $^ $(OutPutOpt) $@ $(DELPHES_LIBS)
+	@$(MT_DLL)
+endif
+endif
+endif
+
+$(DISPLAY): $(DELPHES_DICT_OBJ) $(DISPLAY_DICT_OBJ) $(DELPHES_OBJ) $(DISPLAY_OBJ) $(TCL_OBJ)
+	@mkdir -p $(@D)
+	@echo ">> Building $@"
+ifeq ($(ARCH),aix5)
+	@$(MAKESHARED) $(OutPutOpt) $@ $(DISPLAY_LIBS) -p 0 $^
+else
+ifeq ($(PLATFORM),macosx)
+# We need to make both the .dylib and the .so
+	@$(LD) $(SOFLAGS)$@ $(LDFLAGS) $^ $(OutPutOpt) $@ $(DISPLAY_LIBS)
+ifneq ($(subst $(MACOSX_MINOR),,1234),1234)
+ifeq ($(MACOSX_MINOR),4)
+	@ln -sf $@ $(subst .$(DllSuf),.so,$@)
+endif
+endif
+else
+ifeq ($(PLATFORM),win32)
+	@bindexplib $* $^ > $*.def
+	@lib -nologo -MACHINE:IX86 $^ -def:$*.def $(OutPutOpt)$(DISPLAYLIB)
+	@$(LD) $(SOFLAGS) $(LDFLAGS) $^ $*.exp $(DISPLAY_LIBS) $(OutPutOpt)$@
+	@$(MT_DLL)
+else
+	@$(LD) $(SOFLAGS) $(LDFLAGS) $^ $(OutPutOpt) $@ $(DISPLAY_LIBS)
+	@$(MT_DLL)
+endif
+endif
+endif
+
+clean:
+	@rm -f $(DELPHES_DICT_OBJ) $(DISPLAY_DICT_OBJ) $(DELPHES_OBJ) $(DISPLAY_OBJ) $(TCL_OBJ) core
+	@rm -rf tmp
+
+distclean: clean
+	@rm -f $(DELPHES) $(DELPHESLIB) $(DISPLAY) $(DISPLAYLIB) $(EXECUTABLE)
+
+dist:
+	@echo ">> Building $(DISTTAR)"
+	@mkdir -p $(DISTDIR)
+	@cp -a CREDITS README VERSION Makefile configure classes converters display doc examples external modules python readers $(DISTDIR)
+	@find $(DISTDIR) -depth -name .\* -exec rm -rf {} \;
+	@tar -czf $(DISTTAR) $(DISTDIR)
+	@rm -rf $(DISTDIR)
+
+###
+
+.SUFFIXES: .$(SrcSuf) .$(ObjSuf) .$(DllSuf)
+
+%Dict.$(SrcSuf):
+	@mkdir -p $(@D)
+	@echo ">> Generating $@"
+	@rootcint -f $@ -c -Iexternal $<
+	@echo "#define private public" > $@.arch
+	@echo "#define protected public" >> $@.arch
+	@mv $@ $@.base
+	@cat $@.arch $< $@.base > $@
+	@rm $@.arch $@.base
+
+$(DELPHES_OBJ): tmp/%.$(ObjSuf): %.$(SrcSuf)
+	@mkdir -p $(@D)
+	@echo ">> Compiling $<"
+	@$(CXX) $(CXXFLAGS) -c $< $(OutPutOpt)$@
+
+$(DISPLAY_OBJ): tmp/%.$(ObjSuf): %.$(SrcSuf)
+	@mkdir -p $(@D)
+	@echo ">> Compiling $<"
+	@$(CXX) $(CXXFLAGS) -c $< $(OutPutOpt)$@
+
+$(DELPHES_DICT_OBJ): %.$(ObjSuf): %.$(SrcSuf)
+	@mkdir -p $(@D)
+	@echo ">> Compiling $<"
+	@$(CXX) $(CXXFLAGS) -c $< $(OutPutOpt)$@
+
+$(DISPLAY_DICT_OBJ): %.$(ObjSuf): %.$(SrcSuf)
+	@mkdir -p $(@D)
+	@echo ">> Compiling $<"
+	@$(CXX) $(CXXFLAGS) -c $< $(OutPutOpt)$@
+
+$(TCL_OBJ): tmp/%.$(ObjSuf): %.c
+	@mkdir -p $(@D)
+	@echo ">> Compiling $<"
+	@gcc $(CXXFLAGS) -c $< $(OutPutOpt)$@
+
+$(EXECUTABLE_OBJ): tmp/%.$(ObjSuf): %.cpp
+	@mkdir -p $(@D)
+	@echo ">> Compiling $<"
+	@$(CXX) $(CXXFLAGS) -c $< $(OutPutOpt)$@
+
+$(EXECUTABLE): %$(ExeSuf): $(DELPHES_DICT_OBJ) $(DELPHES_OBJ) $(TCL_OBJ)
+	@echo ">> Building $@"
+	@$(LD) $(LDFLAGS) $^ $(DELPHES_LIBS) $(OutPutOpt)$@
+
+###
+
+
Index: trunk/Delphes/Delphes-3.0.9/README
===================================================================
--- trunk/Delphes/Delphes-3.0.9/README	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/README	(revision 5)
@@ -0,0 +1,139 @@
+Quick start with Delphes
+========================
+
+Commands to get the code:
+
+   wget http://cp3.irmp.ucl.ac.be/downloads/Delphes-3.0.9.tar.gz
+
+   tar -zxf Delphes-3.0.9.tar.gz
+
+Commands to compile the code:
+
+   cd Delphes-3.0.9
+
+   make
+
+Finally, we can run Delphes:
+
+   ./DelphesHepMC
+
+Command line parameters:
+
+   ./DelphesHepMC config_file output_file [input_file(s)]
+     config_file - configuration file in Tcl format
+     output_file - output file in ROOT format,
+     input_file(s) - input file(s) in HepMC format,
+     with no input_file, or when input_file is -, read standard input.
+
+Let's simulate some Z->ee events:
+
+   wget http://cp3.irmp.ucl.ac.be/downloads/z_ee.hep.gz
+   gunzip z_ee.hep.gz
+   ./DelphesSTDHEP examples/delphes_card_CMS.tcl delphes_output.root z_ee.hep
+
+or
+
+   curl -s http://cp3.irmp.ucl.ac.be/downloads/z_ee.hep.gz | gunzip | ./DelphesSTDHEP examples/delphes_card_CMS.tcl delphes_output.root
+
+For more detailed documentation, please visit 
+
+https://cp3.irmp.ucl.ac.be/projects/delphes/wiki/WorkBook
+
+
+Simple analysis using TTree::Draw
+=================================
+
+Now we can start ROOT and look at the data stored in the output ROOT file.
+
+Start ROOT and load Delphes shared library:
+
+   root -l
+   gSystem->Load("libDelphes");
+
+Open ROOT file and do some basic analysis using Draw or TBrowser:
+
+   TFile::Open("delphes_output.root");
+   Delphes->Draw("Electron.PT");
+   TBrowser browser;
+
+Note 1: Delphes - tree name, it can be learned e.g. from TBrowser
+
+Note 2: Electron - branch name; PT - variable (leaf) of this branch
+
+Complete description of all branches can be found in
+
+   doc/RootTreeDescription.html
+
+This information is also available at
+
+   https://cp3.irmp.ucl.ac.be/projects/delphes/wiki/WorkBook/RootTreeDescription
+
+
+Macro-based analysis
+====================
+
+Analysis macro consists of histogram booking, event loop (histogram filling),
+histogram display.
+
+Start ROOT and load Delphes shared library:
+
+   root -l
+   gSystem->Load("libDelphes");
+
+Basic analysis macro:
+
+{
+  // Create chain of root trees
+  TChain chain("Delphes");
+  chain.Add("delphes_output.root");
+  
+  // Create object of class ExRootTreeReader
+  ExRootTreeReader *treeReader = new ExRootTreeReader(&chain);
+  Long64_t numberOfEntries = treeReader->GetEntries();
+  
+  // Get pointers to branches used in this analysis
+  TClonesArray *branchElectron = treeReader->UseBranch("Electron");
+
+  // Book histograms
+  TH1 *histElectronPT = new TH1F("electron pt", "electron P_{T}", 50, 0.0, 100.0);
+
+  // Loop over all events
+  for(Int_t entry = 0; entry < numberOfEntries; ++entry)
+  {
+
+    // Load selected branches with data from specified event
+    treeReader->ReadEntry(entry);
+  
+    // If event contains at least 1 electron
+    if(branchElectron->GetEntries() > 0)
+    {
+      // Take first electron
+      Electron *electron = (Electron*) branchElectron->At(0);
+      
+      // Plot electron transverse momentum
+      histElectronPT->Fill(electron->PT);
+      
+      // Print electron transverse momentum
+      cout << electron->PT << endl;
+    }
+
+  }
+
+  // Show resulting histograms
+  histElectronPT->Draw();
+}
+
+
+More advanced macro-based analysis
+==================================
+
+The 'examples' directory contains ROOT macros Example1.C, Example2.C and Example3.C.
+
+Here are the commands to run these ROOT macros:
+
+   root -l
+   .X examples/Example1.C("delphes_output.root");
+
+or
+
+   root -l examples/Example1.C\(\"delphes_output.root\"\)
Index: trunk/Delphes/Delphes-3.0.9/VERSION
===================================================================
--- trunk/Delphes/Delphes-3.0.9/VERSION	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/VERSION	(revision 5)
@@ -0,0 +1,1 @@
+3.0.9
Index: trunk/Delphes/Delphes-3.0.9/classes/ClassesLinkDef.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/ClassesLinkDef.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/ClassesLinkDef.h	(revision 5)
@@ -0,0 +1,49 @@
+
+/** ExRootAnalysisLinkDef
+ *
+ *  Lists classes to be included in cint dicitonary
+ *
+ *  $Date: 2008-07-08 12:01:52 $
+ *  $Revision: 1.2 $
+ *
+ *  
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+#include "classes/DelphesFactory.h"
+
+#include "classes/SortableObject.h"
+#include "classes/DelphesClasses.h"
+
+#ifdef __CINT__
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+#pragma link C++ class DelphesModule+;
+#pragma link C++ class DelphesFactory+;
+
+#pragma link C++ class SortableObject+;
+
+#pragma link C++ class Event+;
+#pragma link C++ class LHCOEvent+;
+#pragma link C++ class LHEFEvent+;
+#pragma link C++ class HepMCEvent+;
+#pragma link C++ class GenParticle+;
+#pragma link C++ class MissingET+;
+#pragma link C++ class ScalarHT+;
+#pragma link C++ class Rho+;
+#pragma link C++ class Photon+;
+#pragma link C++ class Electron+;
+#pragma link C++ class Muon+;
+#pragma link C++ class Jet+;
+#pragma link C++ class Track+;
+#pragma link C++ class Tower+;
+
+#pragma link C++ class Candidate+;
+
+#endif
+
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesClasses.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesClasses.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesClasses.cc	(revision 5)
@@ -0,0 +1,240 @@
+
+/**
+ *
+ *  Definition of classes to be stored in the root tree.
+ *  Function CompareXYZ sorts objects by the variable XYZ that MUST be
+ *  present in the data members of the root tree class of the branch.
+ *
+ *  $Date: 2008-06-04 13:57:24 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesClasses.h"
+
+#include "classes/DelphesFactory.h"
+#include "classes/SortableObject.h"
+
+CompBase *GenParticle::fgCompare = 0;
+CompBase *Photon::fgCompare = CompPT<Photon>::Instance();
+CompBase *Electron::fgCompare = CompPT<Electron>::Instance();
+CompBase *Muon::fgCompare = CompPT<Muon>::Instance();
+CompBase *Jet::fgCompare = CompPT<Jet>::Instance();
+CompBase *Track::fgCompare = CompPT<Track>::Instance();
+CompBase *Tower::fgCompare = CompE<Tower>::Instance();
+CompBase *Candidate::fgCompare = CompMomentumPt<Candidate>::Instance();
+
+//------------------------------------------------------------------------------
+
+TLorentzVector GenParticle::P4()
+{
+  TLorentzVector vec;
+  vec.SetPxPyPzE(Px, Py, Pz, E);
+  return vec;
+}
+
+//------------------------------------------------------------------------------
+
+TLorentzVector Photon::P4()
+{
+  TLorentzVector vec;
+  vec.SetPtEtaPhiM(PT, Eta, Phi, 0.0);
+  return vec;
+}
+
+//------------------------------------------------------------------------------
+
+TLorentzVector Electron::P4()
+{
+  TLorentzVector vec;
+  vec.SetPtEtaPhiM(PT, Eta, Phi, 0.0);
+  return vec;
+}
+
+//------------------------------------------------------------------------------
+
+TLorentzVector Muon::P4()
+{
+  TLorentzVector vec;
+  vec.SetPtEtaPhiM(PT, Eta, Phi, 0.0);
+  return vec;
+}
+
+//------------------------------------------------------------------------------
+
+TLorentzVector Jet::P4()
+{
+  TLorentzVector vec;
+  vec.SetPtEtaPhiM(PT, Eta, Phi, Mass);
+  return vec;
+}
+
+//------------------------------------------------------------------------------
+
+TLorentzVector Track::P4()
+{
+  TLorentzVector vec;
+  vec.SetPtEtaPhiM(PT, Eta, Phi, 0.0);
+  return vec;
+}
+
+//------------------------------------------------------------------------------
+
+TLorentzVector Tower::P4()
+{
+  TLorentzVector vec;
+  vec.SetPtEtaPhiM(ET, Eta, Phi, 0.0);
+  return vec;
+}
+
+//------------------------------------------------------------------------------
+
+Candidate::Candidate() :
+  PID(0), Status(0), M1(-1), M2(-1), D1(-1), D2(-1),
+  Charge(0), Mass(0.0),
+  IsPU(0), IsConstituent(0),
+  BTag(0), TauTag(0), Eem(0.0), Ehad(0.0),
+  DeltaEta(0.0), DeltaPhi(0.0),
+  Momentum(0.0, 0.0, 0.0, 0.0),
+  Position(0.0, 0.0, 0.0, 0.0),
+  Area(0.0, 0.0, 0.0, 0.0),
+  fFactory(0),
+  fArray(0)
+{
+  Edges[0] = 0.0;
+  Edges[1] = 0.0;
+  Edges[2] = 0.0;
+  Edges[3] = 0.0;
+}
+
+//------------------------------------------------------------------------------
+
+void Candidate::AddCandidate(Candidate *object)
+{
+  if(!fArray) fArray = fFactory->NewArray();
+  fArray->Add(object);
+}
+
+//------------------------------------------------------------------------------
+
+TObjArray *Candidate::GetCandidates()
+{
+  if(!fArray) fArray = fFactory->NewArray();
+  return fArray;
+}
+
+//------------------------------------------------------------------------------
+
+Bool_t Candidate::Overlaps(const Candidate *object) const
+{
+  const Candidate *candidate;
+
+  if(object->GetUniqueID() == GetUniqueID()) return kTRUE;
+
+  if(fArray)
+  {
+    TIter it(fArray);
+    while((candidate = static_cast<Candidate *>(it.Next())))
+    {
+      if(candidate->Overlaps(object)) return kTRUE;
+    }
+  }
+
+  if(object->fArray)
+  {
+    TIter it(object->fArray);
+    while((candidate = static_cast<Candidate *>(it.Next())))
+    {
+      if(candidate->Overlaps(this)) return kTRUE;
+    }
+  }
+
+  return kFALSE;
+}
+
+
+//------------------------------------------------------------------------------
+
+TObject *Candidate::Clone(const char *newname) const
+{
+  Candidate *object = fFactory->NewCandidate();
+  Copy(*object);
+  return object;
+}
+
+//------------------------------------------------------------------------------
+
+void Candidate::Copy(TObject &obj) const
+{
+  Candidate &object = static_cast<Candidate &>(obj);
+  Candidate *candidate;
+
+  object.PID = PID;
+  object.Status = Status;
+  object.M1 = M1;
+  object.M2 = M2;
+  object.D1 = D1;
+  object.D2 = D2;
+  object.Charge = Charge;
+  object.Mass = Mass;
+  object.IsPU = IsPU;
+  object.IsConstituent = IsConstituent;
+  object.BTag = BTag;
+  object.TauTag = TauTag;
+  object.Eem = Eem;
+  object.Ehad = Ehad;
+  object.Edges[0] = Edges[0];
+  object.Edges[1] = Edges[1];
+  object.Edges[2] = Edges[2];
+  object.Edges[3] = Edges[3];
+  object.DeltaEta = DeltaEta;
+  object.DeltaPhi = DeltaPhi;
+  object.Momentum = Momentum;
+  object.Position = Position;
+  object.Area = Area;
+
+  object.fFactory = fFactory;
+  object.fArray = 0;
+
+  if(fArray && fArray->GetEntriesFast() > 0)
+  {
+    TIter itArray(fArray);
+    TObjArray *array = object.GetCandidates();
+    while((candidate = static_cast<Candidate *>(itArray.Next())))
+    {
+      array->Add(candidate);
+    }
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void Candidate::Clear(Option_t* option)
+{
+  SetUniqueID(0);
+  ResetBit(kIsReferenced);
+  PID = 0;
+  Status = 0;
+  M1 = -1; M2 = -1; D1 = -1; D2 = -1;
+  Charge = 0;
+  Mass = 0.0;
+  IsPU = 0;
+  IsConstituent = 0;
+  BTag = 0;
+  TauTag = 0;
+  Eem = 0.0;
+  Ehad = 0.0;
+  Edges[0] = 0.0;
+  Edges[1] = 0.0;
+  Edges[2] = 0.0;
+  Edges[3] = 0.0;
+  DeltaEta = 0.0;
+  DeltaPhi = 0.0;
+  Momentum.SetXYZT(0.0, 0.0, 0.0, 0.0);
+  Position.SetXYZT(0.0, 0.0, 0.0, 0.0);
+  Area.SetXYZT(0.0, 0.0, 0.0, 0.0);
+  fArray = 0;
+}
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesClasses.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesClasses.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesClasses.h	(revision 5)
@@ -0,0 +1,395 @@
+#ifndef DelphesClasses_h
+#define DelphesClasses_h
+
+/**
+ *
+ *  Definition of classes to be stored in the root tree.
+ *  Function CompareXYZ sorts objects by the variable XYZ that MUST be
+ *  present in the data members of the root tree class of the branch.
+ *
+ *  $Date: 2008-06-04 13:57:24 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+// Dependencies (#includes)
+
+#include "TRef.h"
+#include "TObject.h"
+#include "TRefArray.h"
+#include "TLorentzVector.h"
+
+#include "classes/SortableObject.h"
+
+class DelphesFactory;
+
+//---------------------------------------------------------------------------
+
+class Event: public TObject
+{
+public:
+
+  Long64_t Number; // event number
+
+  Float_t ReadTime;
+  Float_t ProcTime;  
+
+  ClassDef(Event, 1)
+};
+
+//---------------------------------------------------------------------------
+
+class LHCOEvent: public Event
+{
+public:
+
+  Int_t Trigger; // trigger word
+
+  ClassDef(LHCOEvent, 1)
+};
+
+//---------------------------------------------------------------------------
+
+class LHEFEvent: public Event
+{
+public:
+
+  Int_t ProcessID; // subprocess code for the event | hepup.IDPRUP
+
+  Float_t Weight; // weight for the event | hepup.XWGTUP
+  Float_t ScalePDF; // scale in GeV used in the calculation of the PDFs in the event | hepup.SCALUP
+  Float_t AlphaQED; // value of the QED coupling used in the event | hepup.AQEDUP
+  Float_t AlphaQCD; // value of the QCD coupling used in the event | hepup.AQCDUP
+
+  ClassDef(LHEFEvent, 2)
+};
+
+//---------------------------------------------------------------------------
+
+class HepMCEvent: public Event
+{
+public:
+
+  Int_t ProcessID; // unique signal process id | signal_process_id()
+  Int_t MPI; // number of multi parton interactions | mpi () 
+
+  Float_t Weight; // weight for the event
+
+  Float_t Scale; // energy scale, see hep-ph/0109068 | event_scale()
+  Float_t AlphaQED; // QED coupling, see hep-ph/0109068 | alphaQED()
+  Float_t AlphaQCD; // QCD coupling, see hep-ph/0109068 | alphaQCD()
+
+  Int_t ID1; // flavour code of first parton | pdf_info()->id1()
+  Int_t ID2; // flavour code of second parton | pdf_info()->id2()     
+
+  Float_t X1; // fraction of beam momentum carried by first parton ("beam side") | pdf_info()->x1()
+  Float_t X2; // fraction of beam momentum carried by second parton ("target side") | pdf_info()->x2()
+
+  Float_t ScalePDF; // Q-scale used in evaluation of PDF's (in GeV) | pdf_info()->scalePDF()
+
+  Float_t PDF1; // PDF (id1, x1, Q) | pdf_info()->pdf1()
+  Float_t PDF2; // PDF (id2, x2, Q) | pdf_info()->pdf2()
+
+  ClassDef(HepMCEvent, 2)
+};
+
+//---------------------------------------------------------------------------
+
+class GenParticle: public SortableObject
+{
+public:
+  Int_t PID; // particle HEP ID number | hepevt.idhep[number]
+
+  Int_t Status; // particle status | hepevt.isthep[number]
+  Int_t IsPU; // 0 or 1 for particles from pile-up interactions
+  
+
+  Int_t M1; // particle 1st mother | hepevt.jmohep[number][0] - 1
+  Int_t M2; // particle 2nd mother | hepevt.jmohep[number][1] - 1
+
+  Int_t D1; // particle 1st daughter | hepevt.jdahep[number][0] - 1
+  Int_t D2; // particle last daughter | hepevt.jdahep[number][1] - 1
+
+  Int_t Charge; // particle charge
+
+  Float_t Mass; // particle mass
+
+  Float_t E; // particle energy | hepevt.phep[number][3]
+  Float_t Px; // particle momentum vector (x component) | hepevt.phep[number][0]
+  Float_t Py; // particle momentum vector (y component) | hepevt.phep[number][1]
+  Float_t Pz; // particle momentum vector (z component) | hepevt.phep[number][2]
+
+  Float_t PT; // particle transverse momentum
+  Float_t Eta; // particle pseudorapidity
+  Float_t Phi; // particle azimuthal angle
+
+  Float_t Rapidity; // particle rapidity
+
+  Float_t T; // particle vertex position (t component) | hepevt.vhep[number][3]
+  Float_t X; // particle vertex position (x component) | hepevt.vhep[number][0]
+  Float_t Y; // particle vertex position (y component) | hepevt.vhep[number][1]
+  Float_t Z; // particle vertex position (z component) | hepevt.vhep[number][2]
+
+  static CompBase *fgCompare; //!
+  const CompBase *GetCompare() const { return fgCompare; }
+  
+  TLorentzVector P4();
+
+  ClassDef(GenParticle, 1)
+};
+
+//---------------------------------------------------------------------------
+
+class MissingET: public TObject
+{
+public:
+  Float_t MET; // mising transverse energy
+  Float_t Phi; // mising energy azimuthal angle
+
+  ClassDef(MissingET, 1)
+};
+
+//---------------------------------------------------------------------------
+
+class ScalarHT: public TObject
+{
+public:
+  Float_t HT; // scalar sum of transverse momenta
+
+  ClassDef(ScalarHT, 1)
+};
+
+//---------------------------------------------------------------------------
+
+class Rho: public TObject
+{
+public:
+  Float_t Rho; // rho energy density
+
+  ClassDef(Rho, 1)
+};
+
+//---------------------------------------------------------------------------
+
+class Photon: public SortableObject
+{
+public:
+
+  Float_t PT; // photon transverse momentum
+  Float_t Eta; // photon pseudorapidity
+  Float_t Phi; // photon azimuthal angle
+
+  Float_t E; // photon energy
+  
+  Float_t EhadOverEem; // ratio of the hadronic versus electromagnetic energy deposited in the calorimeter
+
+  TRefArray Particles; // references to generated particles
+
+  static CompBase *fgCompare; //!
+  const CompBase *GetCompare() const { return fgCompare; }
+
+  TLorentzVector P4();
+
+  ClassDef(Photon, 2)
+};
+
+//---------------------------------------------------------------------------
+
+class Electron: public SortableObject
+{
+public:
+
+  Float_t PT; // electron transverse momentum
+  Float_t Eta; // electron pseudorapidity
+  Float_t Phi; // electron azimuthal angle
+
+  Int_t Charge; // electron charge
+
+  Float_t EhadOverEem; // ratio of the hadronic versus electromagnetic energy deposited in the calorimeter
+
+  TRef Particle; // reference to generated particle
+
+  static CompBase *fgCompare; //!
+  const CompBase *GetCompare() const { return fgCompare; }
+
+  TLorentzVector P4();
+
+  ClassDef(Electron, 2)
+};
+
+//---------------------------------------------------------------------------
+
+class Muon: public SortableObject
+{
+public:
+
+  Float_t PT; // muon transverse momentum
+  Float_t Eta; // muon pseudorapidity
+  Float_t Phi; // muon azimuthal angle
+
+  Int_t Charge; // muon charge
+
+  TRef Particle; // reference to generated particle
+
+  static CompBase *fgCompare; //!
+  const CompBase *GetCompare() const { return fgCompare; }
+
+  TLorentzVector P4();
+
+  ClassDef(Muon, 2)
+};
+
+//---------------------------------------------------------------------------
+
+class Jet: public SortableObject
+{
+public:
+
+  Float_t PT; // jet transverse momentum
+  Float_t Eta; // jet pseudorapidity
+  Float_t Phi; // jet azimuthal angle
+
+  Float_t Mass; // jet invariant mass
+
+  Float_t DeltaEta;  // jet radius in pseudorapidity
+  Float_t DeltaPhi;  // jet radius in azimuthal angle
+
+  UInt_t BTag; // 0 or 1 for a jet that has been tagged as containing a heavy quark
+  UInt_t TauTag; // 0 or 1 for a jet that has been tagged as a tau
+
+  Int_t Charge; // tau charge
+
+  Float_t EhadOverEem; // ratio of the hadronic versus electromagnetic energy deposited in the calorimeter
+
+  TRefArray Constituents; // references to constituents
+  TRefArray Particles; // references to generated particles
+
+  static CompBase *fgCompare; //!
+  const CompBase *GetCompare() const { return fgCompare; }
+
+  TLorentzVector P4();
+
+  ClassDef(Jet, 2)
+};
+
+//---------------------------------------------------------------------------
+
+class Track: public SortableObject 
+{
+public:  
+  Int_t PID; // HEP ID number
+
+  Int_t Charge; // track charge
+
+  Float_t PT; // track transverse momentum
+
+  Float_t Eta; // track pseudorapidity
+  Float_t Phi; // track azimuthal angle
+
+  Float_t EtaOuter; // track pseudorapidity at the tracker edge
+  Float_t PhiOuter; // track azimuthal angle at the tracker edge
+
+  Float_t X; // track vertex position (x component)
+  Float_t Y; // track vertex position (y component)
+  Float_t Z; // track vertex position (z component)
+
+  Float_t XOuter; // track position (x component) at the tracker edge
+  Float_t YOuter; // track position (y component) at the tracker edge
+  Float_t ZOuter; // track position (z component) at the tracker edge
+
+  TRef Particle; // reference to generated particle
+
+  static CompBase *fgCompare; //!
+  const CompBase *GetCompare() const { return fgCompare; }
+
+  TLorentzVector P4();
+
+  ClassDef(Track, 1)
+};
+
+//---------------------------------------------------------------------------
+
+class Tower: public SortableObject 
+{
+public:
+  Float_t ET; // calorimeter tower transverse energy
+  Float_t Eta; // calorimeter tower pseudorapidity
+  Float_t Phi; // calorimeter tower azimuthal angle
+
+  Float_t E; // calorimeter tower energy
+
+  Float_t Eem; // calorimeter tower electromagnetic energy
+  Float_t Ehad; // calorimeter tower hadronic energy
+
+  Float_t Edges[4]; // calorimeter tower edges
+
+  TRefArray Particles; // references to generated particles
+
+  static CompBase *fgCompare; //!
+  const CompBase *GetCompare() const { return fgCompare; }
+
+  TLorentzVector P4();
+
+  ClassDef(Tower, 1)
+};
+
+//---------------------------------------------------------------------------
+
+class Candidate: public SortableObject 
+{
+  friend class DelphesFactory;
+
+public:
+  Candidate();
+
+  Int_t PID;
+
+  Int_t Status;
+  Int_t M1, M2, D1, D2;
+
+  Int_t Charge;
+
+  Float_t Mass;
+  
+  Int_t IsPU;
+  Int_t IsConstituent;
+  
+  UInt_t BTag;
+  UInt_t TauTag;
+
+  Float_t Eem;
+  Float_t Ehad;
+
+  Float_t Edges[4];
+  Float_t DeltaEta;
+  Float_t DeltaPhi;
+
+  TLorentzVector Momentum, Position, Area;
+
+  static CompBase *fgCompare; //!
+  const CompBase *GetCompare() const { return fgCompare; }
+
+  void AddCandidate(Candidate *object);
+  TObjArray *GetCandidates();
+
+  Bool_t Overlaps(const Candidate *object) const;
+
+  virtual void Copy(TObject &object) const;
+  virtual TObject *Clone(const char *newname = "") const;
+  virtual void Clear(Option_t* option = ""); 
+
+private:
+  DelphesFactory *fFactory; //!
+  TObjArray *fArray; //!
+  
+  void SetFactory(DelphesFactory *factory) { fFactory = factory; }
+
+  ClassDef(Candidate, 1)
+};
+
+#endif // DelphesClasses_h
+
+
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesFactory.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesFactory.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesFactory.cc	(revision 5)
@@ -0,0 +1,108 @@
+
+/** \class DelphesFactory
+ *
+ *  Class handling creation of Candidate,
+ *  TObjArray and all other objects.
+ *
+ *  $Date: 2008-06-04 13:57:25 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesClasses.h"
+
+#include "ExRootAnalysis/ExRootTreeBranch.h"
+
+#include "TClass.h"
+#include "TObjArray.h"
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+DelphesFactory::DelphesFactory(const char *name) :
+  TNamed(name, ""), fObjArrays(0)
+{
+  fObjArrays = new ExRootTreeBranch("PermanentObjArrays", TObjArray::Class(), 0);
+}
+
+//------------------------------------------------------------------------------
+
+DelphesFactory::~DelphesFactory()
+{
+  if(fObjArrays) delete fObjArrays;
+
+  map< const TClass*, ExRootTreeBranch* >::iterator itBranches;
+  for(itBranches = fBranches.begin(); itBranches != fBranches.end(); ++itBranches)
+  {
+    delete (itBranches->second);
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void DelphesFactory::Clear()
+{
+  set<TObject *>::iterator itPool;
+  for(itPool = fPool.begin(); itPool != fPool.end(); ++itPool)
+  {
+    (*itPool)->Clear();
+  }
+
+  TProcessID::SetObjectCount(0);
+
+  map< const TClass*, ExRootTreeBranch* >::iterator itBranches;
+  for(itBranches = fBranches.begin(); itBranches != fBranches.end(); ++itBranches)
+  {
+    itBranches->second->Clear();
+  }
+}
+
+//------------------------------------------------------------------------------
+
+TObjArray *DelphesFactory::NewPermanentArray()
+{
+  TObjArray *array = static_cast<TObjArray *>(fObjArrays->NewEntry());
+  fPool.insert(array);
+  return array;
+}
+
+//------------------------------------------------------------------------------
+
+Candidate *DelphesFactory::NewCandidate()
+{
+  Candidate *object = New<Candidate>();
+  object->SetFactory(this);
+  TProcessID::AssignID(object);
+  return object;
+}
+
+//------------------------------------------------------------------------------
+
+TObject *DelphesFactory::New(TClass *cl)
+{
+  TObject *object = 0;
+  ExRootTreeBranch *branch = 0;
+  map<const TClass *, ExRootTreeBranch *>::iterator it = fBranches.find(cl);
+
+  if(it != fBranches.end())
+  {
+    branch = it->second;
+  }
+  else
+  {
+    branch = new ExRootTreeBranch(cl->GetName(), cl, 0);
+    fBranches.insert(make_pair(cl, branch));
+  }
+
+  object = branch->NewEntry();
+  object->Clear();
+  return object;
+}
+
+//------------------------------------------------------------------------------
+
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesFactory.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesFactory.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesFactory.h	(revision 5)
@@ -0,0 +1,58 @@
+#ifndef DelphesFactory_h
+#define DelphesFactory_h
+
+/** \class DelphesFactory
+ *
+ *  Class handling creation of Candidate,
+ *  TObjArray and all other objects.
+ *
+ *  $Date: 2008-06-04 13:57:25 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "TNamed.h"
+
+#include <map>
+#include <set>
+
+class TObjArray;
+class Candidate;
+
+class ExRootTreeBranch;
+
+class DelphesFactory: public TNamed
+{
+public:
+  
+  DelphesFactory(const char *name = "ObjectFactory");
+  ~DelphesFactory();
+
+  void Clear();
+ 
+  TObjArray *NewPermanentArray();
+
+  TObjArray *NewArray() { return New<TObjArray>(); }
+
+  Candidate *NewCandidate();
+
+  TObject *New(TClass *cl);
+
+  template<typename T>
+  T *New() { return static_cast<T *>(New(T::Class())); }
+
+private:
+
+  ExRootTreeBranch *fObjArrays; //!
+
+  std::map< const TClass*, ExRootTreeBranch* > fBranches; //!
+  std::set< TObject* > fPool; //!
+  
+  ClassDef(DelphesFactory, 1)
+};
+
+#endif /* DelphesFactory */
+
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesFormula.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesFormula.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesFormula.cc	(revision 5)
@@ -0,0 +1,85 @@
+
+#include "classes/DelphesFormula.h"
+
+#include "TString.h"
+
+#include <stdexcept>
+#include <string>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+DelphesFormula::DelphesFormula() :
+  TFormula()
+{
+}
+
+//------------------------------------------------------------------------------
+
+DelphesFormula::DelphesFormula(const char *name, const char *expression) :
+  TFormula()
+{
+}
+
+//------------------------------------------------------------------------------
+
+DelphesFormula::~DelphesFormula()
+{
+}
+
+//------------------------------------------------------------------------------
+
+Int_t DelphesFormula::Compile(const char *expression)
+{
+  string buffer;
+  const char *it;
+  for(it = expression; *it; ++it)
+  {
+    if(*it == ' ' || *it == '\t' || *it == '\r' || *it == '\n' || *it == '\\' ) continue;
+    buffer.push_back(*it);
+  }
+  if(TFormula::Compile(buffer.c_str()) != 0)
+  {
+    throw runtime_error("Invalid formula.");
+  }
+  return 0;
+}
+
+//------------------------------------------------------------------------------
+
+Double_t DelphesFormula::Eval(Double_t pt, Double_t eta, Double_t phi, Double_t energy)
+{
+   Double_t x[4] = {pt, eta, phi, energy};
+   return EvalPar(x);
+}
+
+//------------------------------------------------------------------------------
+
+Int_t DelphesFormula::DefinedVariable(TString &chaine, Int_t &action)
+{
+  action = kVariable;
+  if(chaine == "pt")
+  {
+    if(fNdim < 1) fNdim = 1;
+    return 0;
+  }
+  else if(chaine == "eta")
+  {
+    if(fNdim < 2) fNdim = 2;
+    return 1;
+  }
+  else if(chaine == "phi")
+  {
+    if(fNdim < 3) fNdim = 3;
+    return 2;
+  }
+  else if(chaine == "energy")
+  {
+    if(fNdim < 4) fNdim = 4;
+    return 3;
+  }
+  return -1;
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesFormula.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesFormula.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesFormula.h	(revision 5)
@@ -0,0 +1,24 @@
+#ifndef DelphesFormula_h
+#define DelphesFormula_h
+
+#include "TFormula.h"
+
+class DelphesFormula: public TFormula
+{
+public:
+
+  DelphesFormula();
+
+  DelphesFormula(const char *name, const char *expression);
+
+  ~DelphesFormula();
+
+  Int_t Compile(const char *expression);
+
+  Double_t Eval(Double_t pt, Double_t eta = 0, Double_t phi = 0, Double_t energy = 0);
+
+  Int_t DefinedVariable(TString &variable, Int_t &action);
+};
+
+#endif /* DelphesFormula_h */
+
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesHepMCReader.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesHepMCReader.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesHepMCReader.cc	(revision 5)
@@ -0,0 +1,441 @@
+
+/** \class DelphesHepMCReader
+ *
+ *  Reads HepMC file
+ *
+ *
+ *  $Date: 2013-05-07 15:27:32 +0200 (Tue, 07 May 2013) $
+ *  $Revision: 1108 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesHepMCReader.h"
+
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+#include <map>
+#include <vector>
+
+#include <stdio.h>
+
+#include "TObjArray.h"
+#include "TStopwatch.h"
+#include "TDatabasePDG.h"
+#include "TParticlePDG.h"
+#include "TLorentzVector.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesStream.h"
+
+#include "ExRootAnalysis/ExRootTreeBranch.h"
+
+using namespace std;
+
+static const int kBufferSize  = 1024;
+
+//---------------------------------------------------------------------------
+
+DelphesHepMCReader::DelphesHepMCReader() :
+  fInputFile(0), fBuffer(0), fPDG(0),
+  fVertexCounter(-1), fInCounter(-1), fOutCounter(-1),
+  fParticleCounter(0)
+{
+  fBuffer = new char[kBufferSize];
+
+  fPDG = TDatabasePDG::Instance();
+}
+
+//---------------------------------------------------------------------------
+
+DelphesHepMCReader::~DelphesHepMCReader()
+{
+  if(fBuffer) delete[] fBuffer;
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesHepMCReader::SetInputFile(FILE *inputFile)
+{
+  fInputFile = inputFile;
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesHepMCReader::Clear()
+{
+  fStateSize = 0;
+  fState.clear();
+  fWeightSize = 0;
+  fWeight.clear();
+  fMomentumCoefficient = 1.0;
+  fPositionCoefficient = 1.0;
+  fVertexCounter = -1;
+  fInCounter = -1;
+  fOutCounter = -1;
+  fMotherMap.clear();
+  fDaughterMap.clear();
+  fParticleCounter = 0;
+}
+
+//---------------------------------------------------------------------------
+
+bool DelphesHepMCReader::EventReady()
+{
+  return (fVertexCounter == 0) && (fInCounter == 0) && (fOutCounter == 0);
+}
+
+//---------------------------------------------------------------------------
+
+bool DelphesHepMCReader::ReadBlock(DelphesFactory *factory,
+  TObjArray *allParticleOutputArray,
+  TObjArray *stableParticleOutputArray,
+  TObjArray *partonOutputArray)
+{
+  map< int, pair< int, int > >::iterator itMotherMap;
+  map< int, pair< int, int > >::iterator itDaughterMap;
+  char key, momentumUnit[4], positionUnit[3];
+  int i, rc, state;
+  double weight;
+
+  if(!fgets(fBuffer, kBufferSize, fInputFile)) return kFALSE;
+
+  DelphesStream bufferStream(fBuffer + 1);
+
+  key = fBuffer[0];
+
+  if(key == 'E')
+  {
+    Clear();
+
+    rc = bufferStream.ReadInt(fEventNumber)
+      && bufferStream.ReadInt(fMPI)
+      && bufferStream.ReadDbl(fScale)
+      && bufferStream.ReadDbl(fAlphaQCD)
+      && bufferStream.ReadDbl(fAlphaQED)
+      && bufferStream.ReadInt(fProcessID)
+      && bufferStream.ReadInt(fSignalCode)
+      && bufferStream.ReadInt(fVertexCounter)
+      && bufferStream.ReadInt(fBeamCode[0])
+      && bufferStream.ReadInt(fBeamCode[1])
+      && bufferStream.ReadInt(fStateSize);
+
+    if(!rc)
+    {
+      cerr << "** ERROR: " << "invalid event format" << endl;
+      return kFALSE;
+    }
+
+    for(i = 0; i < fStateSize; ++i)
+    {
+      rc = rc && bufferStream.ReadInt(state);
+      fState.push_back(state);
+    }
+
+    rc = rc && bufferStream.ReadInt(fWeightSize);
+
+    if(!rc)
+    {
+      cerr << "** ERROR: " << "invalid event format" << endl;
+      return kFALSE;
+    }
+
+    for(i = 0; i < fWeightSize; ++i)
+    {
+      rc = rc && bufferStream.ReadDbl(weight);
+      fWeight.push_back(weight);
+    }
+
+    if(!rc)
+    {
+      cerr << "** ERROR: " << "invalid event format" << endl;
+      return kFALSE;
+    }
+  }
+  else if(key == 'U')
+  {
+    rc = sscanf(fBuffer + 1, "%3s %2s", momentumUnit, positionUnit);
+
+    if(rc != 2)
+    {
+      cerr << "** ERROR: " << "invalid units format" << endl;
+      return kFALSE;
+    }
+
+    if(strncmp(momentumUnit, "GEV", 3) == 0)
+    {
+      fMomentumCoefficient = 1.0;
+    }
+    else if(strncmp(momentumUnit, "MEV", 3) == 0)
+    {
+      fMomentumCoefficient = 0.001;
+    }
+    
+    if(strncmp(positionUnit, "MM", 3) == 0)
+    {
+      fPositionCoefficient = 1.0;
+    }
+    else if(strncmp(positionUnit, "CM", 3) == 0)
+    {
+      fPositionCoefficient = 10.0;
+    }
+  }
+  else if(key == 'F')
+  {
+    rc = bufferStream.ReadInt(fID1)
+      && bufferStream.ReadInt(fID2)
+      && bufferStream.ReadDbl(fX1)
+      && bufferStream.ReadDbl(fX2)
+      && bufferStream.ReadDbl(fScalePDF)
+      && bufferStream.ReadDbl(fPDF1)
+      && bufferStream.ReadDbl(fPDF2);
+
+    if(!rc)
+    {
+      cerr << "** ERROR: " << "invalid PDF format" << endl;
+      return kFALSE;
+    }
+  }
+  else if(key == 'V' && fVertexCounter > 0)
+  {
+    rc = bufferStream.ReadInt(fOutVertexCode)
+      && bufferStream.ReadInt(fVertexID)
+      && bufferStream.ReadDbl(fX)
+      && bufferStream.ReadDbl(fY)
+      && bufferStream.ReadDbl(fZ)
+      && bufferStream.ReadDbl(fT)
+      && bufferStream.ReadInt(fInCounter)
+      && bufferStream.ReadInt(fOutCounter);
+
+    if(!rc)
+    {
+      cerr << "** ERROR: " << "invalid vertex format" << endl;
+      return kFALSE;
+    }
+    --fVertexCounter;
+  }
+  else if(key == 'P' && fOutCounter > 0)
+  {
+    rc = bufferStream.ReadInt(fParticleCode)
+      && bufferStream.ReadInt(fPID)
+      && bufferStream.ReadDbl(fPx)
+      && bufferStream.ReadDbl(fPy)
+      && bufferStream.ReadDbl(fPz)
+      && bufferStream.ReadDbl(fE)
+      && bufferStream.ReadDbl(fMass)
+      && bufferStream.ReadInt(fStatus)
+      && bufferStream.ReadDbl(fTheta)
+      && bufferStream.ReadDbl(fPhi)
+      && bufferStream.ReadInt(fInVertexCode);
+
+    if(!rc)
+    {
+      cerr << "** ERROR: " << "invalid particle format" << endl;
+      return kFALSE;
+    }
+
+    if(fInVertexCode < 0)
+    {
+      itMotherMap = fMotherMap.find(fInVertexCode);
+      if(itMotherMap == fMotherMap.end())
+      {
+        fMotherMap[fInVertexCode] = make_pair(fParticleCounter, -1);
+      }
+      else
+      {
+        itMotherMap->second.second = fParticleCounter;
+      }
+    }
+
+    if(fInCounter <= 0)
+    {
+      itDaughterMap = fDaughterMap.find(fOutVertexCode);
+      if(itDaughterMap == fDaughterMap.end())
+      {
+        fDaughterMap[fOutVertexCode] = make_pair(fParticleCounter, fParticleCounter);
+      }
+      else
+      {
+        itDaughterMap->second.second = fParticleCounter;
+      }
+    }
+
+    AnalyzeParticle(factory, allParticleOutputArray,
+      stableParticleOutputArray, partonOutputArray);
+
+    if(fInCounter > 0)
+    {
+      --fInCounter;
+    }
+    else
+    {
+      --fOutCounter;
+    }
+
+    ++fParticleCounter;
+  }
+
+  if(EventReady())
+  {
+    FinalizeParticles(allParticleOutputArray);
+  }
+
+  return kTRUE;
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesHepMCReader::AnalyzeEvent(ExRootTreeBranch *branch, long long eventNumber,
+  TStopwatch *readStopWatch, TStopwatch *procStopWatch)
+{
+  HepMCEvent *element;
+
+  element = static_cast<HepMCEvent *>(branch->NewEntry());
+  element->Number = fEventNumber;
+
+  element->ProcessID = fProcessID;
+  element->MPI = fMPI;
+  element->Weight = fWeight.size() > 0 ? fWeight[0] : 1.0;
+  element->Scale = fScale;
+  element->AlphaQED = fAlphaQED;
+  element->AlphaQCD = fAlphaQCD;
+
+  element->ID1 = fID1;
+  element->ID2 = fID2;
+  element->X1 = fX1;
+  element->X2 = fX2;
+  element->ScalePDF = fScalePDF;
+  element->PDF1 = fPDF1;
+  element->PDF2 = fPDF2;
+
+  element->ReadTime = readStopWatch->RealTime();
+  element->ProcTime = procStopWatch->RealTime();
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesHepMCReader::AnalyzeParticle(DelphesFactory *factory,
+  TObjArray *allParticleOutputArray,
+  TObjArray *stableParticleOutputArray,
+  TObjArray *partonOutputArray)
+{
+  Candidate *candidate;
+  TParticlePDG *pdgParticle;
+  int pdgCode;
+
+  candidate = factory->NewCandidate();
+
+  candidate->PID = fPID;
+  pdgCode = TMath::Abs(candidate->PID);
+
+  candidate->Status = fStatus;
+
+  pdgParticle = fPDG->GetParticle(fPID);
+  candidate->Charge = pdgParticle ? int(pdgParticle->Charge()/3.0) : -999;
+  candidate->Mass = pdgParticle ? pdgParticle->Mass() : -999.9;
+
+  candidate->Momentum.SetPxPyPzE(fPx, fPy, fPz, fE);
+  if(fMomentumCoefficient != 1.0)
+  {
+    candidate->Momentum *= fMomentumCoefficient;
+  }
+
+  candidate->M2 = 1;
+  candidate->D2 = 1;
+  if(fInCounter > 0)
+  {
+    candidate->M1 = 1;
+    candidate->Position.SetXYZT(0.0, 0.0, 0.0, 0.0);
+  }
+  else
+  {
+    candidate->M1 = fOutVertexCode;
+    candidate->Position.SetXYZT(fX, fY, fZ, fT);
+    if(fPositionCoefficient != 1.0)
+    {
+      candidate->Position *= fPositionCoefficient;
+    }
+  }
+  if(fInVertexCode < 0)
+  {
+    candidate->D1 = fInVertexCode;
+  }
+  else
+  {
+    candidate->D1 = 1;
+  }
+
+  allParticleOutputArray->Add(candidate);
+
+  if(!pdgParticle) return;
+
+  if(fStatus == 1 && pdgParticle->Stable())
+  {
+    stableParticleOutputArray->Add(candidate);
+  }
+  else if(pdgCode <= 5 || pdgCode == 21 || pdgCode == 15)
+  {
+    partonOutputArray->Add(candidate);
+  }
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesHepMCReader::FinalizeParticles(TObjArray *allParticleOutputArray)
+{
+  Candidate *candidate;
+  map< int, pair< int, int > >::iterator itMotherMap;
+  map< int, pair< int, int > >::iterator itDaughterMap;
+  int i;
+
+  for(i = 0; i < allParticleOutputArray->GetEntriesFast(); ++i)
+  {
+    candidate = static_cast<Candidate *>(allParticleOutputArray->At(i));
+
+    if(candidate->M1 > 0)
+    {
+      candidate->M1 = -1;
+      candidate->M2 = -1;
+    }
+    else
+    {
+      itMotherMap = fMotherMap.find(candidate->M1);
+      if(itMotherMap == fMotherMap.end())
+      {
+        candidate->M1 = -1;
+        candidate->M2 = -1;
+      }
+      else
+      {
+        candidate->M1 = itMotherMap->second.first;
+        candidate->M2 = itMotherMap->second.second;
+      }
+    }
+    if(candidate->D1 > 0)
+    {
+      candidate->D1 = -1;
+      candidate->D2 = -1;
+    }
+    else
+    {
+      itDaughterMap = fDaughterMap.find(candidate->D1);
+      if(itDaughterMap == fDaughterMap.end())
+      {
+        candidate->D1 = -1;
+        candidate->D2 = -1;
+      }
+      else
+      {
+        candidate->D1 = itDaughterMap->second.first;
+        candidate->D2 = itDaughterMap->second.second;
+      }
+    }
+  }
+}
+
+//---------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesHepMCReader.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesHepMCReader.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesHepMCReader.h	(revision 5)
@@ -0,0 +1,91 @@
+#ifndef DelphesHepMCReader_h
+#define DelphesHepMCReader_h
+
+/** \class DelphesHepMCReader
+ *
+ *  Reads HepMC file
+ *
+ *
+ *  $Date: 2013-05-07 15:27:32 +0200 (Tue, 07 May 2013) $
+ *  $Revision: 1108 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include <map>
+#include <vector>
+
+#include <stdio.h>
+
+class TObjArray;
+class TStopwatch;
+class TDatabasePDG;
+class ExRootTreeBranch;
+class DelphesFactory;
+
+class DelphesHepMCReader
+{
+public:
+
+  DelphesHepMCReader();
+  ~DelphesHepMCReader();
+
+  void SetInputFile(FILE *inputFile);
+
+  void Clear();
+  bool EventReady();
+
+  bool ReadBlock(DelphesFactory *factory,
+    TObjArray *allParticleOutputArray,
+    TObjArray *stableParticleOutputArray,
+    TObjArray *partonOutputArray);
+
+  void AnalyzeEvent(ExRootTreeBranch *branch, long long eventNumber,
+    TStopwatch *readStopWatch, TStopwatch *procStopWatch);
+
+private:
+
+  void AnalyzeParticle(DelphesFactory *factory,
+    TObjArray *allParticleOutputArray,
+    TObjArray *stableParticleOutputArray,
+    TObjArray *partonOutputArray);
+
+  void FinalizeParticles(TObjArray *allParticleOutputArray);
+
+  FILE *fInputFile;
+
+  char *fBuffer;
+
+  TDatabasePDG *fPDG;
+
+  int fEventNumber, fMPI, fProcessID, fSignalCode, fVertexCounter, fBeamCode[2];
+  double fScale, fAlphaQCD, fAlphaQED;
+
+  double fMomentumCoefficient, fPositionCoefficient;
+
+  int fStateSize;
+  std::vector< int > fState;
+
+  int fWeightSize;
+  std::vector< double > fWeight;
+
+  int fID1, fID2;
+  double fX1, fX2, fScalePDF, fPDF1, fPDF2;
+
+  int fOutVertexCode, fVertexID, fInCounter, fOutCounter;
+  double fX, fY, fZ, fT;
+
+  int fParticleCode, fPID, fStatus, fInVertexCode;
+  double fPx, fPy, fPz, fE, fMass, fTheta, fPhi;
+
+  int fParticleCounter;
+
+  std::map< int, std::pair < int, int > > fMotherMap;
+  std::map< int, std::pair < int, int > > fDaughterMap;
+};
+
+#endif // DelphesHepMCReader_h
+
+
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesLHEFReader.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesLHEFReader.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesLHEFReader.cc	(revision 5)
@@ -0,0 +1,208 @@
+
+/** \class DelphesLHEFReader
+ *
+ *  Reads LHEF file
+ *
+ *
+ *  $Date: 2013-03-10 00:26:28 +0100 (Sun, 10 Mar 2013) $
+ *  $Revision: 1052 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesLHEFReader.h"
+
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+#include <stdio.h>
+
+#include "TObjArray.h"
+#include "TStopwatch.h"
+#include "TDatabasePDG.h"
+#include "TParticlePDG.h"
+#include "TLorentzVector.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesStream.h"
+
+#include "ExRootAnalysis/ExRootTreeBranch.h"
+
+using namespace std;
+
+static const int kBufferSize  = 1024;
+
+//---------------------------------------------------------------------------
+
+DelphesLHEFReader::DelphesLHEFReader() :
+  fInputFile(0), fBuffer(0), fPDG(0),
+  fEventCounter(-1), fParticleCounter(-1)
+{
+  fBuffer = new char[kBufferSize];
+
+  fPDG = TDatabasePDG::Instance();
+}
+
+//---------------------------------------------------------------------------
+
+DelphesLHEFReader::~DelphesLHEFReader()
+{
+  if(fBuffer) delete[] fBuffer;
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesLHEFReader::SetInputFile(FILE *inputFile)
+{
+  fInputFile = inputFile;
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesLHEFReader::Clear()
+{
+  fEventCounter = -1;
+  fParticleCounter = -1;
+}
+
+//---------------------------------------------------------------------------
+
+bool DelphesLHEFReader::EventReady()
+{
+  return (fEventCounter == 0) && (fParticleCounter == 0);
+}
+
+//---------------------------------------------------------------------------
+
+bool DelphesLHEFReader::ReadBlock(DelphesFactory *factory,
+  TObjArray *allParticleOutputArray,
+  TObjArray *stableParticleOutputArray,
+  TObjArray *partonOutputArray)
+{
+  int rc;
+
+  if(!fgets(fBuffer, kBufferSize, fInputFile)) return kFALSE;
+
+  DelphesStream bufferStream(fBuffer);
+
+  if(strstr(fBuffer, "<event"))
+  {
+    Clear();
+    fEventCounter = 1;
+  }
+  else if(fEventCounter > 0)
+  {
+    rc = bufferStream.ReadInt(fParticleCounter)
+      && bufferStream.ReadInt(fProcessID)
+      && bufferStream.ReadDbl(fWeight)
+      && bufferStream.ReadDbl(fScalePDF)
+      && bufferStream.ReadDbl(fAlphaQED)
+      && bufferStream.ReadDbl(fAlphaQCD);
+
+    if(!rc)
+    {
+      cerr << "** ERROR: " << "invalid event format" << endl;
+      return kFALSE;
+    }
+
+    --fEventCounter;
+  }
+  else if(fParticleCounter > 0)
+  {
+    rc = bufferStream.ReadInt(fPID)
+      && bufferStream.ReadInt(fStatus)
+      && bufferStream.ReadInt(fM1)
+      && bufferStream.ReadInt(fM2)
+      && bufferStream.ReadInt(fC1)
+      && bufferStream.ReadInt(fC2)
+      && bufferStream.ReadDbl(fPx)
+      && bufferStream.ReadDbl(fPy)
+      && bufferStream.ReadDbl(fPz)
+      && bufferStream.ReadDbl(fE)
+      && bufferStream.ReadDbl(fMass);
+
+    if(!rc)
+    {
+      cerr << "** ERROR: " << "invalid particle format" << endl;
+      return kFALSE;
+    }
+
+    AnalyzeParticle(factory, allParticleOutputArray,
+      stableParticleOutputArray, partonOutputArray);
+
+    --fParticleCounter;
+  }
+
+  return kTRUE;
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesLHEFReader::AnalyzeEvent(ExRootTreeBranch *branch, long long eventNumber,
+  TStopwatch *readStopWatch, TStopwatch *procStopWatch)
+{
+  LHEFEvent *element;
+
+  element = static_cast<LHEFEvent *>(branch->NewEntry());
+  element->Number = eventNumber;
+
+  element->ProcessID = fProcessID;
+  element->Weight = fWeight;
+  element->ScalePDF = fScalePDF;
+  element->AlphaQED = fAlphaQED;
+  element->AlphaQCD = fAlphaQCD;
+
+  element->ReadTime = readStopWatch->RealTime();
+  element->ProcTime = procStopWatch->RealTime();
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesLHEFReader::AnalyzeParticle(DelphesFactory *factory,
+  TObjArray *allParticleOutputArray,
+  TObjArray *stableParticleOutputArray,
+  TObjArray *partonOutputArray)
+{
+  Candidate *candidate;
+  TParticlePDG *pdgParticle;
+  int pdgCode;
+
+  candidate = factory->NewCandidate();
+
+  candidate->PID = fPID;
+  pdgCode = TMath::Abs(candidate->PID);
+
+  candidate->Status = fStatus;
+
+  pdgParticle = fPDG->GetParticle(fPID);
+  candidate->Charge = pdgParticle ? int(pdgParticle->Charge()/3.0) : -999;
+  candidate->Mass = pdgParticle ? pdgParticle->Mass() : -999.9;
+
+  candidate->Momentum.SetPxPyPzE(fPx, fPy, fPz, fE);
+  candidate->Position.SetXYZT(0.0, 0.0, 0.0, 0.0);
+
+  candidate->M1 = fM1 - 1;
+  candidate->M2 = fM2 - 1;
+
+  candidate->D1 = -1;
+  candidate->D2 = -1;
+
+  allParticleOutputArray->Add(candidate);
+
+  if(!pdgParticle) return;
+
+  if(fStatus == 1 && pdgParticle->Stable())
+  {
+    stableParticleOutputArray->Add(candidate);
+  }
+  else if(pdgCode <= 5 || pdgCode == 21 || pdgCode == 15)
+  {
+    partonOutputArray->Add(candidate);
+  }
+}
+
+//---------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesLHEFReader.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesLHEFReader.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesLHEFReader.h	(revision 5)
@@ -0,0 +1,69 @@
+#ifndef DelphesLHEFReader_h
+#define DelphesLHEFReader_h
+
+/** \class DelphesLHEFReader
+ *
+ *  Reads LHEF file
+ *
+ *
+ *  $Date: 2013-03-10 00:26:28 +0100 (Sun, 10 Mar 2013) $
+ *  $Revision: 1052 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include <stdio.h>
+
+class TObjArray;
+class TStopwatch;
+class TDatabasePDG;
+class ExRootTreeBranch;
+class DelphesFactory;
+
+class DelphesLHEFReader
+{
+public:
+
+  DelphesLHEFReader();
+  ~DelphesLHEFReader();
+
+  void SetInputFile(FILE *inputFile);
+
+  void Clear();
+  bool EventReady();
+
+  bool ReadBlock(DelphesFactory *factory,
+    TObjArray *allParticleOutputArray,
+    TObjArray *stableParticleOutputArray,
+    TObjArray *partonOutputArray);
+
+  void AnalyzeEvent(ExRootTreeBranch *branch, long long eventNumber,
+    TStopwatch *readStopWatch, TStopwatch *procStopWatch);
+
+private:
+
+  void AnalyzeParticle(DelphesFactory *factory,
+    TObjArray *allParticleOutputArray,
+    TObjArray *stableParticleOutputArray,
+    TObjArray *partonOutputArray);
+
+  FILE *fInputFile;
+
+  char *fBuffer;
+
+  TDatabasePDG *fPDG;
+
+  int fEventCounter;
+
+  int fParticleCounter, fProcessID;
+  double fWeight, fScalePDF, fAlphaQCD, fAlphaQED;
+
+  int fPID, fStatus, fM1, fM2, fC1, fC2;
+  double fPx, fPy, fPz, fE, fMass;
+};
+
+#endif // DelphesLHEFReader_h
+
+
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesModule.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesModule.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesModule.cc	(revision 5)
@@ -0,0 +1,146 @@
+
+/** \class DelphesModule
+ *
+ *  Base class for all Delphes modules
+ *
+ *  $Date: 2008-06-04 13:57:25 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+#include "classes/DelphesFactory.h"
+
+#include "ExRootAnalysis/ExRootTreeReader.h"
+#include "ExRootAnalysis/ExRootTreeBranch.h"
+#include "ExRootAnalysis/ExRootTreeWriter.h"
+#include "ExRootAnalysis/ExRootResult.h"
+
+#include "TROOT.h"
+#include "TClass.h"
+#include "TFolder.h"
+#include "TObjArray.h"
+
+#include <iostream>
+#include <stdexcept>
+#include <sstream>
+
+using namespace std;
+
+DelphesModule::DelphesModule() :
+  fTreeWriter(0), fFactory(0), fPlots(0),
+  fPlotFolder(0), fExportFolder(0)
+{
+}
+
+//------------------------------------------------------------------------------
+
+DelphesModule::~DelphesModule()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void DelphesModule::Init()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void DelphesModule::Process()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void DelphesModule::Finish()
+{
+}
+
+//------------------------------------------------------------------------------
+
+TObjArray *DelphesModule::ImportArray(const char *name)
+{
+  stringstream message;
+  TObjArray *object;
+
+  object = static_cast<TObjArray *>(GetObject(Form("Export/%s", name), TObjArray::Class()));
+  if(!object)
+  {
+    message << "can't access input list '" << name;
+    message << "' in module '" << GetName() << "'";
+    throw runtime_error(message.str());
+  }
+
+  return object;
+}
+
+//------------------------------------------------------------------------------
+
+TObjArray *DelphesModule::ExportArray(const char *name)
+{
+  TObjArray *array;
+  if(!fExportFolder)
+  {
+    fExportFolder = NewFolder("Export");
+  }
+
+  array = GetFactory()->NewPermanentArray();
+
+  array->SetName(name);
+  fExportFolder->Add(array);
+
+  return array;
+}
+
+//------------------------------------------------------------------------------
+
+ExRootTreeBranch *DelphesModule::NewBranch(const char *name, TClass *cl)
+{
+  stringstream message;
+  if(!fTreeWriter)
+  {
+    fTreeWriter = static_cast<ExRootTreeWriter *>(GetObject("TreeWriter", ExRootTreeWriter::Class()));
+    if(!fTreeWriter)
+    {
+      message << "can't access access tree writer";
+      throw runtime_error(message.str());
+    }
+  }
+  return fTreeWriter->NewBranch(name, cl);
+}
+
+//------------------------------------------------------------------------------
+
+ExRootResult *DelphesModule::GetPlots()
+{
+  if(!fPlots)
+  {
+    fPlots = new ExRootResult();
+    fPlots->SetFolder(GetFolder());
+  }
+  return fPlots;
+}
+
+//------------------------------------------------------------------------------
+
+DelphesFactory *DelphesModule::GetFactory()
+{
+  stringstream message;
+  if(!fFactory)
+  {
+    fFactory = static_cast<DelphesFactory *>(GetObject("ObjectFactory", DelphesFactory::Class()));
+    if(!fFactory)
+    {
+      message << "can't access access object factory";
+      throw runtime_error(message.str());
+    }
+  }
+  return fFactory;
+}
+
+
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesModule.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesModule.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesModule.h	(revision 5)
@@ -0,0 +1,63 @@
+#ifndef DelphesModule_h
+#define DelphesModule_h
+
+/** \class DelphesModule
+ *
+ *  Base class for all Delphes modules
+ *
+ *  $Date: 2008-06-04 13:57:25 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "ExRootAnalysis/ExRootTask.h"
+
+class TClass;
+class TObject;
+class TFolder;
+class TClonesArray;
+
+class ExRootResult;
+class ExRootTreeBranch;
+class ExRootTreeWriter;
+
+class DelphesFactory;
+
+class DelphesModule: public ExRootTask 
+{
+public:
+
+  DelphesModule();
+  ~DelphesModule();
+
+  virtual void Init();
+  virtual void Process();
+  virtual void Finish();
+
+  TObjArray *ImportArray(const char *name);
+  TObjArray *ExportArray(const char *name);
+
+  ExRootTreeBranch *NewBranch(const char *name, TClass *cl);
+
+  ExRootResult *GetPlots();
+  DelphesFactory *GetFactory();
+
+protected:
+
+  ExRootTreeWriter *fTreeWriter;
+  DelphesFactory *fFactory;
+
+private:
+
+  ExRootResult *fPlots;
+
+  TFolder *fPlotFolder, *fExportFolder;
+
+  ClassDef(DelphesModule, 1)
+};
+
+#endif /* DelphesModule_h */
+
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesPileUpReader.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesPileUpReader.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesPileUpReader.cc	(revision 5)
@@ -0,0 +1,139 @@
+
+/** \class DelphesPileUpReader
+ *
+ *  Reads pile-up binary file
+ *
+ *
+ *  $Date: 2013-03-08 09:25:30 +0100 (Fri, 08 Mar 2013) $
+ *  $Revision: 1046 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesPileUpReader.h"
+
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+#include <stdio.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+using namespace std;
+
+static const int kIndexSize = 10000000;
+static const int kBufferSize = 1000000;
+static const int kRecordSize = 9;
+
+//------------------------------------------------------------------------------
+
+DelphesPileUpReader::DelphesPileUpReader(const char *fileName) :
+  fEntries(0), fEntrySize(0), fCounter(0),
+  fPileUpFile(0), fIndex(0), fBuffer(0),
+  fInputXDR(0), fIndexXDR(0), fBufferXDR(0)
+{
+  stringstream message;
+
+  fIndex = new char[kIndexSize*8];
+  fBuffer = new char[kBufferSize*kRecordSize*4];
+  fInputXDR = new XDR;
+  fIndexXDR = new XDR;
+  fBufferXDR = new XDR;
+  xdrmem_create(fIndexXDR, fIndex, kIndexSize*8, XDR_DECODE);
+  xdrmem_create(fBufferXDR, fBuffer, kBufferSize*kRecordSize*4, XDR_DECODE);
+
+  fPileUpFile = fopen(fileName, "r");
+
+  if(fPileUpFile == NULL)
+  {
+    message << "can't open pile-up file " << fileName;
+    throw runtime_error(message.str());
+  }
+
+  xdrstdio_create(fInputXDR, fPileUpFile, XDR_DECODE);
+
+  // read number of events
+  fseek(fPileUpFile, -8, SEEK_END);
+  xdr_hyper(fInputXDR, &fEntries);
+
+  if(fEntries >= kIndexSize)
+  {
+    message << "too many events in pile-up file " << fileName;
+    throw runtime_error(message.str());
+  }
+
+  // read index of events
+  fseek(fPileUpFile, -8 - 8*fEntries, SEEK_END);
+  xdr_opaque(fInputXDR, fIndex, fEntries*8);
+}
+
+//------------------------------------------------------------------------------
+
+DelphesPileUpReader::~DelphesPileUpReader()
+{
+  xdr_destroy(fInputXDR);
+  if(fPileUpFile) fclose(fPileUpFile);
+  xdr_destroy(fBufferXDR);
+  xdr_destroy(fIndexXDR);
+  if(fBufferXDR) delete fBufferXDR;
+  if(fIndexXDR) delete fIndexXDR;
+  if(fInputXDR) delete fInputXDR;
+  if(fBuffer) delete[] fBuffer;
+  if(fIndex) delete[] fIndex;
+}
+
+//------------------------------------------------------------------------------
+
+bool DelphesPileUpReader::ReadParticle(int &pid,
+  float &x, float &y, float &z, float &t,
+  float &px, float &py, float &pz, float &e)
+{
+  if(fCounter >= fEntrySize) return false;
+
+  xdr_int(fBufferXDR, &pid);
+  xdr_float(fBufferXDR, &x);
+  xdr_float(fBufferXDR, &y);
+  xdr_float(fBufferXDR, &z);
+  xdr_float(fBufferXDR, &t);
+  xdr_float(fBufferXDR, &px);
+  xdr_float(fBufferXDR, &py);
+  xdr_float(fBufferXDR, &pz);
+  xdr_float(fBufferXDR, &e);
+
+  ++fCounter;
+
+  return true;
+}
+
+//------------------------------------------------------------------------------
+
+bool DelphesPileUpReader::ReadEntry(quad_t entry)
+{
+  quad_t offset;
+
+  if(entry >= fEntries) return false;
+
+  // read event position
+  xdr_setpos(fIndexXDR, 8*entry);
+  xdr_hyper(fIndexXDR, &offset);
+
+  // read event
+  fseek(fPileUpFile, offset, SEEK_SET);
+  xdr_int(fInputXDR, &fEntrySize);
+
+  if(fEntrySize >= kBufferSize)
+  {
+    throw runtime_error("too many particles in pile-up event");
+  }
+
+  xdr_opaque(fInputXDR, fBuffer, fEntrySize*kRecordSize*4);
+  xdr_setpos(fBufferXDR, 0);
+  fCounter = 0;
+
+  return true;
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesPileUpReader.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesPileUpReader.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesPileUpReader.h	(revision 5)
@@ -0,0 +1,55 @@
+#ifndef DelphesPileUpReader_h
+#define DelphesPileUpReader_h
+
+/** \class DelphesPileUpReader
+ *
+ *  Reads pile-up binary file
+ *
+ *
+ *  $Date: 2013-03-08 09:25:30 +0100 (Fri, 08 Mar 2013) $
+ *  $Revision: 1046 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include <stdio.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+class DelphesPileUpReader
+{
+public:
+
+  DelphesPileUpReader(const char *fileName);
+
+  ~DelphesPileUpReader();
+
+  bool ReadParticle(int &pid,
+    float &x, float &y, float &z, float &t,
+    float &px, float &py, float &pz, float &e);
+
+  bool ReadEntry(quad_t entry);
+
+  quad_t GetEntries() const { return fEntries; }
+
+private:
+
+  quad_t fEntries;
+
+  int fEntrySize;
+  int fCounter;
+
+  FILE *fPileUpFile;
+  char *fIndex;
+  char *fBuffer;
+
+  XDR *fInputXDR;
+  XDR *fIndexXDR;
+  XDR *fBufferXDR;
+};
+
+#endif // DelphesPileUpReader_h
+
+
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesPileUpWriter.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesPileUpWriter.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesPileUpWriter.cc	(revision 5)
@@ -0,0 +1,127 @@
+
+/** \class DelphesPileUpWriter
+ *
+ *  Writes pile-up binary file
+ *
+ *
+ *  $Date: 2013-03-10 01:53:09 +0100 (Sun, 10 Mar 2013) $
+ *  $Revision: 1054 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesPileUpWriter.h"
+
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+#include <stdio.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+using namespace std;
+
+static const int kIndexSize = 10000000;
+static const int kBufferSize = 1000000;
+static const int kRecordSize = 9;
+
+//------------------------------------------------------------------------------
+
+DelphesPileUpWriter::DelphesPileUpWriter(const char *fileName) :
+  fEntries(0), fEntrySize(0), fOffset(0),
+  fPileUpFile(0), fIndex(0), fBuffer(0),
+  fOutputXDR(0), fIndexXDR(0), fBufferXDR(0)
+{
+  stringstream message;
+
+  fIndex = new char[kIndexSize*8];
+  fBuffer = new char[kBufferSize*kRecordSize*4];
+  fOutputXDR = new XDR;
+  fIndexXDR = new XDR;
+  fBufferXDR = new XDR;
+  xdrmem_create(fIndexXDR, fIndex, kIndexSize*8, XDR_ENCODE);
+  xdrmem_create(fBufferXDR, fBuffer, kBufferSize*kRecordSize*4, XDR_ENCODE);
+
+  fPileUpFile = fopen(fileName, "w+");
+
+  if(fPileUpFile == NULL)
+  {
+    message << "can't open pile-up file " << fileName;
+    throw runtime_error(message.str());
+  }
+
+  xdrstdio_create(fOutputXDR, fPileUpFile, XDR_ENCODE);
+}
+
+//------------------------------------------------------------------------------
+
+DelphesPileUpWriter::~DelphesPileUpWriter()
+{
+  xdr_destroy(fOutputXDR);
+  if(fPileUpFile) fclose(fPileUpFile);
+  xdr_destroy(fBufferXDR);
+  xdr_destroy(fIndexXDR);
+  if(fBufferXDR) delete fBufferXDR;
+  if(fIndexXDR) delete fIndexXDR;
+  if(fOutputXDR) delete fOutputXDR;
+  if(fBuffer) delete[] fBuffer;
+  if(fIndex) delete[] fIndex;
+}
+
+//------------------------------------------------------------------------------
+
+void DelphesPileUpWriter::WriteParticle(int pid,
+  float x, float y, float z, float t,
+  float px, float py, float pz, float e)
+{
+  if(fEntrySize >= kBufferSize)
+  {
+    throw runtime_error("too many particles in pile-up event");
+  }
+
+  xdr_int(fBufferXDR, &pid);
+  xdr_float(fBufferXDR, &x);
+  xdr_float(fBufferXDR, &y);
+  xdr_float(fBufferXDR, &z);
+  xdr_float(fBufferXDR, &t);
+  xdr_float(fBufferXDR, &px);
+  xdr_float(fBufferXDR, &py);
+  xdr_float(fBufferXDR, &pz);
+  xdr_float(fBufferXDR, &e);
+
+  ++fEntrySize;
+}
+
+//------------------------------------------------------------------------------
+
+void DelphesPileUpWriter::WriteEntry()
+{
+  if(fEntries >= kIndexSize)
+  {
+    throw runtime_error("too many pile-up events");
+  }
+
+  xdr_int(fOutputXDR, &fEntrySize);
+  xdr_opaque(fOutputXDR, fBuffer, fEntrySize*kRecordSize*4);
+
+  xdr_hyper(fIndexXDR, &fOffset);
+  fOffset += fEntrySize*kRecordSize*4 + 4;
+
+  xdr_setpos(fBufferXDR, 0);
+  fEntrySize = 0;
+        
+  ++fEntries;
+}
+
+//------------------------------------------------------------------------------
+
+void DelphesPileUpWriter::WriteIndex()
+{
+  xdr_opaque(fOutputXDR, fIndex, fEntries*8);
+  xdr_hyper(fOutputXDR, &fEntries);
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesPileUpWriter.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesPileUpWriter.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesPileUpWriter.h	(revision 5)
@@ -0,0 +1,54 @@
+#ifndef DelphesPileUpWriter_h
+#define DelphesPileUpWriter_h
+
+/** \class DelphesPileUpWriter
+ *
+ *  Writes pile-up binary file
+ *
+ *
+ *  $Date: 2013-03-10 01:53:09 +0100 (Sun, 10 Mar 2013) $
+ *  $Revision: 1054 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include <stdio.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+class DelphesPileUpWriter
+{
+public:
+
+  DelphesPileUpWriter(const char *fileName);
+
+  ~DelphesPileUpWriter();
+
+  void WriteParticle(int pid,
+    float x, float y, float z, float t,
+    float px, float py, float pz, float e);
+
+  void WriteEntry();
+
+  void WriteIndex();
+
+private:
+
+  quad_t fEntries;
+  int fEntrySize;
+  quad_t fOffset;
+
+  FILE *fPileUpFile;
+  char *fIndex;
+  char *fBuffer;
+
+  XDR *fOutputXDR;
+  XDR *fIndexXDR;
+  XDR *fBufferXDR;
+};
+
+#endif // DelphesPileUpWriter_h
+
+
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesSTDHEPReader.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesSTDHEPReader.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesSTDHEPReader.cc	(revision 5)
@@ -0,0 +1,471 @@
+
+/** \class DelphesSTDHEPReader
+ *
+ *  Reads STDHEP file
+ *
+ *
+ *  $Date: 2013-05-21 22:03:37 +0200 (Tue, 21 May 2013) $
+ *  $Revision: 1120 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesSTDHEPReader.h"
+
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+#include <stdio.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+#include "TObjArray.h"
+#include "TStopwatch.h"
+#include "TDatabasePDG.h"
+#include "TParticlePDG.h"
+#include "TLorentzVector.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+
+#include "ExRootAnalysis/ExRootTreeBranch.h"
+
+using namespace std;
+
+static const int kBufferSize  = 1000000;
+
+//---------------------------------------------------------------------------
+
+DelphesSTDHEPReader::DelphesSTDHEPReader() :
+  fInputFile(0), fInputXDR(0), fBuffer(0), fPDG(0), fBlockType(-1)
+{
+  fInputXDR = new XDR;
+  fBuffer = new char[kBufferSize*96 + 24];
+
+  fPDG = TDatabasePDG::Instance();
+}
+
+//---------------------------------------------------------------------------
+
+DelphesSTDHEPReader::~DelphesSTDHEPReader()
+{
+  if(fBuffer) delete fBuffer;
+  if(fInputXDR) delete fInputXDR;
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesSTDHEPReader::SetInputFile(FILE *inputFile)
+{
+  fInputFile = inputFile;
+  xdrstdio_create(fInputXDR, inputFile, XDR_DECODE);
+  ReadFileHeader();
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesSTDHEPReader::Clear()
+{
+  fBlockType = -1;
+}
+
+//---------------------------------------------------------------------------
+
+bool DelphesSTDHEPReader::EventReady()
+{
+  return (fBlockType == MCFIO_STDHEP) || (fBlockType == MCFIO_STDHEP4);
+}
+
+//---------------------------------------------------------------------------
+
+bool DelphesSTDHEPReader::ReadBlock(DelphesFactory *factory,
+  TObjArray *allParticleOutputArray,
+  TObjArray *stableParticleOutputArray,
+  TObjArray *partonOutputArray)
+{
+  if(feof(fInputFile)) return kFALSE;
+
+  xdr_int(fInputXDR, &fBlockType);
+
+  SkipBytes(4);
+
+  xdr_string(fInputXDR, &fBuffer, 100);
+
+  if(fBlockType == EVENTTABLE)
+  {
+    ReadEventTable();
+  }
+  else if(fBlockType == EVENTHEADER)
+  {
+    ReadSTDHEPHeader();
+  }
+  else if(fBlockType == MCFIO_STDHEPBEG ||
+          fBlockType == MCFIO_STDHEPEND)
+  {
+    ReadSTDCM1();
+  }
+  else if(fBlockType == MCFIO_STDHEP)
+  {
+    ReadSTDHEP();
+    AnalyzeParticles(factory, allParticleOutputArray,
+      stableParticleOutputArray, partonOutputArray);
+  }
+  else if(fBlockType == MCFIO_STDHEP4)
+  {
+    ReadSTDHEP4();
+    AnalyzeParticles(factory, allParticleOutputArray,
+      stableParticleOutputArray, partonOutputArray);
+  }
+  else
+  {
+    throw runtime_error("Unsupported block type.");
+  }
+
+  return kTRUE;
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesSTDHEPReader::SkipBytes(u_int size)
+{
+  u_int rndup;
+  rndup = size % 4;
+  if(rndup > 0)
+  {
+    rndup = 4 - rndup;
+  }
+
+  fseek(fInputFile, size + rndup, SEEK_CUR);
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesSTDHEPReader::SkipArray(u_int elsize)
+{
+  u_int size;
+  xdr_u_int(fInputXDR, &size);
+  SkipBytes(size*elsize);
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesSTDHEPReader::ReadFileHeader()
+{
+  u_int i;
+  enum STDHEPVersion {UNKNOWN, V1, V2, V21} version;
+
+  xdr_int(fInputXDR, &fBlockType);
+  if (fBlockType != FILEHEADER)
+  {
+    throw runtime_error("Header block not found. File is probably corrupted.");
+  }
+
+  SkipBytes(4);
+
+  // version
+  xdr_string(fInputXDR, &fBuffer, 100);
+  if(fBuffer[0] == '\0' || fBuffer[1] == '\0') version = UNKNOWN;
+  else if(fBuffer[0] == '1') version = V1;
+  else if(strncmp(fBuffer, "2.01", 4) == 0) version = V21;
+  else if(fBuffer[0] == '2') version = V2;
+  else version = UNKNOWN;
+
+  if (version == UNKNOWN)
+  {
+    throw runtime_error("Unknown file format version.");
+  }
+
+  SkipArray(1);
+  SkipArray(1);
+  SkipArray(1);
+
+  if (version == V21)
+  {
+    SkipArray(1);
+  }
+
+  // Expected number of events
+  SkipBytes(4);
+
+  // Number of events
+  xdr_u_int(fInputXDR, &fEntries);
+
+  SkipBytes(8);
+
+  // Number of blocks
+  u_int nBlocks = 0;
+  xdr_u_int(fInputXDR, &nBlocks);
+
+  // Number of NTuples
+  u_int nNTuples = 0;
+  if(version != V1)
+  {
+    xdr_u_int(fInputXDR, &nNTuples);
+  }
+
+  if(nNTuples != 0)
+  {
+    throw runtime_error("Files containing n-tuples are not supported.");
+  }
+
+  // Processing blocks extraction
+  if(nBlocks != 0)
+  {
+    SkipArray(4);
+
+    for(i = 0; i < nBlocks; i++)
+    {
+      SkipArray(1);
+    }
+  }
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesSTDHEPReader::ReadEventTable()
+{
+  SkipBytes(8);
+
+  SkipArray(4);
+  SkipArray(4);
+  SkipArray(4);
+  SkipArray(4);
+  SkipArray(4);
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesSTDHEPReader::ReadSTDHEPHeader()
+{
+  SkipBytes(20);
+
+  u_int dimBlocks = 0;
+  xdr_u_int(fInputXDR, &dimBlocks);
+
+  u_int dimNTuples = 0;
+  if(strncmp(fBuffer, "2.00", 4) == 0)
+  {
+    SkipBytes(4);
+    xdr_u_int(fInputXDR, &dimNTuples);
+  }
+
+  // Processing blocks extraction
+  if(dimBlocks > 0)
+  {
+    SkipArray(4);
+    SkipArray(4);
+  }
+
+  // Processing blocks extraction
+  if(dimNTuples > 0 && strncmp(fBuffer, "2.00", 4) == 0)
+  {
+    SkipArray(4);
+    SkipArray(4);
+  }
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesSTDHEPReader::ReadSTDCM1()
+{
+  // skip 5*4 + 2*8 = 36 bytes
+  SkipBytes(36);
+
+  if((strncmp(fBuffer, "1.", 2) == 0) || (strncmp(fBuffer, "2.", 2) == 0) ||
+     (strncmp(fBuffer, "3.", 2) == 0) || (strncmp(fBuffer, "4.", 2) == 0) ||
+     (strncmp(fBuffer, "5.00", 4) == 0))
+  {
+    return;
+  }
+
+  SkipArray(1);
+  SkipArray(1);
+
+  if(strncmp(fBuffer, "5.01", 4) == 0)
+  {
+    return;
+  }
+
+  SkipBytes(4);
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesSTDHEPReader::ReadSTDHEP()
+{
+  u_int idhepSize, isthepSize, jmohepSize, jdahepSize, phepSize, vhepSize;
+
+  // Extracting the event number
+  xdr_int(fInputXDR, &fEventNumber);
+
+  // Extracting the number of particles
+  xdr_int(fInputXDR, &fEventSize);
+
+  if(fEventSize >= kBufferSize)
+  {
+    throw runtime_error("too many particles in event");
+  }
+
+  // 4*n + 4*n + 8*n + 8*n + 40*n + 32*n +
+  // 4 + 4 + 4 + 4 + 4 + 4 = 96*n + 24
+
+  xdr_opaque(fInputXDR, fBuffer, 96*fEventSize + 24);
+
+  idhepSize = ntohl(*(u_int*)(fBuffer));
+  isthepSize = ntohl(*(u_int*)(fBuffer + 4*1 + 4*1*fEventSize));
+  jmohepSize = ntohl(*(u_int*)(fBuffer + 4*2 + 4*2*fEventSize));
+  jdahepSize = ntohl(*(u_int*)(fBuffer + 4*3 + 4*4*fEventSize));
+  phepSize = ntohl(*(u_int*)(fBuffer + 4*4 + 4*6*fEventSize));
+  vhepSize = ntohl(*(u_int*)(fBuffer + 4*5 + 4*16*fEventSize));
+
+  if(fEventSize < 0 ||
+     fEventSize != (int)idhepSize      || fEventSize != (int)isthepSize     ||
+     (2*fEventSize) != (int)jmohepSize || (2*fEventSize) != (int)jdahepSize ||
+     (5*fEventSize) != (int)phepSize   || (4*fEventSize) != (int)vhepSize)
+  {
+    throw runtime_error("Inconsistent size of arrays. File is probably corrupted.");
+  }
+
+  fWeight = 1.0;
+  fAlphaQED = 0.0;
+  fAlphaQCD = 0.0;
+  fScaleSize = 0;
+  memset(fScale, 0, 10*sizeof(double));
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesSTDHEPReader::ReadSTDHEP4()
+{
+  u_int number;
+
+  ReadSTDHEP();
+
+  // Extracting the event weight
+  xdr_double(fInputXDR, &fWeight);
+
+  // Extracting alpha QED
+  xdr_double(fInputXDR, &fAlphaQED);
+
+  // Extracting alpha QCD
+  xdr_double(fInputXDR, &fAlphaQCD);
+
+  // Extracting the event scale
+  xdr_u_int(fInputXDR, &fScaleSize);
+  for(number = 0; number < fScaleSize; ++number)
+  {
+    xdr_double(fInputXDR, &fScale[number]);
+  }
+
+  SkipArray(8);
+  SkipArray(4);
+
+  SkipBytes(4);
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesSTDHEPReader::AnalyzeEvent(ExRootTreeBranch *branch, long long eventNumber,
+  TStopwatch *readStopWatch, TStopwatch *procStopWatch)
+{
+  LHEFEvent *element;
+
+  element = static_cast<LHEFEvent *>(branch->NewEntry());
+
+  element->Number = fEventNumber;
+
+  element->ProcessID = 0;
+
+  element->Weight = fWeight;
+  element->ScalePDF = fScale[0];
+  element->AlphaQED = fAlphaQED;
+  element->AlphaQCD = fAlphaQCD;
+
+  element->ReadTime = readStopWatch->RealTime();
+  element->ProcTime = procStopWatch->RealTime();
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesSTDHEPReader::AnalyzeParticles(DelphesFactory *factory,
+  TObjArray *allParticleOutputArray,
+  TObjArray *stableParticleOutputArray,
+  TObjArray *partonOutputArray)
+{
+  Candidate *candidate;
+  TParticlePDG *pdgParticle;
+  int pdgCode;
+
+  int number;
+  int pid, status, m1, m2, d1, d2;
+  double px, py, pz, e, m;
+  double x, y, z, t;
+
+  XDR bufferXDR[6];
+  xdrmem_create(&bufferXDR[0], fBuffer + 4*1, 4*fEventSize, XDR_DECODE);
+  xdrmem_create(&bufferXDR[1], fBuffer + 4*2 + 4*1*fEventSize, 4*fEventSize, XDR_DECODE);
+  xdrmem_create(&bufferXDR[2], fBuffer + 4*3 + 4*2*fEventSize, 8*fEventSize, XDR_DECODE);
+  xdrmem_create(&bufferXDR[3], fBuffer + 4*4 + 4*4*fEventSize, 8*fEventSize, XDR_DECODE);
+  xdrmem_create(&bufferXDR[4], fBuffer + 4*5 + 4*6*fEventSize, 40*fEventSize, XDR_DECODE);
+  xdrmem_create(&bufferXDR[5], fBuffer + 4*6 + 4*16*fEventSize, 32*fEventSize, XDR_DECODE);
+
+  for(number = 0; number < fEventSize; ++number)
+  {
+    xdr_int(&bufferXDR[0], &status);
+    xdr_int(&bufferXDR[1], &pid);
+    xdr_int(&bufferXDR[2], &m1);
+    xdr_int(&bufferXDR[2], &m2);
+    xdr_int(&bufferXDR[3], &d1);
+    xdr_int(&bufferXDR[3], &d2);
+
+    xdr_double(&bufferXDR[4], &px);
+    xdr_double(&bufferXDR[4], &py);
+    xdr_double(&bufferXDR[4], &pz);
+    xdr_double(&bufferXDR[4], &e);
+    xdr_double(&bufferXDR[4], &m);
+
+    xdr_double(&bufferXDR[5], &x);
+    xdr_double(&bufferXDR[5], &y);
+    xdr_double(&bufferXDR[5], &z);
+    xdr_double(&bufferXDR[5], &t);
+
+    candidate = factory->NewCandidate();
+
+    candidate->PID = pid;
+    pdgCode = TMath::Abs(candidate->PID);
+
+    candidate->Status = status;
+
+    candidate->M1 = m1 - 1;
+    candidate->M2 = m2 - 1;
+
+    candidate->D1 = d1 - 1;
+    candidate->D2 = d2 - 1;
+
+    pdgParticle = fPDG->GetParticle(pid);
+    candidate->Charge = pdgParticle ? int(pdgParticle->Charge()/3.0) : -999;
+    candidate->Mass = pdgParticle ? pdgParticle->Mass() : -999.9;
+
+    candidate->Momentum.SetPxPyPzE(px, py, pz, e);
+
+    candidate->Position.SetXYZT(x, y, z, t);
+
+    allParticleOutputArray->Add(candidate);
+
+    if(!pdgParticle) continue;
+
+    if(status == 1 && pdgParticle->Stable())
+    {
+      stableParticleOutputArray->Add(candidate);
+    }
+    else if(pdgCode <= 5 || pdgCode == 21 || pdgCode == 15)
+    {
+      partonOutputArray->Add(candidate);
+    }
+  }
+}
+
+//---------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesSTDHEPReader.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesSTDHEPReader.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesSTDHEPReader.h	(revision 5)
@@ -0,0 +1,93 @@
+#ifndef DelphesSTDHEPReader_h
+#define DelphesSTDHEPReader_h
+
+/** \class DelphesSTDHEPReader
+ *
+ *  Reads STDHEP file
+ *
+ *
+ *  $Date: 2013-03-10 00:26:28 +0100 (Sun, 10 Mar 2013) $
+ *  $Revision: 1052 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include <stdio.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+class TObjArray;
+class TStopwatch;
+class TDatabasePDG;
+class ExRootTreeBranch;
+class DelphesFactory;
+
+class DelphesSTDHEPReader
+{
+public:
+  enum STDHEPBlock
+  {
+    GENERIC = 0,
+    FILEHEADER = 1,
+    EVENTTABLE = 2,
+    EVENTHEADER = 4,
+    MCFIO_STDHEP = 101,
+    MCFIO_STDHEPBEG = 106,
+    MCFIO_STDHEPEND = 107,
+    MCFIO_STDHEP4 = 201
+  };
+
+  DelphesSTDHEPReader();
+  ~DelphesSTDHEPReader();
+
+  void SetInputFile(FILE *inputFile);
+
+  void Clear();
+  bool EventReady();
+
+  bool ReadBlock(DelphesFactory *factory,
+    TObjArray *allParticleOutputArray,
+    TObjArray *stableParticleOutputArray,
+    TObjArray *partonOutputArray);
+
+  void AnalyzeEvent(ExRootTreeBranch *branch, long long eventNumber,
+    TStopwatch *readStopWatch, TStopwatch *procStopWatch);
+
+private:
+
+  void AnalyzeParticles(DelphesFactory *factory,
+    TObjArray *allParticleOutputArray,
+    TObjArray *stableParticleOutputArray,
+    TObjArray *partonOutputArray);
+
+  void SkipBytes(u_int size);
+  void SkipArray(u_int elsize);
+
+  void ReadFileHeader();
+  void ReadEventTable();
+  void ReadSTDHEPHeader();
+  void ReadSTDCM1();
+  void ReadSTDHEP();
+  void ReadSTDHEP4();
+
+  FILE *fInputFile;
+
+  XDR *fInputXDR;
+
+  char *fBuffer;
+
+  TDatabasePDG *fPDG;
+
+  u_int fEntries;
+  int fBlockType, fEventNumber, fEventSize;
+  double fWeight, fAlphaQCD, fAlphaQED;
+
+  u_int fScaleSize;
+  double fScale[10];
+};
+
+#endif // DelphesSTDHEPReader_h
+
+
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesStream.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesStream.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesStream.cc	(revision 5)
@@ -0,0 +1,95 @@
+
+/** \class DelphesStream
+ *
+ *  Provides an interface to manipulate c strings as if they were input streams
+ *
+ *
+ *  $Date: 2012-11-15 13:57:55 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesStream.h"
+
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <math.h>
+
+#include <iostream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+bool DelphesStream::fFirstLongMin = true;
+bool DelphesStream::fFirstLongMax = true;
+bool DelphesStream::fFirstHugePos = true;
+bool DelphesStream::fFirstHugeNeg = true;
+bool DelphesStream::fFirstZero = true;
+
+//------------------------------------------------------------------------------
+
+DelphesStream::DelphesStream(char *buffer) :
+  fBuffer(buffer)
+{
+}
+
+//------------------------------------------------------------------------------
+
+bool DelphesStream::ReadDbl(double &value)
+{
+  char *start = fBuffer;
+  errno = 0;
+  value = strtod(start, &fBuffer);
+  if(errno == ERANGE)
+  {
+    if(fFirstHugePos && value == HUGE_VAL)
+    {
+      fFirstHugePos = false; 
+      cout << "** WARNING: too large positive value, return " << value << endl;
+    }
+    else if(fFirstHugeNeg && value == -HUGE_VAL)
+    {
+      fFirstHugeNeg = false; 
+      cout << "** WARNING: too large negative value, return " << value << endl;
+    }
+    else if(fFirstZero)
+    {
+      fFirstZero = false; 
+      value = 0.0;
+      cout << "** WARNING: too small value, return " << value << endl;
+    }
+  }
+  return start != fBuffer;
+}
+
+//------------------------------------------------------------------------------
+
+bool DelphesStream::ReadInt(int &value)
+{
+  char *start = fBuffer;
+  errno = 0;
+  value = strtol(start, &fBuffer, 10);
+  if(errno == ERANGE)
+  {
+    if(fFirstLongMin && value == LONG_MIN)
+    {
+      fFirstLongMin = false; 
+      cout << "** WARNING: too large positive value, return " << value << endl;
+    }
+    else if(fFirstLongMax && value == LONG_MAX)
+    {
+      fFirstLongMax = false; 
+      cout << "** WARNING: too large negative value, return " << value << endl;
+    }
+  }
+  return start != fBuffer;
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/classes/DelphesStream.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/DelphesStream.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/DelphesStream.h	(revision 5)
@@ -0,0 +1,39 @@
+#ifndef DelphesStream_h
+#define DelphesStream_h
+
+/** \class DelphesStream
+ *
+ *  Provides an interface to manipulate c strings as if they were input streams
+ *
+ *
+ *  $Date: 2012-11-15 13:57:55 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+class DelphesStream
+{
+public:
+
+  DelphesStream(char *buffer);
+
+  bool ReadDbl(double &value);
+  bool ReadInt(int &value);
+
+private:
+
+  char *fBuffer;
+  
+  static bool fFirstLongMin;
+  static bool fFirstLongMax;
+  static bool fFirstHugePos;
+  static bool fFirstHugeNeg;
+  static bool fFirstZero;
+};
+
+#endif // DelphesStream_h
+
+
Index: trunk/Delphes/Delphes-3.0.9/classes/SortableObject.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/classes/SortableObject.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/classes/SortableObject.h	(revision 5)
@@ -0,0 +1,214 @@
+#ifndef SortableObject_h
+#define SortableObject_h
+
+/** \class SortableObject
+ *
+ *
+ *  $Date: 2008-06-04 13:57:26 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "TRef.h"
+#include "TObject.h"
+#include "TRefArray.h"
+
+#include "TMath.h"
+
+//---------------------------------------------------------------------------
+
+class CompBase
+{
+public:
+  virtual ~CompBase() { }
+  virtual Bool_t IsSortable(const TObject *obj) const { return kTRUE; }
+  virtual Int_t Compare(const TObject *obj1, const TObject *obj2) const = 0;
+};
+
+//---------------------------------------------------------------------------
+
+class SortableObject: public TObject
+{
+public:
+
+  Bool_t IsSortable() const { return GetCompare() ? GetCompare()->IsSortable(this) : kFALSE; }
+  Int_t Compare(const TObject *obj) const { return GetCompare()->Compare(this, obj); }
+
+  virtual const CompBase *GetCompare() const = 0;
+
+  ClassDef(SortableObject, 1)
+};
+
+//---------------------------------------------------------------------------
+// Standard Comparison Criteria: E, ET, PT, DeltaR
+//---------------------------------------------------------------------------
+
+template <typename T>
+class CompE: public CompBase
+{
+  CompE() {}
+public:
+  static CompE *Instance()
+  {
+    static CompE single;
+    return &single;
+  }
+
+  Int_t Compare(const TObject *obj1, const TObject *obj2) const
+  {
+    const T *t1 = static_cast<const T*>(obj1);
+    const T *t2 = static_cast<const T*>(obj2);
+    if(t1->E > t2->E)
+      return -1;
+    else if(t1->E < t2->E)
+      return 1;
+    else
+      return 0;
+  }
+};
+
+//---------------------------------------------------------------------------
+
+template <typename T>
+class CompPT: public CompBase
+{
+  CompPT() {}
+public:
+  static CompPT *Instance()
+  {
+    static CompPT single;
+    return &single;
+  }
+
+  Int_t Compare(const TObject *obj1, const TObject *obj2) const
+  {
+    const T *t1 = static_cast<const T*>(obj1);
+    const T *t2 = static_cast<const T*>(obj2);
+    if(t1->PT > t2->PT)
+      return -1;
+    else if(t1->PT < t2->PT)
+      return 1;
+    else
+      return 0;
+  }
+};
+
+//---------------------------------------------------------------------------
+
+template <typename T>
+class CompMomentumPt: public CompBase
+{
+  CompMomentumPt() {}
+public:
+  static CompMomentumPt *Instance()
+  {
+    static CompMomentumPt single;
+    return &single;
+  }
+
+  Int_t Compare(const TObject *obj1, const TObject *obj2) const
+  {
+    const T *t1 = static_cast<const T*>(obj1);
+    const T *t2 = static_cast<const T*>(obj2);
+    if(t1->Momentum.Pt() > t2->Momentum.Pt())
+      return -1;
+    else if(t1->Momentum.Pt() < t2->Momentum.Pt())
+      return 1;
+    else
+      return 0;
+  }
+};
+
+//---------------------------------------------------------------------------
+
+template <typename T>
+class CompET: public CompBase
+{
+  CompET() {}
+public:
+  static CompET *Instance()
+  {
+    static CompET single;
+    return &single;
+  }
+
+  Int_t Compare(const TObject *obj1, const TObject *obj2) const
+  {
+    const T *t1 = static_cast<const T*>(obj1);
+    const T *t2 = static_cast<const T*>(obj2);
+    if(t1->ET > t2->ET)
+      return -1;
+    else if(t1->ET < t2->ET)
+      return 1;
+    else
+      return 0;
+  }
+};
+
+//---------------------------------------------------------------------------
+
+template <typename T1, typename T2>
+class CompDeltaR: public CompBase
+{
+  CompDeltaR(const T2 *obj = 0) : fObj(obj) {}
+
+  Double_t DeltaPhi(Double_t phi1, Double_t phi2)
+  {
+    Double_t phi = TMath::Abs(phi1 - phi2);
+    return (phi <= TMath::Pi()) ? phi : (2.0*TMath::Pi()) - phi;
+  }
+
+  Double_t Sqr(Double_t x) { return x*x; }
+
+  Double_t SumSqr(Double_t a, Double_t b)
+  {
+    Double_t aAbs = TMath::Abs(a);
+    Double_t bAbs = TMath::Abs(b);
+    if(aAbs > bAbs) return aAbs * TMath::Sqrt(1.0 + Sqr(bAbs / aAbs));
+    else return (bAbs == 0) ? 0.0 : bAbs * TMath::Sqrt(1.0 + Sqr(aAbs / bAbs));
+  };
+
+  const T2 *fObj;
+
+public:
+    static CompDeltaR *Instance(const T2 *obj = 0)
+  {
+      static CompDeltaR single(obj);
+      return &single;
+  }
+
+  void SetObject(const T2 *obj) { fObj = obj; }
+
+  Int_t Compare(const TObject *obj1, const TObject *obj2) const
+  {
+    Double_t eta[3], phi[3], deltaR[2];
+    const T1 *t1 = static_cast<const T1*>(obj1);
+    const T1 *t2 = static_cast<const T1*>(obj2);
+
+    eta[0] = fObj->Eta;
+    phi[0] = fObj->Phi;
+
+    eta[1] = t1->Eta;
+    phi[1] = t1->Phi;
+
+    eta[2] = t2->Eta;
+    phi[2] = t2->Phi;
+
+    deltaR[0] = SumSqr(TMath::Abs(eta[0] - eta[1]), DeltaPhi(phi[0], phi[1]));
+    deltaR[1] = SumSqr(TMath::Abs(eta[0] - eta[2]), DeltaPhi(phi[0], phi[2]));
+
+    if(deltaR[0] < deltaR[1])
+      return -1;
+    else if(deltaR[0] > deltaR[1])
+      return 1;
+    else
+      return 0;
+  }
+};
+
+#endif // SortableObject_h
+
+
Index: trunk/Delphes/Delphes-3.0.9/configure
===================================================================
--- trunk/Delphes/Delphes-3.0.9/configure	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/configure	(revision 5)
@@ -0,0 +1,10 @@
+#! /bin/sh
+#
+# A (so) simple configure script.
+
+# test Makefile && make distclean
+tclsh ./doc/genMakefile.tcl > Makefile
+echo "Makefile ready"
+echo "To build Delphes type "
+echo "   make"
+
Index: trunk/Delphes/Delphes-3.0.9/converters/hepmc2pileup.cpp
===================================================================
--- trunk/Delphes/Delphes-3.0.9/converters/hepmc2pileup.cpp	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/converters/hepmc2pileup.cpp	(revision 5)
@@ -0,0 +1,176 @@
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+#include <signal.h>
+
+#include "TROOT.h"
+#include "TApplication.h"
+
+#include "TFile.h"
+#include "TObjArray.h"
+#include "TStopwatch.h"
+#include "TDatabasePDG.h"
+#include "TParticlePDG.h"
+#include "TLorentzVector.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesHepMCReader.h"
+#include "classes/DelphesPileUpWriter.h"
+
+#include "ExRootAnalysis/ExRootTreeWriter.h"
+#include "ExRootAnalysis/ExRootTreeBranch.h"
+#include "ExRootAnalysis/ExRootProgressBar.h"
+
+using namespace std;
+
+//---------------------------------------------------------------------------
+
+static bool interrupted = false;
+
+void SignalHandler(int sig)
+{
+  interrupted = true;
+}
+
+//---------------------------------------------------------------------------
+
+int main(int argc, char *argv[])
+{
+  char appName[] = "hepmc2pileup";
+  stringstream message;
+  FILE *inputFile = 0;
+  DelphesFactory *factory = 0;
+  TObjArray *stableParticleOutputArray = 0, *allParticleOutputArray = 0, *partonOutputArray = 0;
+  TIterator *itParticle = 0;
+  Candidate *candidate = 0;
+  DelphesPileUpWriter *writer = 0;
+  DelphesHepMCReader *reader = 0;
+  Int_t i;
+  Long64_t length, eventCounter;
+
+  if(argc < 2)
+  {
+    cout << " Usage: " << appName << " output_file" << " [input_file(s)]" << endl;
+    cout << " output_file - output binary pile-up file," << endl;
+    cout << " input_file(s) - input file(s) in HepMC format," << endl;
+    cout << " with no input_file, or when input_file is -, read standard input." << endl;
+    return 1;
+  }
+
+  signal(SIGINT, SignalHandler);
+
+  gROOT->SetBatch();
+
+  int appargc = 1;
+  char *appargv[] = {appName};
+  TApplication app(appName, &appargc, appargv);
+
+  try
+  {
+    writer = new DelphesPileUpWriter(argv[1]);
+
+    factory = new DelphesFactory("ObjectFactory");
+    allParticleOutputArray = factory->NewPermanentArray();
+    stableParticleOutputArray = factory->NewPermanentArray();
+    partonOutputArray = factory->NewPermanentArray();
+
+    itParticle = stableParticleOutputArray->MakeIterator();
+
+    reader = new DelphesHepMCReader;
+
+    i = 2;
+    do
+    {
+      if(interrupted) break;
+
+      if(i == argc || strncmp(argv[i], "-", 2) == 0)
+      {
+        cout << "** Reading standard input" << endl;
+        inputFile = stdin;
+        length = -1;
+      }
+      else
+      {
+        cout << "** Reading " << argv[i] << endl;
+        inputFile = fopen(argv[i], "r");
+
+        if(inputFile == NULL)
+        {
+          message << "can't open " << argv[i];
+          throw runtime_error(message.str());
+        }
+
+        fseek(inputFile, 0L, SEEK_END);
+        length = ftello(inputFile);
+        fseek(inputFile, 0L, SEEK_SET);
+
+        if(length <= 0)
+        {
+          fclose(inputFile);
+          ++i;
+          continue;
+        }
+      }
+
+      reader->SetInputFile(inputFile);
+
+      ExRootProgressBar progressBar(length);
+
+      // Loop over all objects
+      eventCounter = 0;
+      factory->Clear();
+      reader->Clear();
+      while(reader->ReadBlock(factory, allParticleOutputArray,
+        stableParticleOutputArray, partonOutputArray) && !interrupted)
+      {
+        if(reader->EventReady())
+        {
+          ++eventCounter;
+
+          itParticle->Reset();
+          while((candidate = static_cast<Candidate*>(itParticle->Next())))
+          {
+            const TLorentzVector &position = candidate->Position;
+            const TLorentzVector &momentum = candidate->Momentum;
+            writer->WriteParticle(candidate->PID,
+              position.X(), position.Y(), position.Z(), position.T(),
+              momentum.Px(), momentum.Py(), momentum.Pz(), momentum.E());
+          }
+
+          writer->WriteEntry();
+
+          factory->Clear();
+          reader->Clear();
+        }
+        progressBar.Update(ftello(inputFile), eventCounter);
+      }
+
+      fseek(inputFile, 0L, SEEK_END);
+      progressBar.Update(ftello(inputFile), eventCounter, kTRUE);
+      progressBar.Finish();
+
+      if(inputFile != stdin) fclose(inputFile);
+
+      ++i;
+    }
+    while(i < argc);
+
+    writer->WriteIndex();
+
+    cout << "** Exiting..." << endl;
+
+    delete reader;
+    delete factory;
+    delete writer;
+
+    return 0;
+  }
+  catch(runtime_error &e)
+  {
+    if(writer) delete writer;
+    cerr << "** ERROR: " << e.what() << endl;
+    return 1;
+  }
+}
Index: trunk/Delphes/Delphes-3.0.9/converters/lhco2root.cpp
===================================================================
--- trunk/Delphes/Delphes-3.0.9/converters/lhco2root.cpp	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/converters/lhco2root.cpp	(revision 5)
@@ -0,0 +1,459 @@
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+#include <stdlib.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include "TROOT.h"
+#include "TApplication.h"
+
+#include "TFile.h"
+#include "TObjArray.h"
+#include "TStopwatch.h"
+#include "TDatabasePDG.h"
+#include "TParticlePDG.h"
+#include "TLorentzVector.h"
+
+#include "modules/Delphes.h"
+#include "classes/DelphesStream.h"
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+
+#include "ExRootAnalysis/ExRootTreeWriter.h"
+#include "ExRootAnalysis/ExRootTreeBranch.h"
+#include "ExRootAnalysis/ExRootProgressBar.h"
+
+using namespace std;
+
+static const int kBufferSize  = 1024;
+
+/*
+LHC Olympics format discription from http://www.jthaler.net/olympicswiki/doku.php?id=lhc_olympics:data_file_format
+
+    * The first column of each row is just a counter that labels the object.
+    * The event begins with a row labelled "0"; this row contains the event number and the triggering information. The last row of the event is always the missing transverse momentum (MET).
+    * The second column of each row gives the type of object being listed [0, 1, 2, 3, 4, 6 = photon, electron, muon, hadronically-decaying tau, jet, missing transverse energy].
+    * The next three columns give the pseudorapidity, the azimuthal angle, and the transverse momentum of the object.
+    * The sixth column gives the invariant mass of the object.
+    * The seventh column gives the number of tracks associated with the object; in the case of a lepton, this number is multiplied by the charge of the lepton.
+    * The eighth column is 1 or 2 for a jet that has been "tagged" as containing a b-quark (actually a heavy flavor tag that sometimes indicates c-quarks), otherwise it is 0. For muons, the integer part of this number is the identity of the jet (see column 1) that is closest ot this muon in Delta R.
+    * The ninth column is the ratio of the hadronic versus electromagnetic energy deposited in the calorimeter cells associated with the object. For muons to the left of the decimal point is the summed pT in a R=0.4 cone (excluding the muon). To the right of the decimal point is etrat, which is a percentage between .00 and .99. It is the ratio of the transverse energy in a 3x3 grid surrounding the muon to the pT of the muon.
+*/
+
+//------------------------------------------------------------------------------
+
+class LHCOConverter
+{
+public:
+  LHCOConverter(TFile *outputFile);
+  ~LHCOConverter();
+
+  void Write();
+
+  Bool_t ReadLine(FILE *inputFile);
+
+private:
+
+  void AddMissingEvents();
+
+  void AnalyseEvent(ExRootTreeBranch *branch);
+
+  void AnalysePhoton(ExRootTreeBranch *branch);
+  void AnalyseElectron(ExRootTreeBranch *branch);
+  void AnalyseMuon(ExRootTreeBranch *branch);
+  void AnalyseTau(ExRootTreeBranch *branch);
+  void AnalyseJet(ExRootTreeBranch *branch);
+  void AnalyseMissingET(ExRootTreeBranch *branch);
+
+  enum {kIntParamSize = 2, kDblParamSize = 7};
+  Int_t fIntParam[kIntParamSize];
+  Double_t fDblParam[kDblParamSize];
+
+  Bool_t fIsReadyToFill;
+
+  Int_t fTriggerWord, fEventNumber;
+
+  char *fBuffer;
+
+  ExRootTreeWriter *fTreeWriter;
+
+  ExRootTreeBranch *fBranchEvent;
+  ExRootTreeBranch *fBranchTrack;
+  ExRootTreeBranch *fBranchTower;
+  ExRootTreeBranch *fBranchPhoton;
+  ExRootTreeBranch *fBranchElectron;
+  ExRootTreeBranch *fBranchMuon;
+  ExRootTreeBranch *fBranchJet;
+  ExRootTreeBranch *fBranchMissingET;
+
+};
+
+//------------------------------------------------------------------------------
+
+LHCOConverter::LHCOConverter(TFile *outputFile) :
+  fIsReadyToFill(kFALSE),
+  fTriggerWord(0), fEventNumber(1),
+  fBuffer(0), fTreeWriter(0)
+{
+  fBuffer = new char[kBufferSize];
+  fTreeWriter = new ExRootTreeWriter(outputFile, "Delphes");
+
+  // information about reconstructed event
+  fBranchEvent = fTreeWriter->NewBranch("Event", LHCOEvent::Class());
+  // reconstructed tracks
+  fBranchTrack = fTreeWriter->NewBranch("Track", Track::Class());
+  /// calorimeter towers
+  fBranchTower = fTreeWriter->NewBranch("Tower", Tower::Class());
+  // reconstructed photons
+  fBranchPhoton = fTreeWriter->NewBranch("Photon", Photon::Class());
+  // reconstructed electrons
+  fBranchElectron = fTreeWriter->NewBranch("Electron", Electron::Class());
+  // reconstructed muons
+  fBranchMuon = fTreeWriter->NewBranch("Muon", Muon::Class());
+  // reconstructed jets
+  fBranchJet = fTreeWriter->NewBranch("Jet", Jet::Class());
+  // missing transverse energy
+  fBranchMissingET = fTreeWriter->NewBranch("MissingET", MissingET::Class());
+}
+
+//------------------------------------------------------------------------------
+
+LHCOConverter::~LHCOConverter()
+{
+  if(fTreeWriter) delete fTreeWriter;
+  if(fBuffer) delete[] fBuffer;
+}
+
+//------------------------------------------------------------------------------
+
+Bool_t LHCOConverter::ReadLine(FILE *inputFile)
+{
+  int rc;
+
+  if(!fgets(fBuffer, kBufferSize, inputFile)) return kFALSE;
+
+  DelphesStream bufferStream(fBuffer);
+
+  rc = bufferStream.ReadInt(fIntParam[0]);
+
+  if(!rc)
+  {
+    return kTRUE;
+  }
+
+  if(fIntParam[0] == 0)
+  {
+    rc = bufferStream.ReadInt(fEventNumber)
+      && bufferStream.ReadInt(fTriggerWord);
+
+    if(!rc)
+    {
+      cerr << "** ERROR: " << "invalid event format" << endl;
+      return kFALSE;
+    }
+
+    if(fIsReadyToFill && fTreeWriter)
+    {
+      fTreeWriter->Fill();
+      fTreeWriter->Clear();
+    }
+
+    AnalyseEvent(fBranchEvent);
+    fIsReadyToFill = kTRUE;
+  }
+  else
+  {
+    rc = bufferStream.ReadInt(fIntParam[1])
+      && bufferStream.ReadDbl(fDblParam[0])
+      && bufferStream.ReadDbl(fDblParam[1])
+      && bufferStream.ReadDbl(fDblParam[2])
+      && bufferStream.ReadDbl(fDblParam[3])
+      && bufferStream.ReadDbl(fDblParam[4])
+      && bufferStream.ReadDbl(fDblParam[5])
+      && bufferStream.ReadDbl(fDblParam[6]);
+
+    if(!rc)
+    {
+      cerr << "** ERROR: " << "invalid object format" << endl;
+      return kFALSE;
+    }
+
+    switch(fIntParam[1])
+    {
+      case 0: AnalysePhoton(fBranchPhoton); break;
+      case 1: AnalyseElectron(fBranchElectron); break;
+      case 2: AnalyseMuon(fBranchMuon); break;
+      case 3: AnalyseTau(fBranchJet); break;
+      case 4: AnalyseJet(fBranchJet); break;
+      case 6: AnalyseMissingET(fBranchMissingET); break;
+    }
+  }
+
+  return kTRUE;
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOConverter::Write()
+{
+  if(fIsReadyToFill && fTreeWriter) fTreeWriter->Fill();
+  if(fTreeWriter) fTreeWriter->Write();
+  fIsReadyToFill = kFALSE;
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOConverter::AnalyseEvent(ExRootTreeBranch *branch)
+{
+  LHCOEvent *element;
+
+  element = static_cast<LHCOEvent*>(branch->NewEntry());
+
+  element->Number = fEventNumber;
+  element->Trigger = fTriggerWord;
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOConverter::AnalysePhoton(ExRootTreeBranch *branch)
+{
+  Photon *element;
+
+  element = static_cast<Photon*>(branch->NewEntry());
+
+  element->Eta = fDblParam[0];
+  element->Phi = fDblParam[1];
+  element->PT = fDblParam[2];
+  element->EhadOverEem = fDblParam[6];
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOConverter::AnalyseElectron(ExRootTreeBranch *branch)
+{
+  Electron *element;
+
+  element = static_cast<Electron*>(branch->NewEntry());
+
+  element->Eta = fDblParam[0];
+  element->Phi = fDblParam[1];
+  element->PT = fDblParam[2];
+
+  element->Charge = fDblParam[4] < 0.0 ? -1 : 1;
+/*
+  element->Ntrk = TMath::Abs(fDblParam[4]);
+*/
+  element->EhadOverEem = fDblParam[6];
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOConverter::AnalyseMuon(ExRootTreeBranch *branch)
+{
+  Muon *element;
+
+  element = static_cast<Muon*>(branch->NewEntry());
+
+  element->Eta = fDblParam[0];
+  element->Phi = fDblParam[1];
+  element->PT = fDblParam[2];
+
+  element->Charge = fDblParam[4] < 0.0 ? -1 : 1;
+/*
+  element->Ntrk = TMath::Abs(fDblParam[4]);
+
+  element->JetIndex = Int_t(fDblParam[5]);
+
+  element->PTiso = Int_t(fDblParam[6]);
+  element->ETiso = fDblParam[6] - element->PTiso;
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOConverter::AnalyseTau(ExRootTreeBranch *branch)
+{
+  Jet *element;
+
+  element = static_cast<Jet*>(branch->NewEntry());
+
+  element->Eta = fDblParam[0];
+  element->Phi = fDblParam[1];
+  element->PT = fDblParam[2];
+
+  element->Mass = fDblParam[3];
+
+  element->BTag = 0;
+  element->TauTag = 1;
+
+  element->Charge = fDblParam[4] < 0 ? -1 : 1;
+/*
+  element->Ntrk = TMath::Abs(fDblParam[4]);
+*/
+  element->EhadOverEem = fDblParam[6];
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOConverter::AnalyseJet(ExRootTreeBranch *branch)
+{
+  Jet *element;
+
+  element = static_cast<Jet*>(branch->NewEntry());
+
+  element->Eta = fDblParam[0];
+  element->Phi = fDblParam[1];
+  element->PT = fDblParam[2];
+
+  element->Mass = fDblParam[3];
+/*
+  element->Ntrk = TMath::Abs(Int_t(fDblParam[4]));
+*/
+  element->BTag = Int_t(fDblParam[5]);
+  element->TauTag = 0;
+
+  element->Charge = 0;
+
+  element->EhadOverEem = fDblParam[6];
+/*
+  element->Index = fIntParam[0];
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOConverter::AnalyseMissingET(ExRootTreeBranch *branch)
+{
+  MissingET *element;
+
+  element = static_cast<MissingET*>(branch->NewEntry());
+
+  element->Phi = fDblParam[1];
+  element->MET = fDblParam[2];
+}
+
+//---------------------------------------------------------------------------
+
+static bool interrupted = false;
+
+void SignalHandler(int sig)
+{
+  interrupted = true;
+}
+
+//---------------------------------------------------------------------------
+
+int main(int argc, char *argv[])
+{
+  char appName[] = "lhco2root";
+  stringstream message;
+  FILE *inputFile = 0;
+  TFile *outputFile = 0;
+  LHCOConverter *converter = 0;
+  Int_t i;
+  Long64_t length, eventCounter;
+
+  if(argc < 2)
+  {
+    cout << " Usage: " << appName << " output_file" << " [input_file(s)]" << endl;
+    cout << " output_file - output file in ROOT format," << endl;
+    cout << " input_file(s) - input file(s) in LHCO format," << endl;
+    cout << " with no input_file, or when input_file is -, read standard input." << endl;
+    return 1;
+  }
+
+  signal(SIGINT, SignalHandler);
+
+  gROOT->SetBatch();
+
+  int appargc = 1;
+  char *appargv[] = {appName};
+  TApplication app(appName, &appargc, appargv);
+
+  try
+  {
+    outputFile = TFile::Open(argv[1], "CREATE");
+
+    if(outputFile == NULL)
+    {
+      message << "can't open " << argv[1];
+      throw runtime_error(message.str());
+    }
+
+    converter = new LHCOConverter(outputFile);
+
+    i = 2;
+    do
+    {
+      if(interrupted) break;
+
+      if(i == argc || strcmp(argv[i], "-") == 0)
+      {
+        cout << "** Reading standard input" << endl;
+        inputFile = stdin;
+        length = -1;
+      }
+      else
+      {
+        cout << "** Reading " << argv[i] << endl;
+        inputFile = fopen(argv[i], "r");
+
+        if(inputFile == NULL)
+        {
+          message << "can't open " << argv[i];
+          throw runtime_error(message.str());
+        }
+
+        fseek(inputFile, 0L, SEEK_END);
+        length = ftello(inputFile);
+        fseek(inputFile, 0L, SEEK_SET);
+
+        if(length <= 0)
+        {
+          fclose(inputFile);
+          ++i;
+          continue;
+        }
+      }
+
+      eventCounter = 0;
+      ExRootProgressBar progressBar(length);
+
+      // Loop over all objects
+      while(converter->ReadLine(inputFile) && !interrupted)
+      {
+        ++eventCounter;
+
+        progressBar.Update(ftello(inputFile), eventCounter);
+      }
+      converter->Write();
+
+      fseek(inputFile, 0L, SEEK_END);
+      progressBar.Update(ftello(inputFile), eventCounter, kTRUE);
+      progressBar.Finish();
+
+      if(inputFile != stdin) fclose(inputFile);
+
+      ++i;
+    }
+    while(i < argc);
+
+    cout << "** Exiting..." << endl;
+
+    delete converter;
+    delete outputFile;
+
+    return 0;
+  }
+  catch(runtime_error &e)
+  {
+    if(converter) delete converter;
+    if(outputFile) delete outputFile;
+    cerr << "** ERROR: " << e.what() << endl;
+    return 1;
+  }
+}
+
+
Index: trunk/Delphes/Delphes-3.0.9/converters/pileup2root.cpp
===================================================================
--- trunk/Delphes/Delphes-3.0.9/converters/pileup2root.cpp	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/converters/pileup2root.cpp	(revision 5)
@@ -0,0 +1,187 @@
+
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+#include <stdlib.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+#include "TROOT.h"
+#include "TApplication.h"
+
+#include "TFile.h"
+#include "TObjArray.h"
+#include "TStopwatch.h"
+#include "TDatabasePDG.h"
+#include "TParticlePDG.h"
+#include "TLorentzVector.h"
+
+#include "classes/DelphesStream.h"
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesPileUpReader.h"
+
+#include "ExRootAnalysis/ExRootTreeWriter.h"
+#include "ExRootAnalysis/ExRootTreeBranch.h"
+#include "ExRootAnalysis/ExRootProgressBar.h"
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+void ProcessEvent(DelphesPileUpReader *reader, ExRootTreeBranch *branch)
+{
+  GenParticle *particle;
+  Int_t pid;
+  Float_t x, y, z, t;
+  Float_t px, py, pz, e;
+  TDatabasePDG *pdg = TDatabasePDG::Instance();
+  TParticlePDG *pdgParticle;
+  TLorentzVector momentum;
+  Double_t pt, signPz, cosTheta, eta, rapidity;
+
+  while(reader->ReadParticle(pid, x, y, z, t, px, py, pz, e))
+  {
+    particle = static_cast<GenParticle*>(branch->NewEntry());
+
+    particle->PID = pid;
+    particle->X = x;
+    particle->Y = y;
+    particle->Z = z;
+    particle->T = t;
+    particle->Px = px;
+    particle->Py = py;
+    particle->Pz = pz;
+    particle->E = e;
+
+    particle->Status = 1;
+    particle->IsPU = 1;
+
+    particle->M1 = -1;
+    particle->M2 = -1;
+
+    particle->D1 = -1;
+    particle->D2 = -1;
+
+    pdgParticle = pdg->GetParticle(pid);
+    particle->Charge = pdgParticle ? Int_t(pdgParticle->Charge()/3.0) : -999;
+
+    particle->Mass = pdgParticle ? pdgParticle->Mass() : -999.9;
+
+    momentum.SetPxPyPzE(px, py, pz, e);
+    pt = momentum.Pt();
+    cosTheta = TMath::Abs(momentum.CosTheta());
+    signPz = (momentum.Pz() >= 0.0) ? 1.0 : -1.0;
+    eta = (cosTheta == 1.0 ? signPz*999.9 : momentum.Eta());
+    rapidity = (cosTheta == 1.0 ? signPz*999.9 : momentum.Rapidity());
+
+    particle->Eta = eta;
+    particle->Phi = momentum.Phi();
+    particle->PT = pt;
+
+    particle->Rapidity = rapidity;
+  }
+}
+
+//---------------------------------------------------------------------------
+
+static bool interrupted = false;
+
+void SignalHandler(int sig)
+{
+  interrupted = true;
+}
+
+//---------------------------------------------------------------------------
+
+int main(int argc, char *argv[])
+{
+  char appName[] = "pileup2root";
+  stringstream message;
+  TFile *outputFile = 0;
+  ExRootTreeWriter *treeWriter = 0;
+  ExRootTreeBranch *branchParticle = 0;
+  DelphesPileUpReader *reader = 0;
+  Long64_t entry, allEntries;
+
+  if(argc != 3)
+  {
+    cout << " Usage: " << appName << " output_file" << " input_file" << endl;
+    cout << " output_file - output file in ROOT format," << endl;
+    cout << " input_file - input binary pile-up file." << endl;
+    return 1;
+  }
+
+  signal(SIGINT, SignalHandler);
+
+  gROOT->SetBatch();
+
+  int appargc = 1;
+  char *appargv[] = {appName};
+  TApplication app(appName, &appargc, appargv);
+
+  try
+  {
+    outputFile = TFile::Open(argv[1], "CREATE");
+
+    if(outputFile == NULL)
+    {
+      message << "can't open " << argv[1];
+      throw runtime_error(message.str());
+    }
+
+    cout << "** Reading " << argv[2] << endl;
+
+    reader = new DelphesPileUpReader(argv[2]);
+    allEntries = reader->GetEntries();
+
+    cout << "** Input file contains " << allEntries << " events" << endl;
+
+    if(allEntries > 0)
+    {
+      treeWriter = new ExRootTreeWriter(outputFile, "Delphes");
+      branchParticle = treeWriter->NewBranch("Particle", GenParticle::Class());
+
+      ExRootProgressBar progressBar(allEntries - 1);
+      // Loop over all events
+      for(entry = 0; entry < allEntries && !interrupted; ++entry)
+      {
+        if(!reader->ReadEntry(entry))
+        {
+          cerr << "** ERROR: cannot read event " << entry << endl;
+          break;
+        }
+
+        treeWriter->Clear();
+        ProcessEvent(reader, branchParticle);
+        treeWriter->Fill();
+
+        progressBar.Update(entry);
+      }
+      treeWriter->Write();
+
+      progressBar.Finish();
+
+      delete treeWriter;
+    }
+    delete reader;
+
+    cout << "** Exiting..." << endl;
+
+    return 0;
+  }
+  catch(runtime_error &e)
+  {
+    if(treeWriter) delete treeWriter;
+    if(reader) delete reader;
+    if(outputFile) delete outputFile;
+    cerr << "** ERROR: " << e.what() << endl;
+    return 1;
+  }
+}
+
+
Index: trunk/Delphes/Delphes-3.0.9/converters/root2lhco.cpp
===================================================================
--- trunk/Delphes/Delphes-3.0.9/converters/root2lhco.cpp	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/converters/root2lhco.cpp	(revision 5)
@@ -0,0 +1,503 @@
+#include <stdexcept>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+
+#include <stdlib.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include "TROOT.h"
+#include "TApplication.h"
+
+#include "TFile.h"
+#include "TClonesArray.h"
+
+#include "classes/DelphesClasses.h"
+
+#include "ExRootAnalysis/ExRootTreeReader.h"
+#include "ExRootAnalysis/ExRootProgressBar.h"
+
+using namespace std;
+
+/*
+LHC Olympics format discription from http://www.jthaler.net/olympicswiki/doku.php?id=lhc_olympics:data_file_format
+
+    * The first column of each row is just a counter that labels the object.
+    * The event begins with a row labelled "0"; this row contains the event number and the triggering information. The last row of the event is always the missing transverse momentum (MET).
+    * The second column of each row gives the type of object being listed [0, 1, 2, 3, 4, 6 = photon, electron, muon, hadronically-decaying tau, jet, missing transverse energy].
+    * The next three columns give the pseudorapidity, the azimuthal angle, and the transverse momentum of the object.
+    * The sixth column gives the invariant mass of the object.
+    * The seventh column gives the number of tracks associated with the object; in the case of a lepton, this number is multiplied by the charge of the lepton.
+    * The eighth column is 1 or 2 for a jet that has been "tagged" as containing a b-quark (actually a heavy flavor tag that sometimes indicates c-quarks), otherwise it is 0. For muons, the integer part of this number is the identity of the jet (see column 1) that is closest ot this muon in Delta R.
+    * The ninth column is the ratio of the hadronic versus electromagnetic energy deposited in the calorimeter cells associated with the object. For muons to the left of the decimal point is the summed pT in a R=0.4 cone (excluding the muon). To the right of the decimal point is etrat, which is a percentage between .00 and .99. It is the ratio of the transverse energy in a 3x3 grid surrounding the muon to the pT of the muon.
+*/
+
+class LHCOWriter
+{
+public:
+  LHCOWriter(ExRootTreeReader *treeReader, FILE *outputFile);
+  ~LHCOWriter();
+
+  void ProcessEvent();
+
+private:
+
+  void Reset();
+  void Write();
+
+  void AnalyseEvent();
+
+  void AnalysePhotons();
+  void AnalyseElectrons();
+  void AnalyseMuons();
+  void AnalyseTauJets();
+  void AnalyseJets();
+
+  void AnalyseMissingET();
+
+  enum {kIntParamSize = 2, kDblParamSize = 9};
+  Int_t fIntParam[kIntParamSize];
+  Double_t fDblParam[kDblParamSize];
+
+  Long64_t fTriggerWord, fEventNumber;
+
+  ExRootTreeReader *fTreeReader;
+  FILE *fOutputFile;
+
+  TClonesArray *fBranchEvent;
+
+  TClonesArray *fBranchTrack;
+  TClonesArray *fBranchTower;
+
+  TClonesArray *fBranchPhoton;
+  TClonesArray *fBranchElectron;
+  TClonesArray *fBranchMuon;
+  TClonesArray *fBranchJet;
+  TClonesArray *fBranchMissingET;
+
+  TIterator *fItTrack;
+  TIterator *fItTower;
+
+  TIterator *fItPhoton;
+  TIterator *fItElectron;
+  TIterator *fItMuon;
+  TIterator *fItJet;
+};
+
+//------------------------------------------------------------------------------
+
+LHCOWriter::LHCOWriter(ExRootTreeReader *treeReader, FILE *outputFile) :
+  fTriggerWord(0), fEventNumber(1), fTreeReader(0), fOutputFile(0)
+{
+  fTreeReader = treeReader;
+  fOutputFile = outputFile;
+
+  // information about reconstructed event
+  fBranchEvent = fTreeReader->UseBranch("Event");
+  // reconstructed tracks
+  fBranchTrack = fTreeReader->UseBranch("Track");
+  fItTrack = fBranchTrack->MakeIterator();
+  // calorimeter towers
+  fBranchTower = fTreeReader->UseBranch("Tower");
+  fItTower = fBranchTower->MakeIterator();
+  // reconstructed photons
+  fBranchPhoton = fTreeReader->UseBranch("Photon");
+  fItPhoton = fBranchPhoton->MakeIterator();
+  // reconstructed electrons
+  fBranchElectron = fTreeReader->UseBranch("Electron");
+  fItElectron = fBranchElectron->MakeIterator();
+  // reconstructed muons
+  fBranchMuon = fTreeReader->UseBranch("Muon");
+  fItMuon = fBranchMuon->MakeIterator();
+  // reconstructed jets
+  fBranchJet = fTreeReader->UseBranch("Jet");
+  fItJet = fBranchJet->MakeIterator();
+  // missing transverse energy
+  fBranchMissingET = fTreeReader->UseBranch("MissingET");
+}
+
+//------------------------------------------------------------------------------
+
+LHCOWriter::~LHCOWriter()
+{
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOWriter::ProcessEvent()
+{
+  fIntParam[0] = 0;
+
+  AnalyseEvent();
+
+  AnalysePhotons();
+  AnalyseElectrons();
+  AnalyseMuons();
+  AnalyseTauJets();
+  AnalyseJets();
+
+  AnalyseMissingET();
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOWriter::Reset()
+{
+  int i;
+  for(i = 1; i < kIntParamSize; ++i)
+  {
+    fIntParam[i] = 0;
+  }
+
+  for(i = 0; i < kDblParamSize; ++i)
+  {
+    fDblParam[i] = 0.0;
+  }
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOWriter::Write()
+{
+  fprintf(fOutputFile, "%4d %4d %8.3f %8.3f %7.2f %7.2f %6.1f %6.1f %7.2f %6.1f %6.1f\n",
+    fIntParam[0], fIntParam[1], fDblParam[0], fDblParam[1], fDblParam[2],
+    fDblParam[3], fDblParam[4], fDblParam[5], fDblParam[6], fDblParam[7], fDblParam[8]);
+
+  ++fIntParam[0];
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOWriter::AnalyseEvent()
+{
+  Event *element;
+
+  element = static_cast<Event*>(fBranchEvent->At(0));
+
+  fprintf(fOutputFile, "%4d %13lld %8d\n", 0, element->Number, 0);
+
+  ++fIntParam[0];
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOWriter::AnalysePhotons()
+{
+  Photon *element;
+
+  fItPhoton->Reset();
+  while((element = static_cast<Photon*>(fItPhoton->Next())))
+  {
+    Reset();
+
+    fIntParam[1] = 0;
+
+    fDblParam[0] = element->Eta;
+    fDblParam[1] = element->Phi;
+    fDblParam[2] = element->PT;
+
+    fDblParam[6] = element->EhadOverEem;
+
+    Write();
+  }
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOWriter::AnalyseElectrons()
+{
+  Electron *element;
+
+  fItElectron->Reset();
+  while((element = static_cast<Electron*>(fItElectron->Next())))
+  {
+    Reset();
+
+    fIntParam[1] = 1;
+
+    fDblParam[0] = element->Eta;
+    fDblParam[1] = element->Phi;
+    fDblParam[2] = element->PT;
+
+    fDblParam[4] = element->Charge;
+
+    fDblParam[6] = element->EhadOverEem;
+
+    Write();
+  }
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOWriter::AnalyseMuons()
+{
+  Muon *element;
+  Track *track;
+  Tower *tower;
+  Jet *jet;
+  Int_t muonCounter, tauCounter, jetCounter, minIndex;
+  Float_t sumPT, sumET, ratET, jetDR, minDR;
+
+  muonCounter = 0;
+  fItMuon->Reset();
+  while((element = static_cast<Muon*>(fItMuon->Next())))
+  {
+    Reset();
+
+    sumPT = 0.0;
+    fItTrack->Reset();
+    while((track = static_cast<Track*>(fItTrack->Next())))
+    {
+      if(element->P4().DeltaR(track->P4()) < 0.5) sumPT += track->PT;
+    }
+
+    sumET = 0.0;
+    fItTower->Reset();
+    while((tower = static_cast<Tower*>(fItTower->Next())))
+    {
+      if(element->P4().DeltaR(tower->P4()) < 0.5) sumET += tower->ET;
+    }
+
+    tauCounter = 0;
+    jetCounter = 0;
+    minIndex = -1;
+    minDR = 1.0E9;
+    fItJet->Reset();
+    while((jet = static_cast<Jet*>(fItJet->Next())))
+    {
+      if(jet->TauTag != 0)
+      {
+        ++tauCounter;
+        continue;
+      }
+
+      jetDR = element->P4().DeltaR(jet->P4());
+      if(jetDR < minDR)
+      {
+        minIndex = jetCounter;
+        minDR = jetDR;
+      }
+      ++jetCounter;
+    }
+
+    fIntParam[1] = 2;
+
+    fDblParam[0] = element->Eta;
+    fDblParam[1] = element->Phi;
+    fDblParam[2] = element->PT;
+
+    fDblParam[3] = 0.11;
+
+    fDblParam[4] = element->Charge;
+
+    if(minIndex >= 0)
+    {
+      fDblParam[5] = fIntParam[0] + fBranchMuon->GetEntriesFast() - muonCounter + tauCounter + minIndex;
+    }
+
+    ratET = sumET/element->PT;
+    fDblParam[6] = Float_t(TMath::Nint(sumPT)) + (ratET < 1.0 ? ratET : 0.99);
+
+    Write();
+    ++muonCounter;
+  }
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOWriter::AnalyseTauJets()
+{
+  Jet *element;
+  Track *track;
+  Int_t counter;
+
+  fItJet->Reset();
+  while((element = static_cast<Jet*>(fItJet->Next())))
+  {
+    if(element->TauTag == 0) continue;
+
+    Reset();
+
+    counter = 0;
+    fItTrack->Reset();
+    while((track = static_cast<Track*>(fItTrack->Next())))
+    {
+      if(element->P4().DeltaR(track->P4()) < 0.5) ++counter;
+    }
+
+    fIntParam[1] = 3;
+
+    fDblParam[0] = element->Eta;
+    fDblParam[1] = element->Phi;
+    fDblParam[2] = element->PT;
+    fDblParam[3] = element->Mass;
+    fDblParam[4] = counter * element->Charge;
+
+    fDblParam[6] = element->EhadOverEem;
+
+    Write();
+  }
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOWriter::AnalyseJets()
+{
+  Jet *element;
+  Track *track;
+  Int_t counter;
+
+  fItJet->Reset();
+  while((element = static_cast<Jet*>(fItJet->Next())))
+  {
+    if(element->TauTag != 0) continue;
+
+    Reset();
+
+    counter = 0;
+    fItTrack->Reset();
+    while((track = static_cast<Track*>(fItTrack->Next())))
+    {
+      if(element->P4().DeltaR(track->P4()) < 0.5) ++counter;
+    }
+
+    fIntParam[1] = 4;
+
+    fDblParam[0] = element->Eta;
+    fDblParam[1] = element->Phi;
+    fDblParam[2] = element->PT;
+    fDblParam[3] = element->Mass;
+    fDblParam[4] = counter;
+    fDblParam[5] = element->BTag;
+    fDblParam[6] = element->EhadOverEem;
+
+    Write();
+  }
+}
+
+//---------------------------------------------------------------------------
+
+void LHCOWriter::AnalyseMissingET()
+{
+  MissingET *element;
+
+  element = static_cast<MissingET*>(fBranchMissingET->At(0));
+
+  Reset();
+
+  fIntParam[1] = 6;
+
+  fDblParam[1] = element->Phi;
+  fDblParam[2] = element->MET;
+
+  Write();
+}
+
+//---------------------------------------------------------------------------
+
+static bool interrupted = false;
+
+void SignalHandler(int sig)
+{
+  interrupted = true;
+}
+
+//---------------------------------------------------------------------------
+
+int main(int argc, char *argv[])
+{
+  char appName[] = "root2lhco";
+  stringstream message;
+  FILE *outputFile = 0;
+  TChain *inputChain = 0;
+  LHCOWriter *writer = 0;
+  ExRootTreeReader *treeReader = 0;
+  Long64_t entry, allEntries;
+
+  if(argc < 2 || argc > 3)
+  {
+    cout << " Usage: " << appName << " input_file" << " [output_file]" << endl;
+    cout << " input_file - input file in ROOT format," << endl;
+    cout << " output_file - output file in LHCO format," << endl;
+    cout << " with no output_file, or when output_file is -, write to standard output." << endl;
+    return 1;
+  }
+
+  signal(SIGINT, SignalHandler);
+
+  gROOT->SetBatch();
+
+  int appargc = 1;
+  char *appargv[] = {appName};
+  TApplication app(appName, &appargc, appargv);
+
+  try
+  {
+    cout << "** Reading " << argv[1] << endl;
+    inputChain = new TChain("Delphes");
+    inputChain->Add(argv[1]);
+
+    ExRootTreeReader *treeReader = new ExRootTreeReader(inputChain);
+
+    if(argc == 2 || strcmp(argv[2], "-") == 0)
+    {
+      outputFile = stdout;
+    }
+    else
+    {
+      outputFile = fopen(argv[2], "w");
+
+      if(outputFile == NULL)
+      {
+        message << "can't open " << argv[2];
+        throw runtime_error(message.str());
+      }
+    }
+
+    allEntries = treeReader->GetEntries();
+    cout << "** Input file contains " << allEntries << " events" << endl;
+
+    if(allEntries > 0)
+    {
+      // Create LHC Olympics converter:
+      writer = new LHCOWriter(treeReader, outputFile);
+
+      ExRootProgressBar progressBar(allEntries - 1);
+      // Loop over all events
+      for(entry = 0; entry < allEntries && !interrupted; ++entry)
+      {
+        if(!treeReader->ReadEntry(entry))
+        {
+          cerr << "** ERROR: cannot read event " << entry << endl;
+          break;
+        }
+
+        writer->ProcessEvent();
+
+        progressBar.Update(entry);
+      }
+      progressBar.Finish();
+
+      delete writer;
+    }
+
+    cout << "** Exiting..." << endl;
+
+    if(outputFile != stdout) fclose(outputFile);
+    delete treeReader;
+    delete inputChain;
+    return 0;
+  }
+  catch(runtime_error &e)
+  {
+    if(writer) delete writer;
+    if(treeReader) delete treeReader;
+    if(inputChain) delete inputChain;
+    cerr << "** ERROR: " << e.what() << endl;
+    return 1;
+  }
+}
+
+
Index: trunk/Delphes/Delphes-3.0.9/converters/root2pileup.cpp
===================================================================
--- trunk/Delphes/Delphes-3.0.9/converters/root2pileup.cpp	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/converters/root2pileup.cpp	(revision 5)
@@ -0,0 +1,125 @@
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include <signal.h>
+
+#include "TROOT.h"
+#include "TApplication.h"
+
+#include "TFile.h"
+#include "TClonesArray.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesPileUpWriter.h"
+
+#include "ExRootAnalysis/ExRootTreeReader.h"
+#include "ExRootAnalysis/ExRootProgressBar.h"
+
+using namespace std;
+
+//---------------------------------------------------------------------------
+
+static bool interrupted = false;
+
+void SignalHandler(int sig)
+{
+  interrupted = true;
+}
+
+//---------------------------------------------------------------------------
+
+int main(int argc, char *argv[])
+{
+  char appName[] = "root2pileup";
+  stringstream message;
+  TChain *inputChain = 0;
+  ExRootTreeReader *treeReader = 0;
+  TClonesArray *branchParticle = 0;
+  TIterator *itParticle = 0;
+  GenParticle *particle = 0;
+  DelphesPileUpWriter *writer = 0;
+  Long64_t entry, allEntries;
+  Int_t i;
+
+  if(argc < 3)
+  {
+    cout << " Usage: " << appName << " output_file" << " input_file(s)" << endl;
+    cout << " output_file - output binary pile-up file," << endl;
+    cout << " input_file(s) - input file(s) in ROOT format." << endl;
+    return 1;
+  }
+
+  signal(SIGINT, SignalHandler);
+
+  gROOT->SetBatch();
+
+  int appargc = 1;
+  char *appargv[] = {appName};
+  TApplication app(appName, &appargc, appargv);
+
+  try
+  {
+    inputChain = new TChain("Delphes");
+    for(i = 2; i < argc && !interrupted; ++i)
+    {
+      inputChain->Add(argv[i]);
+    }
+
+    treeReader = new ExRootTreeReader(inputChain);
+    branchParticle = treeReader->UseBranch("Particle");
+    itParticle = branchParticle->MakeIterator();
+
+    writer = new DelphesPileUpWriter(argv[1]);
+
+    allEntries = treeReader->GetEntries();
+    cout << "** Input file(s) contain(s) " << allEntries << " events" << endl;
+
+    if(allEntries > 0)
+    {
+      ExRootProgressBar progressBar(allEntries - 1);
+      // Loop over all events in the input file
+      for(entry = 0; entry < allEntries && !interrupted; ++entry)
+      {
+        if(!treeReader->ReadEntry(entry))
+        {
+          cerr << "** ERROR: cannot read event " << entry << endl;
+          break;
+        }
+
+        itParticle->Reset();
+        while((particle = static_cast<GenParticle*>(itParticle->Next())))
+        {
+          writer->WriteParticle(particle->PID,
+            particle->X, particle->Y, particle->Z, particle->T,
+            particle->Px, particle->Py, particle->Pz, particle->E);
+        }
+        
+        writer->WriteEntry();
+
+        progressBar.Update(entry);
+      }
+      progressBar.Finish();
+
+      writer->WriteIndex();
+    }
+
+    cout << "** Exiting..." << endl;
+
+    delete writer;
+    delete itParticle;
+    delete treeReader;
+    delete inputChain;
+    return 0;
+  }
+  catch(runtime_error &e)
+  {
+    if(writer) delete writer;
+    if(itParticle) delete itParticle;
+    if(treeReader) delete treeReader;
+    if(inputChain) delete inputChain;
+    cerr << "** ERROR: " << e.what() << endl;
+    return 1;
+  }
+}
Index: trunk/Delphes/Delphes-3.0.9/converters/stdhep2pileup.cpp
===================================================================
--- trunk/Delphes/Delphes-3.0.9/converters/stdhep2pileup.cpp	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/converters/stdhep2pileup.cpp	(revision 5)
@@ -0,0 +1,176 @@
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+#include <signal.h>
+
+#include "TROOT.h"
+#include "TApplication.h"
+
+#include "TFile.h"
+#include "TObjArray.h"
+#include "TStopwatch.h"
+#include "TDatabasePDG.h"
+#include "TParticlePDG.h"
+#include "TLorentzVector.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesSTDHEPReader.h"
+#include "classes/DelphesPileUpWriter.h"
+
+#include "ExRootAnalysis/ExRootTreeWriter.h"
+#include "ExRootAnalysis/ExRootTreeBranch.h"
+#include "ExRootAnalysis/ExRootProgressBar.h"
+
+using namespace std;
+
+//---------------------------------------------------------------------------
+
+static bool interrupted = false;
+
+void SignalHandler(int sig)
+{
+  interrupted = true;
+}
+
+//---------------------------------------------------------------------------
+
+int main(int argc, char *argv[])
+{
+  char appName[] = "stdhep2pileup";
+  stringstream message;
+  FILE *inputFile = 0;
+  DelphesFactory *factory = 0;
+  TObjArray *stableParticleOutputArray = 0, *allParticleOutputArray = 0, *partonOutputArray = 0;
+  TIterator *itParticle = 0;
+  Candidate *candidate = 0;
+  DelphesPileUpWriter *writer = 0;
+  DelphesSTDHEPReader *reader = 0;
+  Int_t i;
+  Long64_t length, eventCounter;
+
+  if(argc < 2)
+  {
+    cout << " Usage: " << appName << " output_file" << " [input_file(s)]" << endl;
+    cout << " output_file - output binary pile-up file," << endl;
+    cout << " input_file(s) - input file(s) in STDHEP format," << endl;
+    cout << " with no input_file, or when input_file is -, read standard input." << endl;
+    return 1;
+  }
+
+  signal(SIGINT, SignalHandler);
+
+  gROOT->SetBatch();
+
+  int appargc = 1;
+  char *appargv[] = {appName};
+  TApplication app(appName, &appargc, appargv);
+
+  try
+  {
+    writer = new DelphesPileUpWriter(argv[1]);
+
+    factory = new DelphesFactory("ObjectFactory");
+    allParticleOutputArray = factory->NewPermanentArray();
+    stableParticleOutputArray = factory->NewPermanentArray();
+    partonOutputArray = factory->NewPermanentArray();
+
+    itParticle = stableParticleOutputArray->MakeIterator();
+
+    reader = new DelphesSTDHEPReader;
+
+    i = 2;
+    do
+    {
+      if(interrupted) break;
+
+      if(i == argc || strncmp(argv[i], "-", 2) == 0)
+      {
+        cout << "** Reading standard input" << endl;
+        inputFile = stdin;
+        length = -1;
+      }
+      else
+      {
+        cout << "** Reading " << argv[i] << endl;
+        inputFile = fopen(argv[i], "r");
+
+        if(inputFile == NULL)
+        {
+          message << "can't open " << argv[i];
+          throw runtime_error(message.str());
+        }
+
+        fseek(inputFile, 0L, SEEK_END);
+        length = ftello(inputFile);
+        fseek(inputFile, 0L, SEEK_SET);
+
+        if(length <= 0)
+        {
+          fclose(inputFile);
+          ++i;
+          continue;
+        }
+      }
+
+      reader->SetInputFile(inputFile);
+
+      ExRootProgressBar progressBar(length);
+
+      // Loop over all objects
+      eventCounter = 0;
+      factory->Clear();
+      reader->Clear();
+      while(reader->ReadBlock(factory, allParticleOutputArray,
+        stableParticleOutputArray, partonOutputArray) && !interrupted)
+      {
+        if(reader->EventReady())
+        {
+          ++eventCounter;
+
+          itParticle->Reset();
+          while((candidate = static_cast<Candidate*>(itParticle->Next())))
+          {
+            const TLorentzVector &position = candidate->Position;
+            const TLorentzVector &momentum = candidate->Momentum;
+            writer->WriteParticle(candidate->PID,
+              position.X(), position.Y(), position.Z(), position.T(),
+              momentum.Px(), momentum.Py(), momentum.Pz(), momentum.E());
+          }
+
+          writer->WriteEntry();
+
+          factory->Clear();
+          reader->Clear();
+        }
+        progressBar.Update(ftello(inputFile), eventCounter);
+      }
+
+      fseek(inputFile, 0L, SEEK_END);
+      progressBar.Update(ftello(inputFile), eventCounter, kTRUE);
+      progressBar.Finish();
+
+      if(inputFile != stdin) fclose(inputFile);
+
+      ++i;
+    }
+    while(i < argc);
+
+    writer->WriteIndex();
+
+    cout << "** Exiting..." << endl;
+
+    delete reader;
+    delete factory;
+    delete writer;
+
+    return 0;
+  }
+  catch(runtime_error &e)
+  {
+    if(writer) delete writer;
+    cerr << "** ERROR: " << e.what() << endl;
+    return 1;
+  }
+}
Index: trunk/Delphes/Delphes-3.0.9/display/DelphesCaloData.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/display/DelphesCaloData.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/display/DelphesCaloData.cc	(revision 5)
@@ -0,0 +1,24 @@
+
+#include "display/DelphesCaloData.h"
+
+//------------------------------------------------------------------------------
+
+DelphesCaloData::DelphesCaloData(Int_t nslices) :
+  TEveCaloDataVec(nslices)
+{
+}
+
+//------------------------------------------------------------------------------
+
+DelphesCaloData::~DelphesCaloData()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void DelphesCaloData::ClearTowers()
+{
+   fGeomVec.clear();
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/display/DelphesCaloData.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/display/DelphesCaloData.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/display/DelphesCaloData.h	(revision 5)
@@ -0,0 +1,20 @@
+#ifndef DelphesCaloData_h
+#define DelphesCaloData_h
+
+#include "TEveCaloData.h"
+
+class DelphesCaloData: public TEveCaloDataVec 
+{
+public:
+  
+  DelphesCaloData(Int_t nslices);
+
+  ~DelphesCaloData();
+
+  void ClearTowers();
+
+  ClassDef(DelphesCaloData, 1)
+};
+
+#endif /* DelphesCaloData_h */
+
Index: trunk/Delphes/Delphes-3.0.9/display/DelphesDisplay.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/display/DelphesDisplay.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/display/DelphesDisplay.cc	(revision 5)
@@ -0,0 +1,150 @@
+
+#include "TEveManager.h"
+#include "TEveViewer.h"
+#include "TGLViewer.h"
+#include "TGLWidget.h"
+#include "TEveScene.h"
+#include "TEveProjectionManager.h"
+#include "TEveProjectionAxes.h"
+#include "TEveBrowser.h"
+#include "TEveWindow.h"
+#include "TGTab.h"
+
+#include "TEveCalo2DGL.h"
+#include "TEveCalo3DGL.h"  
+#include "TEveCaloLegoGL.h"
+#include "TEveCaloLegoOverlay.h"
+#include "TEveLegoEventHandler.h"
+
+#include "display/DelphesDisplay.h"
+
+//------------------------------------------------------------------------------
+
+DelphesDisplay::DelphesDisplay()
+{
+  TEveProjectionAxes *axes;
+  TEveWindowSlot *slot;
+  TEveWindowPack *packH, *pack0, *pack1;
+
+  fRPhiMgr = new TEveProjectionManager(TEveProjection::kPT_RPhi);
+  fRhoZMgr = new TEveProjectionManager(TEveProjection::kPT_RhoZ);
+
+	fRPhiGeomScene = gEve->SpawnNewScene("RPhi Geometry");
+	fRhoZGeomScene = gEve->SpawnNewScene("RhoZ Geometry");
+
+	fRPhiCaloScene = gEve->SpawnNewScene("RPhi Calorimeter");
+	fRhoZCaloScene = gEve->SpawnNewScene("RhoZ Calorimeter");
+	fLegoCaloScene = gEve->SpawnNewScene("Lego Calorimeter");
+
+	fRPhiEventScene = gEve->SpawnNewScene("RPhi Event Data");
+	fRhoZEventScene = gEve->SpawnNewScene("RhoZ Event Data");
+  
+  axes = new TEveProjectionAxes(fRPhiMgr);
+  fRPhiGeomScene->AddElement(axes);
+
+  axes = new TEveProjectionAxes(fRhoZMgr);
+  fRhoZGeomScene->AddElement(axes);
+
+  // close default tab
+  gEve->GetBrowser()->GetTabRight()->CloseTab(0);
+
+  // frames
+  slot = TEveWindow::CreateWindowInTab(gEve->GetBrowser()->GetTabRight());
+  packH = slot->MakePack();
+
+  packH->SetElementName("Delphes Display");
+  packH->SetHorizontal();
+  packH->SetShowTitleBar(kFALSE);
+
+  pack0 = packH->NewSlot()->MakePack();
+  pack0->SetShowTitleBar(kFALSE);
+
+  pack1 = packH->NewSlot()->MakePack();
+  pack1->SetShowTitleBar(kFALSE);
+
+  pack1->NewSlot()->MakeCurrent();
+  f3DimView = gEve->SpawnNewViewer("3D View", "");
+  f3DimView->AddScene(gEve->GetGlobalScene());
+  f3DimView->AddScene(gEve->GetEventScene());
+  
+  pack1->NewSlot()->MakeCurrent();
+  fLegoView = gEve->SpawnNewViewer("Lego View", "");
+  fLegoView->GetGLViewer()->SetCurrentCamera(TGLViewer::kCameraOrthoXOY);
+  fLegoView->AddScene(fLegoCaloScene);
+  
+  pack0->NewSlot()->MakeCurrent();
+  fRPhiView = gEve->SpawnNewViewer("RPhi View", "");
+  fRPhiView->GetGLViewer()->SetCurrentCamera(TGLViewer::kCameraOrthoXOY);
+  fRPhiView->AddScene(fRPhiGeomScene);
+  fRPhiView->AddScene(fRPhiCaloScene);
+  fRPhiView->AddScene(fRPhiEventScene);
+        
+  pack0->NewSlot()->MakeCurrent();
+  fRhoZView = gEve->SpawnNewViewer("RhoZ View", "");
+  fRhoZView->GetGLViewer()->SetCurrentCamera(TGLViewer::kCameraOrthoXOY);
+  fRhoZView->AddScene(fRhoZGeomScene);
+  fRhoZView->AddScene(fRhoZCaloScene);
+  fRhoZView->AddScene(fRhoZEventScene);
+}
+
+//------------------------------------------------------------------------------
+
+DelphesDisplay::~DelphesDisplay()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void DelphesDisplay::ImportGeomRPhi(TEveElement* el)
+{ 
+  fRPhiMgr->ImportElements(el, fRPhiGeomScene);
+}
+
+void DelphesDisplay::ImportGeomRhoZ(TEveElement* el)
+{ 
+  fRhoZMgr->ImportElements(el, fRhoZGeomScene);
+}
+
+void DelphesDisplay::ImportCaloRPhi(TEveCalo3D *calo)
+{
+  fRPhiMgr->ImportElements(calo, fRPhiCaloScene);
+}
+
+void DelphesDisplay::ImportCaloRhoZ(TEveCalo3D *calo)
+{
+  fRhoZMgr->ImportElements(calo, fRhoZCaloScene);
+}
+
+void DelphesDisplay::ImportCaloLego(TEveCaloLego *calo)
+{
+  TEveCaloLegoOverlay *overlay = new TEveCaloLegoOverlay();
+ 
+  overlay->SetCaloLego(calo);
+  fLegoView->GetGLViewer()->AddOverlayElement(overlay);
+
+  fLegoCaloScene->AddElement(calo);
+}
+
+void DelphesDisplay::ImportEventRPhi(TEveElement* el)
+{ 
+  fRPhiMgr->ImportElements(el, fRPhiEventScene);
+}
+
+void DelphesDisplay::ImportEventRhoZ(TEveElement* el)
+{ 
+  fRhoZMgr->ImportElements(el, fRhoZEventScene);
+}
+
+//---------------------------------------------------------------------------
+
+void DelphesDisplay::DestroyEventRPhi()
+{
+  fRPhiEventScene->DestroyElements();
+}
+
+void DelphesDisplay::DestroyEventRhoZ()
+{
+  fRhoZEventScene->DestroyElements();
+}
+//------------------------------------------------------------------------------
+
Index: trunk/Delphes/Delphes-3.0.9/display/DelphesDisplay.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/display/DelphesDisplay.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/display/DelphesDisplay.h	(revision 5)
@@ -0,0 +1,54 @@
+#ifndef DelphesDisplay_h
+#define DelphesDisplay_h
+
+class TEveProjectionManager;
+class TEveElement;
+class TEveCalo3D;
+class TEveCaloLego;
+class TEveViewer;
+class TEveScene;
+
+class DelphesDisplay
+{
+public:
+  
+  DelphesDisplay();
+
+  virtual ~DelphesDisplay();
+
+  void ImportGeomRPhi(TEveElement* el);
+  void ImportGeomRhoZ(TEveElement* el);
+
+  void ImportCaloRPhi(TEveCalo3D *calo);
+  void ImportCaloRhoZ(TEveCalo3D *calo);
+  void ImportCaloLego(TEveCaloLego *calo);
+
+  void ImportEventRPhi(TEveElement* el);
+  void ImportEventRhoZ(TEveElement* el);
+
+  void DestroyEventRPhi();
+  void DestroyEventRhoZ();
+
+private:
+
+  TEveProjectionManager *fRPhiMgr;
+  TEveProjectionManager *fRhoZMgr;
+
+  TEveViewer *fRPhiView;
+  TEveViewer *fRhoZView;
+  TEveViewer *f3DimView;
+  TEveViewer *fLegoView;
+
+  TEveScene *fRPhiGeomScene;
+  TEveScene *fRhoZGeomScene;
+
+  TEveScene *fRPhiCaloScene;
+  TEveScene *fRhoZCaloScene;
+  TEveScene *fLegoCaloScene;
+
+  TEveScene *fRPhiEventScene;
+  TEveScene *fRhoZEventScene;
+};
+
+#endif /* DelphesDisplay_h */
+
Index: trunk/Delphes/Delphes-3.0.9/display/DisplayLinkDef.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/display/DisplayLinkDef.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/display/DisplayLinkDef.h	(revision 5)
@@ -0,0 +1,27 @@
+
+/** ExRootAnalysisLinkDef
+ *
+ *  Lists classes to be included in cint dicitonary
+ *
+ *  $Date: 2013-04-22 22:00:46 +0200 (Mon, 22 Apr 2013) $
+ *  $Revision: 1097 $
+ *
+ *  
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "display/DelphesDisplay.h"
+#include "display/DelphesCaloData.h"
+
+#ifdef __CINT__
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+#pragma link C++ class DelphesDisplay+;
+#pragma link C++ class DelphesCaloData+;
+
+#endif
+
Index: trunk/Delphes/Delphes-3.0.9/doc/Makefile.arch
===================================================================
--- trunk/Delphes/Delphes-3.0.9/doc/Makefile.arch	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/doc/Makefile.arch	(revision 5)
@@ -0,0 +1,493 @@
+# -*- mode: makefile -*-
+#
+# Makefile containing platform dependencies for ROOT based projects.
+#
+# Copyright (c) 2000 Rene Brun and Fons Rademakers
+#
+# Author: Fons Rademakers, 29/2/2000
+
+RC           := root-config
+ifneq ($(shell which $(RC) 2>&1 | sed -ne "s@.*/$(RC)@$(RC)@p"),$(RC))
+ifneq ($(ROOTSYS),)
+RC1          := $(ROOTSYS)/bin/root-config
+ifneq ($(shell which $(RC1) 2>&1 | sed -ne "s@.*/$(RC)@$(RC)@p"),$(RC))
+$(error Please make sure $(RC1) can be found in path)
+else
+RC           := $(RC1)
+endif
+else
+$(error Please make sure $(RC) can be found in path)
+endif
+endif
+
+ARCH         := $(shell $(RC) --arch)
+PLATFORM     := $(shell $(RC) --platform)
+ALTCC        := $(shell $(RC) --cc)
+ALTCXX       := $(shell $(RC) --cxx)
+ALTF77       := $(shell $(RC) --f77)
+ALTLD        := $(shell $(RC) --ld)
+
+#CXX           =
+ObjSuf        = o
+SrcSuf        = cxx
+ExeSuf        =
+DllSuf        = so
+OutPutOpt     = -o # keep whitespace after "-o"
+
+ifeq (debug,$(findstring debug,$(ROOTBUILD)))
+OPT           = -g
+OPT2          = -g
+else
+ifneq ($(findstring debug, $(strip $(shell $(RC) --config))),)
+OPT           = -g
+OPT2          = -g
+else
+OPT           = -O
+OPT2          = -O2
+endif
+endif
+
+ROOTCFLAGS   := $(shell $(RC) --cflags)
+ROOTLDFLAGS  := $(shell $(RC) --ldflags)
+ROOTLIBS     := $(shell $(RC) --libs)
+ROOTGLIBS    := $(shell $(RC) --glibs)
+HASTHREAD    := $(shell $(RC) --has-thread)
+ROOTDICTTYPE := $(shell $(RC) --dicttype)
+ROOTCINT     := rootcint
+
+ifeq ($(PLATFORM),macosx)
+MACOSX_MINOR := $(shell sw_vers | sed -n 's/ProductVersion://p' | cut -d . -f 2)
+ifeq ($(MACOSX_DEPLOYMENT_TARGET),)
+MACOSXTARGET := 10.$(MACOSX_MINOR)
+else
+MACOSXTARGET := $(MACOSX_DEPLOYMENT_TARGET)
+endif
+endif
+
+ifeq ($(ARCH),hpuxacc)
+# HP-UX 10.x with aCC
+CXX           = aCC
+CXXFLAGS      = $(OPT) +Z
+LD            = aCC
+LDFLAGS       = $(OPT) -z
+SOFLAGS       = -b
+endif
+
+ifeq ($(ARCH),hpuxia64acc)
+# HP-UX 11i 1.5 (IA-64) with aCC
+CXX           = aCC
+CXXFLAGS      = +DD64 $(OPT) +Z
+LD            = aCC
+LDFLAGS       = +DD64 $(OPT) -z
+SOFLAGS       = -b
+endif
+
+ifeq ($(ARCH),hpuxgcc)
+# HP-UX 10.x with g++
+CXXFLAGS      = $(OPT) -fPIC
+CXX           = g++
+LD            = g++
+LDFLAGS       = $(OPT)
+SOFLAGS       = -fPIC -shared
+endif
+
+ifeq ($(ARCH),hurddeb)
+# GNU/Hurd
+CXX           = g++
+CXXFLAGS      = $(OPT2) -Wall -fPIC
+LD            = g++
+LDFLAGS       = $(OPT2)
+SOFLAGS       = -shared
+endif
+
+ifeq ($(ARCH),aix5)
+# IBM AIX >5.x xlC
+CXX           = xlC
+CXXFLAGS      = $(OPT)
+LD            = xlC
+LDFLAGS       = $(OPT)
+SOFLAGS       =
+DllSuf        = a
+endif
+
+ifeq ($(ARCH),aixgcc)
+# IBM AIX >5.x with GCC
+CXX           = g++
+CXXFLAGS      = $(OPT)
+LD            = g++
+LDFLAGS       = $(OPT)
+SOFLAGS       = -shared
+DllSuf        = a
+EXPLLINKLIBS  = $(ROOTLIBS) $(ROOTGLIBS)
+endif
+
+ifeq ($(ARCH),solaris)
+# Solaris CC
+CXX           = /opt/SUNWspro/bin/CC
+CXXFLAGS      = $(OPT) -KPIC
+LD            = /opt/SUNWspro/bin/CC
+LDFLAGS       = $(OPT)
+SOFLAGS       = -G
+endif
+
+ifeq ($(ARCH),solarisCC5)
+# Solaris CC 5.0
+CXX           = CC
+CXXFLAGS      = $(OPT) -KPIC
+LD            = CC
+LDFLAGS       = $(OPT)
+SOFLAGS       = -G
+endif
+
+ifeq ($(ARCH),solaris64CC5)
+# Solaris CC 5.0 64-bit
+CXX           = CC
+CXXFLAGS      = $(OPT) -KPIC
+LD            = CC
+LDFLAGS       = $(OPT)
+SOFLAGS       = -G
+endif
+
+ifeq ($(ARCH),sgicc)
+# SGI
+CXX           = CC -n32  -I/usr/include/CC.sgi
+CXXFLAGS      = $(OPT)
+LD            = CC -n32 -LANG:std  -I/usr/include/CC.sgi
+LDFLAGS       = $(OPT)
+SOFLAGS       = -shared
+endif
+
+ifeq ($(ARCH),sgicc64)
+# SGI
+CXX           = CC -64  -I/usr/include/CC.sgi
+CXXFLAGS      = $(OPT)
+LD            = CC -64 -LANG:std -I/usr/include/CC.sgi
+LDFLAGS       = $(OPT)
+SOFLAGS       = -shared
+endif
+
+ifeq ($(ARCH),sgigcc)
+# SGI 6.x with gcc
+CXX           = g++
+CXXFLAGS      = $(OPT) -Wall -fPIC
+LD            = g++
+LDFLAGS       = $(OPT) -Wl,-u,__builtin_new -Wl,-u,__builtin_delete -Wl,-u,__nw__FUiPv
+SOFLAGS       = -shared
+endif
+
+ifeq ($(ARCH),sgin32gcc)
+# SGI 6.x with gcc for n32 ABI
+CXX           = g++
+CXXFLAGS      = $(OPT) -Wall -fPIC
+LD            = g++
+LDFLAGS       = $(OPT) -L/usr/lib32 -Wl,-woff,134 -lgen
+SOFLAGS       = -shared
+endif
+
+ifeq ($(ARCH),alphagcc)
+# Alpha/OSF with gcc
+CXX           = g++
+CXXFLAGS      = $(OPT2) -Wall -fPIC
+LD            = g++
+LDFLAGS       = $(OPT2)
+SOFLAGS       = -Wl,-expect_unresolved,* -shared
+endif
+
+ifeq ($(ARCH),alphacxx6)
+# Alpha/OSF with cxx6
+CXX           = cxx
+CXXFLAGS      = $(OPT)
+LD            = cxx
+LDFLAGS       = $(OPT)
+SOFLAGS       = -shared -nocxxstd -Wl,-expect_unresolved,*,-msym
+endif
+
+ifeq ($(ARCH),linux)
+# Linux with egcs, gcc 2.9x, gcc 3.x
+CXX           = g++
+CXXFLAGS      = $(OPT2) -Wall -fPIC
+LD            = g++
+LDFLAGS       = $(OPT2)
+SOFLAGS       = -shared
+endif
+
+ifeq ($(ARCH),linuxicc)
+# Linux with Intel icc compiler
+ICC_MAJOR    := $(shell icc -v 2>&1 | awk '{ if (NR==1) print $$2 }' | \
+                cut -d'.' -f1)
+ICC_MINOR    := $(shell icc -v 2>&1 | awk '{ if (NR==1) print $$2 }' | \
+                cut -d'.' -f2)
+CXX           = icc
+CXXFLAGS      = $(OPT) -fPIC -wd1476
+LD            = icpc
+LDFLAGS       = $(OPT)
+SOFLAGS       = -shared
+endif
+
+ifeq ($(ARCH),linuxppcgcc)
+# PPC Linux with gcc and glibc
+CXX           = g++
+CXXFLAGS      = $(OPT2) -Wall -fPIC
+LD            = g++
+LDFLAGS       = $(OPT2)
+SOFLAGS       = -shared
+endif
+
+ifeq ($(ARCH),linuxia64gcc)
+# Itanium Linux with gcc 2.9x
+CXX           = g++
+CXXFLAGS      = $(OPT2) -Wall -fPIC
+LD            = g++
+LDFLAGS       = $(OPT2)
+SOFLAGS       = -shared
+endif
+
+ifeq ($(ARCH),linuxia64ecc)
+# Itanium Linux with Intel icc (was ecc)
+ICC_MAJOR    := $(shell icc -v 2>&1 | awk '{ if (NR==1) print $$2 }' | \
+                cut -d'.' -f1)
+ICC_MINOR    := $(shell icc -v 2>&1 | awk '{ if (NR==1) print $$2 }' | \
+                cut -d'.' -f2)
+CXX           = icc
+CXXFLAGS      = $(OPT) -fPIC -wd1476 -ftz
+LD            = icpc
+LDFLAGS       = $(OPT)
+SOFLAGS       = -shared
+endif
+
+ifeq ($(ARCH),linuxx8664gcc)
+# AMD Opteron and Intel EM64T (64 bit mode) Linux with gcc 3.x
+CXX           = g++
+CXXFLAGS      = $(OPT2) -Wall -fPIC
+LD            = g++
+LDFLAGS       = $(OPT2)
+SOFLAGS       = -shared
+endif
+
+ifeq ($(ARCH),linuxppc64gcc)
+# PPC64 Linux with gcc 3.x
+CXX           = g++
+CXXFLAGS      = $(OPT) -Wall -fPIC
+LD            = g++
+LDFLAGS       = $(OPT)
+SOFLAGS       = -shared
+endif
+
+ifeq ($(ARCH),linuxx8664icc)
+# AMD Opteron and Intel EM64T (64 bit mode) Linux with Intel icc compiler
+CXX           = icc
+CXXFLAGS      = $(OPT) -fPIC -wd1476 -wd1572
+LD            = icpc
+LDFLAGS       = $(OPT)
+SOFLAGS       = -shared
+endif
+
+ifeq ($(ARCH),linuxalphagcc)
+# Alpha Linux with gcc
+CXX           = g++
+CXXFLAGS      = $(OPT2) -Wall -fPIC
+LD            = g++
+LDFLAGS       = $(OPT2)
+SOFLAGS       = -shared
+endif
+
+ifeq ($(ARCH),linuxmips)
+# GNU/Linux on mips (BE/LE, O32/N32/N64) with gcc
+CXX           = g++
+CXXFLAGS      = $(OPT2) -Wall -fPIC
+LD            = g++
+LDFLAGS       = $(OPT2)
+SOFLAGS       = -shared
+endif
+
+ifeq ($(ARCH),linuxhppa)
+# GNU/Linux on hppa with gcc
+CXX           = g++
+CXXFLAGS      = $(OPT2) -Wall -fPIC
+LD            = g++
+LDFLAGS       = $(OPT2)
+SOFLAGS       = -shared
+endif
+
+ifeq ($(ARCH),linuxarm)
+# ARM Linux with egcs
+CXX           = g++
+CXXFLAGS      = $(OPT) -Wall -fPIC
+LD            = g++
+LDFLAGS       = $(OPT)
+SOFLAGS       = -shared
+endif
+
+ifeq ($(ARCH),freebsd4)
+# FreeBSD with glibc
+CXX           = g++
+CXXFLAGS      = $(OPT) -W -Wall -fPIC
+LD            = $(CXX)
+LDFLAGS       = $(OPT)
+SOFLAGS       = -shared -Wl,-x
+endif
+
+ifeq ($(ARCH),freebsd5)
+# FreeBSD with glibc
+CXX           = g++
+CXXFLAGS      = $(OPT) -W -Wall -fPIC
+LD            = $(CXX)
+LDFLAGS       = $(OPT)
+SOFLAGS       = -shared -Wl,-x
+endif
+
+ifeq ($(ARCH),freebsd7)
+# FreeBSD with libc
+CXX           = g++
+CXXFLAGS      = $(OPT) -W -Wall -fPIC
+LD            = $(CXX)
+LDFLAGS       = $(OPT)
+SOFLAGS       = -shared -Wl,-x
+endif
+
+ifeq ($(ARCH),openbsd)
+# OpenBSD with libc
+CXX           = g++
+CXXFLAGS      = $(OPT) -pipe -W -Wall -fPIC
+LD            = g++
+LDFLAGS       = $(OPT)
+SOFLAGS       = -shared -Wl,-x
+endif
+
+ifeq ($(ARCH),macosx)
+# MacOS X with cc (GNU cc 2.95.2 and gcc 3.3)
+CXX           = g++
+CXXFLAGS      = $(OPT2) -pipe -Wall -W -Woverloaded-virtual
+LD            = g++
+LDFLAGS       = $(OPT2) -mmacosx-version-min=$(MACOSXTARGET)
+EXPLLINKLIBS  = $(ROOTLIBS) $(ROOTGLIBS)
+# The SOFLAGS will be used to create the .dylib,
+# the .so will be created separately
+ifeq ($(subst $(MACOSX_MINOR),,1234),1234)
+DllSuf        = so
+else
+DllSuf        = dylib
+endif
+ifneq ($(subst $(MACOSX_MINOR),,12),12)
+LD            = g++
+endif
+SOFLAGS       = -dynamiclib -single_module -install_name $(CURDIR)/
+endif
+
+ifeq ($(ARCH),macosxicc)
+# MacOS X with Intel icc compiler
+ifeq ($(MACOSX_MINOR),5)
+MACOSX_MINOR := 4
+endif
+CXX           = icc
+CXXFLAGS      = $(OPT) -fPIC -wd1476
+LD            = icpc
+LDFLAGS       = $(OPT2) -mmacosx-version-min=$(MACOSXTARGET)
+EXPLLINKLIBS  = $(ROOTLIBS) $(ROOTGLIBS)
+# The SOFLAGS will be used to create the .dylib,
+# the .so will be created separately
+ifeq ($(subst $(MACOSX_MINOR),,1234),1234)
+DllSuf        = so
+else
+DllSuf        = dylib
+endif
+SOFLAGS       = -dynamiclib -single_module -install_name $(CURDIR)/
+endif
+
+ifeq ($(ARCH),macosx64)
+# MacOS X >= 10.4 with gcc 64 bit mode (GNU gcc 4.*)
+# Only specific option (-m64) comes from root-config
+CXX           = g++
+CXXFLAGS      = $(OPT2) -pipe -Wall -W -Woverloaded-virtual
+LD            = g++
+LDFLAGS       = $(OPT2) -mmacosx-version-min=$(MACOSXTARGET)
+EXPLLINKLIBS  = $(ROOTLIBS) $(ROOTGLIBS)
+# The SOFLAGS will be used to create the .dylib,
+# the .so will be created separately
+ifeq ($(subst $(MACOSX_MINOR),,1234),1234)
+DllSuf        = so
+else
+DllSuf        = dylib
+endif
+SOFLAGS       = -dynamiclib -single_module -install_name $(CURDIR)/
+endif
+
+ifeq ($(ARCH),win32)
+# Windows with the VC++ compiler
+VC_MAJOR     := $(shell unset VS_UNICODE_OUTPUT; cl.exe 2>&1 | awk '{ if (NR==1) print $$(NF-2) }' | \
+                cut -d'.' -f1)
+ObjSuf        = obj
+SrcSuf        = cxx
+ExeSuf        = .exe
+DllSuf        = dll
+OutPutOpt     = -out:
+CXX           = cl
+ifeq (debug,$(findstring debug,$(ROOTBUILD)))
+CXXOPT        = -Z7
+LDOPT         = -debug
+else
+ifneq ($(findstring debug, $(strip $(shell $(RC) --config))),)
+CXXOPT        = -Z7
+LDOPT         = -debug
+else
+CXXOPT        = -O2
+LDOPT         = -opt:ref
+endif
+endif
+ROOTINCDIR   := -I$(shell cygpath -m `$(RC) --incdir`)
+CXXFLAGS      = $(CXXOPT) -nologo $(ROOTINCDIR) -FIw32pragma.h
+LD            = link
+LDFLAGS       = $(LDOPT) -nologo
+SOFLAGS       = -DLL
+
+EXPLLINKLIBS  = $(ROOTLIBS) $(ROOTGLIBS)
+ifneq (,$(findstring $(VC_MAJOR),14 15))
+MT_EXE        = mt -nologo -manifest $@.manifest -outputresource:$@\;1; rm -f $@.manifest
+MT_DLL        = mt -nologo -manifest $@.manifest -outputresource:$@\;2; rm -f $@.manifest
+else
+MT_EXE        =
+MT_DLL        =
+endif
+endif
+
+ifeq ($(ARCH),win32gcc)
+# Windows with gcc
+DllSuf        = dll
+ExeSuf        = .exe
+CXX           = g++
+CXXFLAGS      = $(OPT) -pipe -Wall -Woverloaded-virtual -I/usr/X11R6/include
+LD            = g++
+LDFLAGS       = $(OPT) -Wl,--enable-auto-import \
+                -Wl,--enable-runtime-pseudo-reloc \
+		-L/usr/X11R6/lib
+SOFLAGS       = -shared -Wl,--enable-auto-image-base \
+                -Wl,--export-all-symbols
+EXPLLINKLIBS  = $(ROOTLIBS) $(ROOTGLIBS)
+endif
+
+ifeq ($(CXX),)
+$(error $(ARCH) invalid architecture)
+endif
+
+CXXFLAGS     += $(ROOTCFLAGS)
+LDFLAGS      += $(ROOTLDFLAGS)
+LIBS          = $(ROOTLIBS) $(SYSLIBS)
+GLIBS         = $(ROOTGLIBS) $(SYSLIBS)
+
+ifneq ($(ALTCC),)
+   CC  = $(ALTCC)
+endif
+ifneq ($(ALTCXX),)
+   CXX = $(ALTCXX)
+endif
+ifneq ($(ALTF77),)
+   F77 = $(ALTF77)
+endif
+ifneq ($(ALTLD),)
+   LD  = $(ALTLD)
+endif
+
+ifneq ($(findstring g++, $(CXX)),)
+GCC_MAJOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d'.' -f1)
+GCC_MINOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d'.' -f2)
+endif
Index: trunk/Delphes/Delphes-3.0.9/doc/RootTreeDescription.html
===================================================================
--- trunk/Delphes/Delphes-3.0.9/doc/RootTreeDescription.html	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/doc/RootTreeDescription.html	(revision 5)
@@ -0,0 +1,516 @@
+<html>
+<head>
+  <meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+  <meta NAME="keywords" CONTENT="root, tree, ntuple, format, description">
+  <title>root tree description</title>
+</head>
+<body>
+<H1>root tree description</H1>
+<hr>
+<H2>Classes</H2>
+<hr>
+<table style="border: 1px dotted;" align="center" border="0" cellpadding="7" cellspacing="3" widt="95%">
+<tr><td><b>Parameter</b></td>
+<td><b>Definition</b></td>
+<td><b>How it was calculated</b></td></tr>
+<tr bgcolor="#ffffff"><td colspan=3><hr><a name="Event"><H3>Event</H3><hr></td></tr>
+<tr bgcolor="#eeeeee">
+  <td>Number</td>
+  <td>event number</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff"><td colspan=3><hr><a name="LHCOEvent"><H3>LHCOEvent</H3><hr></td></tr>
+<tr bgcolor="#ffffff">
+  <td><a href="#Event">Event</a></td>
+  <td>LHCOEvent inherits all Event parameters</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Trigger</td>
+  <td>trigger word</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff"><td colspan=3><hr><a name="LHEFEvent"><H3>LHEFEvent</H3><hr></td></tr>
+<tr bgcolor="#ffffff">
+  <td><a href="#Event">Event</a></td>
+  <td>LHEFEvent inherits all Event parameters</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>ProcessID</td>
+  <td>subprocess code for the event </td>
+  <td> hepup.IDPRUP</td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Weight</td>
+  <td>weight for the event </td>
+  <td> hepup.XWGTUP</td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>ScalePDF</td>
+  <td>scale in GeV used in the calculation of the PDFs in the event </td>
+  <td> hepup.SCALUP</td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>AlphaQED</td>
+  <td>value of the QED coupling used in the event </td>
+  <td> hepup.AQEDUP</td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>AlphaQCD</td>
+  <td>value of the QCD coupling used in the event </td>
+  <td> hepup.AQCDUP</td>
+</tr>
+<tr bgcolor="#ffffff"><td colspan=3><hr><a name="HepMCEvent"><H3>HepMCEvent</H3><hr></td></tr>
+<tr bgcolor="#ffffff">
+  <td><a href="#Event">Event</a></td>
+  <td>HepMCEvent inherits all Event parameters</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>ProcessID</td>
+  <td>unique signal process id </td>
+  <td> signal_process_id()</td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>MPI</td>
+  <td>number of multi parton interactions </td>
+  <td> mpi () </td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Weight</td>
+  <td>weight for the event</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Scale</td>
+  <td>energy scale, see hep-ph/0109068 </td>
+  <td> event_scale()</td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>AlphaQED</td>
+  <td>QED coupling, see hep-ph/0109068 </td>
+  <td> alphaQED()</td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>AlphaQCD</td>
+  <td>QCD coupling, see hep-ph/0109068 </td>
+  <td> alphaQCD()</td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>ID1</td>
+  <td>flavour code of first parton </td>
+  <td> pdf_info()->id1()</td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>ID2</td>
+  <td>flavour code of second parton </td>
+  <td> pdf_info()->id2()     </td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>X1</td>
+  <td>fraction of beam momentum carried by first parton ("beam side") </td>
+  <td> pdf_info()->x1()</td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>X2</td>
+  <td>fraction of beam momentum carried by second parton ("target side") </td>
+  <td> pdf_info()->x2()</td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>ScalePDF</td>
+  <td>Q-scale used in evaluation of PDF's (in GeV) </td>
+  <td> pdf_info()->scalePDF()</td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>PDF1</td>
+  <td>PDF (id1, x1, Q) </td>
+  <td> pdf_info()->pdf1()</td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>PDF2</td>
+  <td>PDF (id2, x2, Q) </td>
+  <td> pdf_info()->pdf2()</td>
+</tr>
+<tr bgcolor="#ffffff"><td colspan=3><hr><a name="GenParticle"><H3>GenParticle</H3><hr></td></tr>
+<tr bgcolor="#eeeeee">
+  <td>PID</td>
+  <td>particle HEP ID number </td>
+  <td> hepevt.idhep[number]</td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Status</td>
+  <td>particle status </td>
+  <td> hepevt.isthep[number]</td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>IsPU</td>
+  <td>0 or 1 for particles from pile-up interactions</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>M1</td>
+  <td>particle 1st mother </td>
+  <td> hepevt.jmohep[number][0] - 1</td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>M2</td>
+  <td>particle 2nd mother </td>
+  <td> hepevt.jmohep[number][1] - 1</td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>D1</td>
+  <td>particle 1st daughter </td>
+  <td> hepevt.jdahep[number][0] - 1</td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>D2</td>
+  <td>particle last daughter </td>
+  <td> hepevt.jdahep[number][1] - 1</td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Charge</td>
+  <td>particle charge</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Mass</td>
+  <td>particle mass</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>E</td>
+  <td>particle energy </td>
+  <td> hepevt.phep[number][3]</td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Px</td>
+  <td>particle momentum vector (x component) </td>
+  <td> hepevt.phep[number][0]</td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Py</td>
+  <td>particle momentum vector (y component) </td>
+  <td> hepevt.phep[number][1]</td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Pz</td>
+  <td>particle momentum vector (z component) </td>
+  <td> hepevt.phep[number][2]</td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>PT</td>
+  <td>particle transverse momentum</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Eta</td>
+  <td>particle pseudorapidity</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Phi</td>
+  <td>particle azimuthal angle</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Rapidity</td>
+  <td>particle rapidity</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>T</td>
+  <td>particle vertex position (t component) </td>
+  <td> hepevt.vhep[number][3]</td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>X</td>
+  <td>particle vertex position (x component) </td>
+  <td> hepevt.vhep[number][0]</td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Y</td>
+  <td>particle vertex position (y component) </td>
+  <td> hepevt.vhep[number][1]</td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Z</td>
+  <td>particle vertex position (z component) </td>
+  <td> hepevt.vhep[number][2]</td>
+</tr>
+<tr bgcolor="#ffffff"><td colspan=3><hr><a name="MissingET"><H3>MissingET</H3><hr></td></tr>
+<tr bgcolor="#eeeeee">
+  <td>MET</td>
+  <td>mising transverse energy</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Phi</td>
+  <td>mising energy azimuthal angle</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff"><td colspan=3><hr><a name="ScalarHT"><H3>ScalarHT</H3><hr></td></tr>
+<tr bgcolor="#eeeeee">
+  <td>HT</td>
+  <td>scalar sum of transverse momenta</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff"><td colspan=3><hr><a name="Rho"><H3>Rho</H3><hr></td></tr>
+<tr bgcolor="#eeeeee">
+  <td>Rho</td>
+  <td>rho energy density</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff"><td colspan=3><hr><a name="Photon"><H3>Photon</H3><hr></td></tr>
+<tr bgcolor="#eeeeee">
+  <td>PT</td>
+  <td>photon transverse momentum</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Eta</td>
+  <td>photon pseudorapidity</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Phi</td>
+  <td>photon azimuthal angle</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>E</td>
+  <td>photon energy</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>EhadOverEem</td>
+  <td>ratio of the hadronic versus electromagnetic energy deposited in the calorimeter</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Particles</td>
+  <td>references to generated particles</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff"><td colspan=3><hr><a name="Electron"><H3>Electron</H3><hr></td></tr>
+<tr bgcolor="#eeeeee">
+  <td>PT</td>
+  <td>electron transverse momentum</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Eta</td>
+  <td>electron pseudorapidity</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Phi</td>
+  <td>electron azimuthal angle</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Charge</td>
+  <td>electron charge</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>EhadOverEem</td>
+  <td>ratio of the hadronic versus electromagnetic energy deposited in the calorimeter</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Particle</td>
+  <td>reference to generated particle</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff"><td colspan=3><hr><a name="Muon"><H3>Muon</H3><hr></td></tr>
+<tr bgcolor="#eeeeee">
+  <td>PT</td>
+  <td>muon transverse momentum</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Eta</td>
+  <td>muon pseudorapidity</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Phi</td>
+  <td>muon azimuthal angle</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Charge</td>
+  <td>muon charge</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Particle</td>
+  <td>reference to generated particle</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff"><td colspan=3><hr><a name="Jet"><H3>Jet</H3><hr></td></tr>
+<tr bgcolor="#eeeeee">
+  <td>PT</td>
+  <td>jet transverse momentum</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Eta</td>
+  <td>jet pseudorapidity</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Phi</td>
+  <td>jet azimuthal angle</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Mass</td>
+  <td>jet invariant mass</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>BTag</td>
+  <td>0 or 1 for a jet that has been tagged as containing a heavy quark</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>TauTag</td>
+  <td>0 or 1 for a jet that has been tagged as a tau</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Charge</td>
+  <td>tau charge</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>EhadOverEem</td>
+  <td>ratio of the hadronic versus electromagnetic energy deposited in the calorimeter</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Constituents</td>
+  <td>references to constituents</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Particles</td>
+  <td>references to generated particles</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff"><td colspan=3><hr><a name="Track"><H3>Track</H3><hr></td></tr>
+<tr bgcolor="#eeeeee">
+  <td>PID</td>
+  <td>HEP ID number</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Charge</td>
+  <td>track charge</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>PT</td>
+  <td>track transverse momentum</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Eta</td>
+  <td>track pseudorapidity</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Phi</td>
+  <td>track azimuthal angle</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>EtaOuter</td>
+  <td>track pseudorapidity at the tracker edge</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>PhiOuter</td>
+  <td>track azimuthal angle at the tracker edge</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>X</td>
+  <td>track vertex position (x component)</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Y</td>
+  <td>track vertex position (y component)</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Z</td>
+  <td>track vertex position (z component)</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>XOuter</td>
+  <td>track position (x component) at the tracker edge</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>YOuter</td>
+  <td>track position (y component) at the tracker edge</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>ZOuter</td>
+  <td>track position (z component) at the tracker edge</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Particle</td>
+  <td>reference to generated particle</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff"><td colspan=3><hr><a name="Tower"><H3>Tower</H3><hr></td></tr>
+<tr bgcolor="#eeeeee">
+  <td>ET</td>
+  <td>calorimeter tower transverse energy</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Eta</td>
+  <td>calorimeter tower pseudorapidity</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Phi</td>
+  <td>calorimeter tower azimuthal angle</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>E</td>
+  <td>calorimeter tower energy</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Eem</td>
+  <td>calorimeter tower electromagnetic energy</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Ehad</td>
+  <td>calorimeter tower hadronic energy</td>
+  <td></td>
+</tr>
+<tr bgcolor="#eeeeee">
+  <td>Edges[4]</td>
+  <td>calorimeter tower edges</td>
+  <td></td>
+</tr>
+<tr bgcolor="#ffffff">
+  <td>Particles</td>
+  <td>references to generated particles</td>
+  <td></td>
+</tr>
+</table>
+</body></html>
Index: trunk/Delphes/Delphes-3.0.9/doc/data_flow.sh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/doc/data_flow.sh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/doc/data_flow.sh	(revision 5)
@@ -0,0 +1,32 @@
+#! /bin/sh
+
+if [ $# -ne 1 ]
+then
+  echo " Usage: $0 config_file"
+  echo " config_file - configuration file in Tcl format."
+  exit
+fi
+
+awk '
+  BEGIN{
+    print "digraph G {"
+    print "rankdir=LR";
+  }
+  $1~/module/{
+    dst=$3
+  }
+  $2~/InputArray/{
+    split($3, src, "/");
+    if(src[1] == "Delphes") src[1] = "Reader";
+    print dst"[shape=box, style=rounded];";
+    print src[1]"->"dst" [label="src[2]"];"
+  }
+  $2~/Branch/{
+    split($3, src, "/");
+    if(src[1] == "Delphes") src[1] = "Reader";
+    print "\"Branch "$4"\" [shape=box, style=\"rounded,filled\", fillcolor=lightgrey];";
+    print src[1]"->\"Branch "$4"\" [label="src[2]"];";    
+  }
+  END{
+    print "}"
+  }' $1 | dot -Tpng > data_flow.png
Index: trunk/Delphes/Delphes-3.0.9/doc/doxygen.cfg
===================================================================
--- trunk/Delphes/Delphes-3.0.9/doc/doxygen.cfg	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/doc/doxygen.cfg	(revision 5)
@@ -0,0 +1,5 @@
+PROJECT_NAME = Delphes
+OUTPUT_DIRECTORY = doxygen
+WARNINGS = YES
+INPUT = classes modules readers
+FILE_PATTERNS = *.cc *.h *.cpp *.hpp
Index: trunk/Delphes/Delphes-3.0.9/doc/genMakefile.tcl
===================================================================
--- trunk/Delphes/Delphes-3.0.9/doc/genMakefile.tcl	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/doc/genMakefile.tcl	(revision 5)
@@ -0,0 +1,350 @@
+#!/usr/bin/env tclsh
+
+set prefix "tmp/"
+set suffix " \\\n\t"
+
+set srcSuf {.$(SrcSuf)}
+set objSuf {.$(ObjSuf)}
+set exeSuf {$(ExeSuf)}
+
+proc dependencies {fileName firstLine {force 1} {command {}}} {
+  global suffix headerFiles sourceFiles
+
+  if {[info exists sourceFiles($fileName)]} return
+
+  set sourceFiles($fileName) 1
+
+  set list {}
+  set fid [open $fileName]
+  while {! [eof $fid]} {
+    set line [gets $fid]
+    if [regexp -- {^\s*#include\s*"((\w+/)+\w+\.(h|hh))"} $line] {
+      set elements [split $line {"}]
+      set file [lindex $elements 1]
+      if [file exists $file] {
+        lappend list $file
+        set headerFiles($file) 1
+      } elseif [file exists external/$file] {
+        lappend list external/$file
+        set headerFiles(external/$file) 1
+	  }
+    }
+  }
+  
+  if {[llength $list] > 0} {
+    puts -nonewline $firstLine
+    foreach file $list {puts -nonewline $suffix$file}
+    if {$command != {}} {
+      puts ""
+      puts $command
+    }
+    puts ""
+  } elseif {$force} {
+    puts -nonewline $firstLine
+    if {$command != {}} {
+      puts ""
+      puts $command
+    }
+    puts ""
+  }
+
+  close $fid  
+}
+
+proc dictDeps {dictVar args} {
+
+  global prefix suffix srcSuf objSuf
+
+  set dict [eval glob -nocomplain $args]
+  
+  set dictSrcFiles {}
+  set dictObjFiles {}
+
+  foreach fileName $dict {
+    regsub {LinkDef\.h} $fileName {Dict} dictName
+    set dictName $prefix$dictName
+  
+    lappend dictSrcFiles $dictName$srcSuf
+    lappend dictObjFiles $dictName$objSuf
+  
+    dependencies $fileName "$dictName$srcSuf:$suffix$fileName"
+  }
+  
+  puts -nonewline "${dictVar} = $suffix"
+  puts [join $dictSrcFiles $suffix]
+  puts ""
+
+  puts -nonewline "${dictVar}_OBJ = $suffix"
+  puts [join $dictObjFiles $suffix]
+  puts ""
+
+}
+
+proc sourceDeps {srcPrefix args} {
+
+  global prefix suffix srcSuf objSuf
+  
+  set source [eval glob -nocomplain $args]
+    
+  set srcObjFiles {}
+  
+  foreach fileName $source {
+    regsub {\.cc} $fileName {} srcName
+    set srcObjName $prefix$srcName
+  
+    lappend srcObjFiles $srcObjName$objSuf
+  
+    dependencies $fileName "$srcObjName$objSuf:$suffix$srcName$srcSuf"
+  }
+
+  puts -nonewline "${srcPrefix}_OBJ = $suffix"
+  puts [join $srcObjFiles $suffix]
+  puts ""
+}
+
+proc tclDeps {} {
+
+  global prefix suffix srcSuf objSuf
+   
+  set source [glob -nocomplain {external/tcl/*.c}]
+  
+  set srcObjFiles {}
+  
+  foreach fileName $source {
+    if {$fileName == "tcl/tclc.c" || $fileName == "tcl/tcl.c"} continue
+ 
+    regsub {\.c} $fileName {} srcName
+    set srcObjName $prefix$srcName
+  
+    lappend srcObjFiles $srcObjName$objSuf
+  
+    dependencies $fileName "$srcObjName$objSuf:$suffix$fileName"
+  }
+  
+  puts -nonewline "TCL_OBJ = $suffix"
+  puts [join $srcObjFiles $suffix]
+  puts ""
+}
+
+proc executableDeps {} {
+
+  global prefix suffix objSuf exeSuf
+   
+  set executable [glob -nocomplain {readers/*.cpp} {converters/*.cpp}]
+  
+  set exeFiles {}
+  
+  foreach fileName $executable {
+    regsub {\.cpp} $fileName {} exeObjName
+    set exeObjName $prefix$exeObjName
+    set exeName [file tail $exeObjName]
+
+    lappend exeFiles $exeName$exeSuf
+    lappend exeObjFiles $exeObjName$objSuf
+    
+    puts "$exeName$exeSuf:$suffix$exeObjName$objSuf"
+    puts ""
+  
+    dependencies $fileName "$exeObjName$objSuf:$suffix$fileName"
+  }
+  
+  if [info exists exeFiles] {
+    puts -nonewline "EXECUTABLE = $suffix"
+    puts [join $exeFiles $suffix]
+    puts ""
+  }
+  if [info exists exeObjFiles] {
+    puts -nonewline "EXECUTABLE_OBJ = $suffix"
+    puts [join $exeObjFiles $suffix]
+    puts ""
+  }
+
+}
+
+proc headerDeps {} {
+  global suffix headerFiles
+    
+  foreach fileName [array names headerFiles] {
+    dependencies $fileName "$fileName:" 0 "\t@touch \$@"
+  }
+}
+
+puts {
+#
+# Makefile for ExRootAnalysis
+#
+# Author: P. Demin - UCL, Louvain-la-Neuve
+#
+# multi-platform configuration is taken from ROOT (root/test/Makefile.arch)
+#
+
+include doc/Makefile.arch
+
+ifeq ($(ARCH),macosx64)
+UNDEFOPT = dynamic_lookup
+endif
+
+SrcSuf = cc
+
+CXXFLAGS += $(ROOTCFLAGS) -Wno-write-strings -D_FILE_OFFSET_BITS=64 -DDROP_CGAL -I. -Iexternal -Iexternal/tcl
+DELPHES_LIBS = $(shell $(RC) --libs) -lEG $(SYSLIBS)
+DISPLAY_LIBS = $(shell $(RC) --evelibs) $(SYSLIBS)
+
+###
+
+DELPHES = libDelphes.$(DllSuf)
+DELPHESLIB = libDelphes.lib
+
+DISPLAY = libDelphesDisplay.$(DllSuf)
+DISPLAYLIB = libDelphesDisplay.lib
+
+VERSION = $(shell cat VERSION)
+DISTDIR = Delphes-$(VERSION)
+DISTTAR = $(DISTDIR).tar.gz
+
+all:
+
+}
+
+executableDeps
+
+dictDeps {DELPHES_DICT} {classes/*LinkDef.h} {modules/*LinkDef.h} {external/ExRootAnalysis/*LinkDef.h}
+
+dictDeps {DISPLAY_DICT} {display/*LinkDef.h}
+
+sourceDeps {DELPHES} {classes/*.cc} {modules/*.cc} {external/ExRootAnalysis/*.cc} {external/fastjet/*.cc} {external/fastjet/tools/*.cc} {external/fastjet/plugins/*/*.cc}
+
+sourceDeps {DISPLAY} {display/*.cc}
+
+tclDeps
+
+headerDeps
+
+puts {
+
+###
+
+all: $(DELPHES) $(EXECUTABLE)
+
+display: $(DISPLAY)
+
+$(DELPHES): $(DELPHES_DICT_OBJ) $(DELPHES_OBJ) $(TCL_OBJ)
+	@mkdir -p $(@D)
+	@echo ">> Building $@"
+ifeq ($(ARCH),aix5)
+	@$(MAKESHARED) $(OutPutOpt) $@ $(DELPHES_LIBS) -p 0 $^
+else
+ifeq ($(PLATFORM),macosx)
+# We need to make both the .dylib and the .so
+	@$(LD) $(SOFLAGS)$@ $(LDFLAGS) $^ $(OutPutOpt) $@ $(DELPHES_LIBS)
+ifneq ($(subst $(MACOSX_MINOR),,1234),1234)
+ifeq ($(MACOSX_MINOR),4)
+	@ln -sf $@ $(subst .$(DllSuf),.so,$@)
+endif
+endif
+else
+ifeq ($(PLATFORM),win32)
+	@bindexplib $* $^ > $*.def
+	@lib -nologo -MACHINE:IX86 $^ -def:$*.def $(OutPutOpt)$(DELPHESLIB)
+	@$(LD) $(SOFLAGS) $(LDFLAGS) $^ $*.exp $(DELPHES_LIBS) $(OutPutOpt)$@
+	@$(MT_DLL)
+else
+	@$(LD) $(SOFLAGS) $(LDFLAGS) $^ $(OutPutOpt) $@ $(DELPHES_LIBS)
+	@$(MT_DLL)
+endif
+endif
+endif
+
+$(DISPLAY): $(DELPHES_DICT_OBJ) $(DISPLAY_DICT_OBJ) $(DELPHES_OBJ) $(DISPLAY_OBJ) $(TCL_OBJ)
+	@mkdir -p $(@D)
+	@echo ">> Building $@"
+ifeq ($(ARCH),aix5)
+	@$(MAKESHARED) $(OutPutOpt) $@ $(DISPLAY_LIBS) -p 0 $^
+else
+ifeq ($(PLATFORM),macosx)
+# We need to make both the .dylib and the .so
+	@$(LD) $(SOFLAGS)$@ $(LDFLAGS) $^ $(OutPutOpt) $@ $(DISPLAY_LIBS)
+ifneq ($(subst $(MACOSX_MINOR),,1234),1234)
+ifeq ($(MACOSX_MINOR),4)
+	@ln -sf $@ $(subst .$(DllSuf),.so,$@)
+endif
+endif
+else
+ifeq ($(PLATFORM),win32)
+	@bindexplib $* $^ > $*.def
+	@lib -nologo -MACHINE:IX86 $^ -def:$*.def $(OutPutOpt)$(DISPLAYLIB)
+	@$(LD) $(SOFLAGS) $(LDFLAGS) $^ $*.exp $(DISPLAY_LIBS) $(OutPutOpt)$@
+	@$(MT_DLL)
+else
+	@$(LD) $(SOFLAGS) $(LDFLAGS) $^ $(OutPutOpt) $@ $(DISPLAY_LIBS)
+	@$(MT_DLL)
+endif
+endif
+endif
+
+clean:
+	@rm -f $(DELPHES_DICT_OBJ) $(DISPLAY_DICT_OBJ) $(DELPHES_OBJ) $(DISPLAY_OBJ) $(TCL_OBJ) core
+	@rm -rf tmp
+
+distclean: clean
+	@rm -f $(DELPHES) $(DELPHESLIB) $(DISPLAY) $(DISPLAYLIB) $(EXECUTABLE)
+
+dist:
+	@echo ">> Building $(DISTTAR)"
+	@mkdir -p $(DISTDIR)
+	@cp -a CREDITS README VERSION Makefile configure classes converters display doc examples external modules python readers $(DISTDIR)
+	@find $(DISTDIR) -depth -name .\* -exec rm -rf {} \;
+	@tar -czf $(DISTTAR) $(DISTDIR)
+	@rm -rf $(DISTDIR)
+
+###
+
+.SUFFIXES: .$(SrcSuf) .$(ObjSuf) .$(DllSuf)
+
+%Dict.$(SrcSuf):
+	@mkdir -p $(@D)
+	@echo ">> Generating $@"
+	@rootcint -f $@ -c -Iexternal $<
+	@echo "#define private public" > $@.arch
+	@echo "#define protected public" >> $@.arch
+	@mv $@ $@.base
+	@cat $@.arch $< $@.base > $@
+	@rm $@.arch $@.base
+
+$(DELPHES_OBJ): tmp/%.$(ObjSuf): %.$(SrcSuf)
+	@mkdir -p $(@D)
+	@echo ">> Compiling $<"
+	@$(CXX) $(CXXFLAGS) -c $< $(OutPutOpt)$@
+
+$(DISPLAY_OBJ): tmp/%.$(ObjSuf): %.$(SrcSuf)
+	@mkdir -p $(@D)
+	@echo ">> Compiling $<"
+	@$(CXX) $(CXXFLAGS) -c $< $(OutPutOpt)$@
+
+$(DELPHES_DICT_OBJ): %.$(ObjSuf): %.$(SrcSuf)
+	@mkdir -p $(@D)
+	@echo ">> Compiling $<"
+	@$(CXX) $(CXXFLAGS) -c $< $(OutPutOpt)$@
+
+$(DISPLAY_DICT_OBJ): %.$(ObjSuf): %.$(SrcSuf)
+	@mkdir -p $(@D)
+	@echo ">> Compiling $<"
+	@$(CXX) $(CXXFLAGS) -c $< $(OutPutOpt)$@
+
+$(TCL_OBJ): tmp/%.$(ObjSuf): %.c
+	@mkdir -p $(@D)
+	@echo ">> Compiling $<"
+	@gcc $(CXXFLAGS) -c $< $(OutPutOpt)$@
+
+$(EXECUTABLE_OBJ): tmp/%.$(ObjSuf): %.cpp
+	@mkdir -p $(@D)
+	@echo ">> Compiling $<"
+	@$(CXX) $(CXXFLAGS) -c $< $(OutPutOpt)$@
+
+$(EXECUTABLE): %$(ExeSuf): $(DELPHES_DICT_OBJ) $(DELPHES_OBJ) $(TCL_OBJ)
+	@echo ">> Building $@"
+	@$(LD) $(LDFLAGS) $^ $(DELPHES_LIBS) $(OutPutOpt)$@
+
+###
+
+}
Index: trunk/Delphes/Delphes-3.0.9/doc/replace_troot.sh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/doc/replace_troot.sh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/doc/replace_troot.sh	(revision 5)
@@ -0,0 +1,8 @@
+#! /bin/sh
+
+for file in `grep -l 'TRoot' *`
+do
+  echo $file
+  sed 's/TRoot/ExRoot/g' ${file} > ${file}.tmp
+  mv ${file}.tmp ${file}
+done
Index: trunk/Delphes/Delphes-3.0.9/doc/root_tree_html.sh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/doc/root_tree_html.sh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/doc/root_tree_html.sh	(revision 5)
@@ -0,0 +1,78 @@
+#! /bin/sh
+
+if [ $# -ne 1 ]
+then
+  echo " Usage: $0 output_file"
+  echo " output_file - output file in HTML format."
+  exit
+fi
+
+awk '
+  BEGIN {  
+    print "<html>"
+    
+    print "<head>"
+    print "  <meta HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=iso-8859-1\">"
+    print "  <meta NAME=\"keywords\" CONTENT=\"root, tree, ntuple, format, description\">"
+    print "  <title>root tree description</title>"
+    print "</head>"
+
+    print "<body>"
+    
+    print "<H1>root tree description</H1>"
+
+    print "<hr>"
+    print "<H2>Classes</H2>"
+    print "<hr>"
+
+    print "<table style=\"border: 1px dotted;\" align=\"center\" border=\"0\" cellpadding=\"7\" cellspacing=\"3\" widt=\"95%\">"
+    print "<tr><td><b>Parameter</b></td>"
+    print "<td><b>Definition</b></td>"
+    print "<td><b>How it was calculated</b></td></tr>"
+  }
+
+  function print_line(name, comment, even, end) {
+    if(name != ""){
+      if(even) print "<tr bgcolor=\"#eeeeee\">"
+      else print "<tr bgcolor=\"#ffffff\">"
+      print "  <td>"name"</td>"
+      split(comment, a, "|");
+      print "  <td>"a[1]"</td>"
+      print "  <td>"a[2]"</td>"
+      print "</tr>"
+    }
+  }
+
+  /^ *class /{
+    print_line(name, comment, even, 1);
+    even = 0;
+    name = "";
+    comment = "";
+    split($2, a, ":");
+    if(a[1] == "Candidate" || a[1] == "DelphesFactory;") next;
+    print "<tr bgcolor=\"#ffffff\"><td colspan=3><hr><a name=\""a[1]"\"><H3>"a[1]"</H3><hr></td></tr>"
+  }
+
+  /: public [^S]/{
+    if($4 == "TObject") next;
+    name = sprintf("<a href=\"#%s\">%s</a>", $4, $4);
+    split($2, a, ":");
+    comment = sprintf("%s inherits all %s parameters", a[1], $4);
+  }
+
+  /^ *[A-Za-z_]* [A-Za-z].*; \/\/ / {
+    print_line(name, comment, even, 0);
+    split($2, a, ";");
+    name = a[1];
+    split($0, a, "// ");
+    comment = a[2];
+    even = !even;
+  }
+
+  /^ +\/\/ /{split($0, a, "// "); comment = comment" "a[2]}
+  END {
+    print_line(name, comment, even, 1);
+    print "</table>"
+    print "</body></html>"
+  }' ../classes/DelphesClasses.h >> $1
+
Index: trunk/Delphes/Delphes-3.0.9/doc/root_tree_wiki.sh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/doc/root_tree_wiki.sh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/doc/root_tree_wiki.sh	(revision 5)
@@ -0,0 +1,47 @@
+#! /bin/sh
+
+awk '
+  BEGIN {  
+    print "||= Parameter =||= Definition =||= How it was calculated =||";
+  }
+
+  function print_line(name, comment, even, end) {
+    if(name != ""){
+      split(comment, a, "|");
+      print "|| "name" || "a[1]" || "a[2]" ||";
+    }
+  }
+
+  /^ *class /{
+    print_line(name, comment, even, 1);
+    even = 0;
+    name = "";
+    comment = "";
+    split($2, a, ":");
+    if(a[1] == "Candidate" || a[1] == "DelphesFactory;") next;
+    print "|| || || ||";
+    print "|||| class "a[1]" || ||"
+    print "|| || || ||"
+  }
+
+  /: public [^S]/{
+    if($4 == "TObject") next;
+    name = $4;
+    split($2, a, ":");
+    comment = sprintf("%s inherits all %s parameters", a[1], $4);
+  }
+
+  /^ *[A-Za-z_]* [A-Za-z].*; \/\/ / {
+    print_line(name, comment, even, 0);
+    split($2, a, ";");
+    name = a[1];
+    split($0, a, "// ");
+    comment = a[2];
+    even = !even;
+  }
+
+  /^ +\/\/ /{split($0, a, "// "); comment = comment" "a[2]}
+  END {
+    print_line(name, comment, even, 1);
+  }' ../classes/DelphesClasses.h
+
Index: trunk/Delphes/Delphes-3.0.9/doc/update_fastjet.sh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/doc/update_fastjet.sh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/doc/update_fastjet.sh	(revision 5)
@@ -0,0 +1,92 @@
+version=3.0.3
+
+#wget http://fastjet.fr/repo/fastjet-${version}.tar.gz
+
+tar -zxf fastjet-${version}.tar.gz
+mkdir -p fastjet/plugins
+mkdir -p fastjet/internal
+mkdir -p fastjet/tools
+
+cd fastjet-${version}
+./configure --enable-allcxxplugins
+cd -
+
+echo ${version} > fastjet/VERSION
+
+cd fastjet
+cp -a ../fastjet-${version}/AUTHORS .
+cp -a ../fastjet-${version}/COPYING .
+cp -a ../fastjet-${version}/src/*.cc .
+cp -a ../fastjet-${version}/include/fastjet/*.h .
+cp -a ../fastjet-${version}/include/fastjet/*.hh .
+cp -a ../fastjet-${version}/include/fastjet/internal/*.hh internal
+cp -a ../fastjet-${version}/include/fastjet/internal/*.icc internal
+cp -a ../fastjet-${version}/tools/*.cc tools
+cp -a ../fastjet-${version}/tools/fastjet/tools/*.hh tools
+cd -
+
+cd fastjet/plugins
+
+mkdir -p ATLASCone/fastjet
+cp -a ../../fastjet-${version}/plugins/ATLASCone/*.hh ATLASCone
+cp -a ../../fastjet-${version}/plugins/ATLASCone/*.cc ATLASCone
+cp -a ../../fastjet-${version}/plugins/ATLASCone/README ATLASCone
+cp -a ../../fastjet-${version}/plugins/ATLASCone/fastjet/*.hh ATLASCone/fastjet
+
+mkdir -p CDFCones/fastjet
+cp -a ../../fastjet-${version}/plugins/CDFCones/*.cc CDFCones
+cp -a ../../fastjet-${version}/plugins/CDFCones/CDFcode/*.hh CDFCones
+cp -a ../../fastjet-${version}/plugins/CDFCones/CDFcode/*.cc CDFCones
+cp -a ../../fastjet-${version}/plugins/CDFCones/fastjet/*.hh CDFCones/fastjet
+ 
+mkdir -p CMSIterativeCone/fastjet
+cp -a ../../fastjet-${version}/plugins/CMSIterativeCone/*.h CMSIterativeCone
+cp -a ../../fastjet-${version}/plugins/CMSIterativeCone/*.cc CMSIterativeCone
+cp -a ../../fastjet-${version}/plugins/CMSIterativeCone/README CMSIterativeCone
+cp -a ../../fastjet-${version}/plugins/CMSIterativeCone/fastjet/*.hh CMSIterativeCone/fastjet
+
+mkdir -p D0RunICone/fastjet
+cp -a ../../fastjet-${version}/plugins/D0RunICone/*.h D0RunICone
+cp -a ../../fastjet-${version}/plugins/D0RunICone/*.hpp D0RunICone
+cp -a ../../fastjet-${version}/plugins/D0RunICone/*.cc D0RunICone
+cp -a ../../fastjet-${version}/plugins/D0RunICone/fastjet/*.hh D0RunICone/fastjet
+
+mkdir -p D0RunIICone/fastjet
+cp -a ../../fastjet-${version}/plugins/D0RunIICone/*.h D0RunIICone
+cp -a ../../fastjet-${version}/plugins/D0RunIICone/*.hpp D0RunIICone
+cp -a ../../fastjet-${version}/plugins/D0RunIICone/*.cc D0RunIICone
+cp -a ../../fastjet-${version}/plugins/D0RunIICone/fastjet/*.hh D0RunIICone/fastjet
+
+mkdir -p EECambridge/fastjet
+cp -a ../../fastjet-${version}/plugins/EECambridge/*.cc EECambridge
+cp -a ../../fastjet-${version}/plugins/EECambridge/fastjet/*.hh EECambridge/fastjet
+
+mkdir -p GridJet/fastjet
+cp -a ../../fastjet-${version}/plugins/GridJet/*.cc GridJet
+cp -a ../../fastjet-${version}/plugins/GridJet/fastjet/*.hh GridJet/fastjet
+
+mkdir -p Jade/fastjet
+cp -a ../../fastjet-${version}/plugins/Jade/*.cc Jade
+cp -a ../../fastjet-${version}/plugins/Jade/fastjet/*.hh Jade/fastjet
+
+mkdir -p NestedDefs/fastjet
+cp -a ../../fastjet-${version}/plugins/NestedDefs/*.cc NestedDefs
+cp -a ../../fastjet-${version}/plugins/NestedDefs/fastjet/*.hh NestedDefs/fastjet
+
+cp -a ../../fastjet-${version}/plugins/README .
+
+mkdir -p SISCone/fastjet
+cp -a ../../fastjet-${version}/plugins/SISCone/SISConePlugin.cc SISCone
+cp -a ../../fastjet-${version}/plugins/SISCone/siscone/AUTHORS SISCone
+cp -a ../../fastjet-${version}/plugins/SISCone/siscone/COPYING SISCone
+cp -a ../../fastjet-${version}/plugins/SISCone/siscone/siscone/*.h SISCone
+cp -a ../../fastjet-${version}/plugins/SISCone/siscone/siscone/*.cpp SISCone
+cp -a ../../fastjet-${version}/plugins/SISCone/fastjet/*.hh SISCone/fastjet
+rename .cpp .cc SISCone/*.cpp
+
+
+mkdir -p TrackJet/fastjet
+cp -a ../../fastjet-${version}/plugins/TrackJet/*.cc TrackJet
+cp -a ../../fastjet-${version}/plugins/TrackJet/fastjet/*.hh TrackJet/fastjet
+
+cd -
Index: trunk/Delphes/Delphes-3.0.9/examples/DelphesBrowser.C
===================================================================
--- trunk/Delphes/Delphes-3.0.9/examples/DelphesBrowser.C	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/examples/DelphesBrowser.C	(revision 5)
@@ -0,0 +1,28 @@
+/*
+root -l examples/DelphesBrowser.C
+*/
+
+{
+  #include <stdexcept>
+  gSystem->Load("libDelphes");
+
+  TFile *outputFile = TFile::Open("test.root", "RECREATE");
+  ExRootTreeWriter *treeWriter = new ExRootTreeWriter(outputFile, "Delphes");
+
+  ExRootConfReader *confReader = new ExRootConfReader;
+  
+  Delphes *modularDelphes = new Delphes("Delphes");
+
+  TObjArray *allParticleOutputArray = modularDelphes->ExportArray("allParticles");
+  TObjArray *stableParticleOutputArray = modularDelphes->ExportArray("stableParticles");
+  TObjArray *partonOutputArray = modularDelphes->ExportArray("partons");
+
+  confReader->ReadFile("examples/delphes_card_CMS.tcl");
+
+  modularDelphes->SetConfReader(confReader);
+  modularDelphes->SetTreeWriter(treeWriter);
+
+  modularDelphes->InitTask();
+
+  TBrowser browser;
+}
Index: trunk/Delphes/Delphes-3.0.9/examples/DelphesCMSFWLite.cpp
===================================================================
--- trunk/Delphes/Delphes-3.0.9/examples/DelphesCMSFWLite.cpp	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/examples/DelphesCMSFWLite.cpp	(revision 5)
@@ -0,0 +1,232 @@
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+#include <memory>
+
+#include <map>
+
+#include <stdlib.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include "TROOT.h"
+#include "TApplication.h"
+
+#include "TFile.h"
+#include "TObjArray.h"
+#include "TStopwatch.h"
+#include "TDatabasePDG.h"
+#include "TParticlePDG.h"
+#include "TLorentzVector.h"
+
+#include "modules/Delphes.h"
+#include "classes/DelphesStream.h"
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+
+#include "ExRootAnalysis/ExRootTreeWriter.h"
+#include "ExRootAnalysis/ExRootTreeBranch.h"
+#include "ExRootAnalysis/ExRootProgressBar.h"
+
+#include "FWCore/FWLite/interface/AutoLibraryLoader.h"
+
+#include "DataFormats/FWLite/interface/Event.h"
+#include "DataFormats/FWLite/interface/Handle.h"
+#include "DataFormats/HepMCCandidate/interface/GenParticle.h"
+
+using namespace std;
+
+//---------------------------------------------------------------------------
+
+void ConvertInput(fwlite::Event &event, DelphesFactory *factory, TObjArray *allParticleOutputArray, TObjArray *stableParticleOutputArray, TObjArray *partonOutputArray)
+{
+  size_t i;
+  fwlite::Handle< vector< reco::GenParticle > > handleParticle;
+  handleParticle.getByLabel(event, "genParticles");
+
+  Candidate *candidate;
+  TDatabasePDG *pdg;
+  TParticlePDG *pdgParticle;
+  Int_t pdgCode;
+
+  Int_t pid, status;
+  Double_t px, py, pz, e;
+  Double_t x, y, z;
+
+  pdg = TDatabasePDG::Instance();
+
+  for(i = 0; i < handleParticle->size(); ++i)
+  {
+    const reco::GenParticle &particle = (*handleParticle)[i];
+
+     pid = particle.pdgId();
+     status = particle.status();
+     px = particle.px(), py = particle.py(), pz = particle.phi(), e = particle.energy();
+     x = particle.vx(), y = particle.vy(), z = particle.vz();
+
+    if(status == 1 || status == 2)
+    {
+      candidate = factory->NewCandidate();
+
+      candidate->PID = pid;
+      pdgCode = TMath::Abs(candidate->PID);
+
+      candidate->Status = status;
+
+      pdgParticle = pdg->GetParticle(pid);
+      candidate->Charge = pdgParticle ? Int_t(pdgParticle->Charge()/3.0) : -999;
+      candidate->Mass = pdgParticle ? pdgParticle->Mass() : -999.9;
+
+      candidate->Momentum.SetPxPyPzE(px, py, pz, e);
+
+      candidate->Position.SetXYZT(x, y, z, 0.0);
+
+      allParticleOutputArray->Add(candidate);
+
+      if(!pdgParticle) return;
+
+      if(status == 1)
+      {
+        stableParticleOutputArray->Add(candidate);
+      }
+      else if(pdgCode <= 5 || pdgCode == 21 || pdgCode == 15)
+      {
+        partonOutputArray->Add(candidate);
+      }
+    }
+  }
+}
+
+//---------------------------------------------------------------------------
+
+static bool interrupted = false;
+
+void SignalHandler(int sig)
+{
+  interrupted = true;
+}
+
+//---------------------------------------------------------------------------
+
+int main(int argc, char *argv[])
+{
+  char appName[] = "DelphesCMSFWLite";
+  stringstream message;
+  TFile *inputFile = 0;
+  TFile *outputFile = 0;
+  TStopwatch eventStopWatch;
+  ExRootTreeWriter *treeWriter = 0;
+  ExRootConfReader *confReader = 0;
+  Delphes *modularDelphes = 0;
+  DelphesFactory *factory = 0;
+  TObjArray *allParticleOutputArray = 0, *stableParticleOutputArray = 0, *partonOutputArray = 0;
+  Int_t i;
+  Long64_t entry, allEntries;
+
+  if(argc < 4)
+  {
+    cout << " Usage: " << appName << " config_file" << " output_file" << " input_file(s)" << endl;
+    cout << " config_file - configuration file in Tcl format," << endl;
+    cout << " output_file - output file in ROOT format," << endl;
+    cout << " input_file(s) - input file(s) in ROOT format." << endl;
+    return 1;
+  }
+
+  signal(SIGINT, SignalHandler);
+
+  gROOT->SetBatch();
+
+  int appargc = 1;
+  char *appargv[] = {appName};
+  TApplication app(appName, &appargc, appargv);
+
+  AutoLibraryLoader::enable();
+
+  try
+  {
+    outputFile = TFile::Open(argv[2], "CREATE");
+
+    if(outputFile == NULL)
+    {
+      message << "can't open " << argv[2] << endl;
+      throw runtime_error(message.str());
+    }
+
+    treeWriter = new ExRootTreeWriter(outputFile, "Delphes");
+
+    confReader = new ExRootConfReader;
+    confReader->ReadFile(argv[1]);
+
+    modularDelphes = new Delphes("Delphes");
+    modularDelphes->SetConfReader(confReader);
+    modularDelphes->SetTreeWriter(treeWriter);
+
+    factory = modularDelphes->GetFactory();
+    allParticleOutputArray = modularDelphes->ExportArray("allParticles");
+    stableParticleOutputArray = modularDelphes->ExportArray("stableParticles");
+    partonOutputArray = modularDelphes->ExportArray("partons");
+
+    modularDelphes->InitTask();
+
+    for(i = 3; i < argc && !interrupted; ++i)
+    {
+      cout << "** Reading " << argv[i] << endl;
+
+      inputFile = TFile::Open(argv[i]);
+
+      if(inputFile == NULL)
+      {
+        message << "can't open " << argv[i] << endl;
+        throw runtime_error(message.str());
+      }
+
+      fwlite::Event event(inputFile);
+
+      allEntries = event.size();
+
+      if(allEntries <= 0) continue;
+
+      ExRootProgressBar progressBar(allEntries - 1);
+
+      // Loop over all objects
+      entry = 0;
+      modularDelphes->Clear();
+      treeWriter->Clear();
+      for(event.toBegin(); !event.atEnd() && !interrupted; ++event)
+      {
+        ConvertInput(event, factory, allParticleOutputArray, stableParticleOutputArray, partonOutputArray);
+        modularDelphes->ProcessTask();
+
+        treeWriter->Fill();
+
+        modularDelphes->Clear();
+        treeWriter->Clear();
+
+        progressBar.Update(entry);
+        ++entry;
+      }
+      progressBar.Finish();
+
+      inputFile->Close();
+    }
+
+    modularDelphes->FinishTask();
+    treeWriter->Write();
+
+    cout << "** Exiting..." << endl;
+
+    delete modularDelphes;
+    delete confReader;
+    delete treeWriter;
+    delete outputFile;
+
+    return 0;
+  }
+  catch(runtime_error &e)
+  {
+    if(treeWriter) delete treeWriter;
+    if(outputFile) delete outputFile;
+    cerr << "** ERROR: " << e.what() << endl;
+    return 1;
+  }
+}
Index: trunk/Delphes/Delphes-3.0.9/examples/DelphesCMSFWLite.sh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/examples/DelphesCMSFWLite.sh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/examples/DelphesCMSFWLite.sh	(revision 5)
@@ -0,0 +1,7 @@
+
+INC="`echo -I$CMSSW_FWLITE_INCLUDE_PATH | sed 's/:/ -I/g'` -I$CMSSW_RELEASE_BASE/src"
+
+LIB="`echo -L$LD_LIBRARY_PATH | sed 's/include/lib/g; s/:/ -L/g'` `echo -L$CMSSW_FWLITE_INCLUDE_PATH | sed 's/include/lib/g; s/:/ -L/g'` -lFWCoreFWLite -lDataFormatsFWLite -lDataFormatsPatCandidates -lDataFormatsLuminosity -lCommonToolsUtils"
+
+g++ -std=c++0x -I. -Iexternal $INC `root-config --cflags --ldflags --libs` -L. -lDelphes $LIB -o DelphesCMSFWLite examples/DelphesCMSFWLite.cpp
+
Index: trunk/Delphes/Delphes-3.0.9/examples/EventDisplay.C
===================================================================
--- trunk/Delphes/Delphes-3.0.9/examples/EventDisplay.C	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/examples/EventDisplay.C	(revision 5)
@@ -0,0 +1,260 @@
+/*
+root -l examples/EventDisplay.C\(\"examples/delphes_card_CMS.tcl\",\"delphes_output.root\"\)
+ShowEvent(1);
+ShowEvent(2);
+*/
+
+//------------------------------------------------------------------------------
+
+// radius of the barrel, in m
+Double_t gRadius = 1.29;
+
+// half-length of the barrel, in m
+Double_t gHalfLength = 3.0;
+
+// magnetic field
+Double_t gBz = 3.8;
+
+TAxis *gEtaAxis = 0;
+TAxis *gPhiAxis = 0;
+
+//------------------------------------------------------------------------------
+
+#include <set>
+#include <vector>
+
+using namespace std;
+
+class ExRootTreeReader;
+class DelphesCaloData;
+class DelphesDisplay;
+
+TChain gChain("Delphes");
+
+ExRootTreeReader *gTreeReader = 0;
+
+TClonesArray *gBranchTower = 0;
+TClonesArray *gBranchTrack = 0;
+TClonesArray *gBranchJet = 0;
+
+DelphesCaloData *gCaloData = 0;
+TEveElementList *gJetList = 0;
+TEveTrackList *gTrackList = 0;
+
+DelphesDisplay *gDelphesDisplay = 0;
+
+//------------------------------------------------------------------------------
+
+void EventDisplay(const char *configFile, const char *inputFile)
+{
+  gSystem->Load("libDelphesDisplay");
+
+  TEveManager::Create(kTRUE, "IV");
+
+  ExRootConfParam param, paramEtaBins;
+  Long_t i, j, size, sizeEtaBins;
+  set< Double_t > etaSet;
+  set< Double_t >::iterator itEtaSet;
+
+  Double_t *etaBins;
+
+  ExRootConfReader *confReader = new ExRootConfReader;
+  confReader->ReadFile(configFile);
+
+  gRadius = confReader->GetDouble("ParticlePropagator::Radius", 1.0);
+  gHalfLength = confReader->GetDouble("ParticlePropagator::HalfLength", 3.0);
+  gBz = confReader->GetDouble("ParticlePropagator::Bz", 0.0);
+
+  // read eta and phi bins
+  param = confReader->GetParam("Calorimeter::EtaPhiBins");
+  size = param.GetSize();
+  etaSet.clear();
+  for(i = 0; i < size/2; ++i)
+  {
+    paramEtaBins = param[i*2];
+    sizeEtaBins = paramEtaBins.GetSize();
+
+    for(j = 0; j < sizeEtaBins; ++j)
+    {
+      etaSet.insert(paramEtaBins[j].GetDouble());
+    }
+  }
+
+  delete confReader;
+
+  etaBins = new Double_t[etaSet.size()];
+  i = 0;
+
+  for(itEtaSet = etaSet.begin(); itEtaSet != etaSet.end(); ++itEtaSet)
+  {
+    etaBins[i] = *itEtaSet;
+    ++i;
+  }
+
+  gEtaAxis = new TAxis(etaSet.size() - 1, etaBins);
+  gPhiAxis = new TAxis(72, -TMath::Pi(), TMath::Pi());
+
+  // Create chain of root trees
+  gChain.Add(inputFile);
+
+  // Create object of class ExRootTreeReader
+  gTreeReader = new ExRootTreeReader(&gChain);
+
+  // Get pointers to branches
+  gBranchTower = gTreeReader->UseBranch("Tower");
+  gBranchTrack = gTreeReader->UseBranch("Track");
+  gBranchJet = gTreeReader->UseBranch("Jet");
+
+  // data
+  gCaloData = new DelphesCaloData(2);
+  gCaloData->RefSliceInfo(0).Setup("ECAL", 0.1, kRed);
+  gCaloData->RefSliceInfo(1).Setup("HCAL", 0.1, kBlue);
+  gCaloData->SetEtaBins(gEtaAxis);
+  gCaloData->SetPhiBins(gPhiAxis);
+  gCaloData->IncDenyDestroy();
+
+  gJetList = new TEveElementList("Jets");
+  gEve->AddElement(gJetList);
+
+  gTrackList = new TEveTrackList("Tracks");
+  gTrackList->SetMainColor(kBlue);
+  gTrackList->SetMarkerColor(kRed);
+  gTrackList->SetMarkerStyle(kCircle);
+  gTrackList->SetMarkerSize(0.5);
+  gEve->AddElement(gTrackList);
+
+  TEveTrackPropagator *trkProp = gTrackList->GetPropagator();
+  trkProp->SetMagField(0.0, 0.0, -gBz);
+  trkProp->SetMaxR(gRadius*100.0);
+  trkProp->SetMaxZ(gHalfLength*100.0);
+
+  // viewers and scenes
+
+  TEveElementList *geometry = new TEveElementList("Geometry");
+
+  TEveGeoShape *barell = new TEveGeoShape("Barell");
+  barell->SetShape(new TGeoTube(gRadius*100.0 - 1, gRadius*100.0, gHalfLength*100.0));
+  barell->SetMainColor(kCyan);
+  barell->SetMainTransparency(80);
+  geometry->AddElement(barell);
+
+  TEveCalo3D *calo = new TEveCalo3D(gCaloData);
+  calo->SetBarrelRadius(gRadius*100.0);
+  calo->SetEndCapPos(gHalfLength*100.0);
+
+  gStyle->SetPalette(1, 0);
+  TEveCaloLego *lego = new TEveCaloLego(gCaloData);
+  lego->InitMainTrans();
+  lego->RefMainTrans().SetScale(TMath::TwoPi(), TMath::TwoPi(), TMath::Pi());
+  lego->SetAutoRebin(kFALSE);
+  lego->Set2DMode(TEveCaloLego::kValSizeOutline);
+
+  gDelphesDisplay = new DelphesDisplay;
+
+  gEve->AddGlobalElement(geometry);
+  gEve->AddGlobalElement(calo);
+
+  gDelphesDisplay->ImportGeomRPhi(geometry);
+  gDelphesDisplay->ImportCaloRPhi(calo);
+
+  gDelphesDisplay->ImportGeomRhoZ(geometry);
+  gDelphesDisplay->ImportCaloRhoZ(calo);
+
+  gDelphesDisplay->ImportCaloLego(lego);
+
+  gEve->Redraw3D(kTRUE);
+}
+
+//------------------------------------------------------------------------------
+
+void ShowEvent(Long64_t event)
+{
+  TIter itTower(gBranchTower);
+  TIter itTrack(gBranchTrack);
+  TIter itJet(gBranchJet);
+
+  Tower *tower;
+  Track *track;
+  Jet *jet;
+
+  TEveJetCone *eveJetCone;
+  TEveTrack *eveTrack;
+
+  Int_t counter;
+
+  TEveElement *currentEvent = gEve->GetCurrentEvent();
+
+  TEveTrackPropagator *trkProp = gTrackList->GetPropagator();
+
+  if(event >= gTreeReader->GetEntries()) return;
+
+  // Load selected branches with data from specified event
+  gTreeReader->ReadEntry(event);
+
+  gCaloData->ClearTowers();
+  gJetList->DestroyElements();
+  gTrackList->DestroyElements();
+
+  // Loop over all towers
+  itTower.Reset();
+  while((tower = (Tower *) itTower.Next()))
+  {
+    gCaloData->AddTower(tower->Edges[0], tower->Edges[1], tower->Edges[2], tower->Edges[3]);
+    gCaloData->FillSlice(0, tower->Eem);
+    gCaloData->FillSlice(1, tower->Ehad);
+  }
+  gCaloData->DataChanged();
+
+  // Loop over all tracks
+  itTrack.Reset();
+  counter = 0;
+  while((track = (Track *) itTrack.Next()))
+  {
+    TParticle pb(track->PID, 1, 0, 0, 0, 0,
+                 track->P4().Px(), track->P4().Py(),
+                 track->P4().Pz(), track->P4().E(),
+                 track->X, track->Y, track->Z, 0.0);
+
+    eveTrack = new TEveTrack(&pb, counter, trkProp);
+    eveTrack->SetName(Form("%s [%d]", pb.GetName(), counter++));
+    eveTrack->SetStdTitle();
+    eveTrack->SetAttLineAttMarker(gTrackList);
+
+    switch(TMath::Abs(track->PID))
+    {
+      case 11:
+        eveTrack->SetLineColor(kRed);
+        break;
+      case 13:
+        eveTrack->SetLineColor(kGreen);
+        break;
+      default:
+        eveTrack->SetLineColor(kBlue);
+    }
+    gTrackList->AddElement(eveTrack);
+    eveTrack->MakeTrack();
+  }
+
+  // Loop over all jets
+  itJet.Reset();
+  counter = 0;
+  while((jet = (Jet *) itJet.Next()))
+  {
+    eveJetCone = new TEveJetCone();
+    eveJetCone->SetName(Form("jet [%d]", counter++));
+    eveJetCone->SetMainTransparency(60);
+    eveJetCone->SetLineColor(kYellow);
+    eveJetCone->SetCylinder(gRadius*100.0 - 10, gHalfLength*100.0 - 10);
+    eveJetCone->SetPickable(kTRUE);
+    eveJetCone->AddEllipticCone(jet->Eta, jet->Phi, jet->DeltaEta, jet->DeltaPhi);
+    gJetList->AddElement(eveJetCone);
+  }
+
+  gDelphesDisplay->DestroyEventRPhi();
+  gDelphesDisplay->ImportEventRPhi(currentEvent);
+
+  gDelphesDisplay->DestroyEventRhoZ();
+  gDelphesDisplay->ImportEventRhoZ(currentEvent);
+
+  gEve->Redraw3D(kTRUE);
+}
Index: trunk/Delphes/Delphes-3.0.9/examples/Example1.C
===================================================================
--- trunk/Delphes/Delphes-3.0.9/examples/Example1.C	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/examples/Example1.C	(revision 5)
@@ -0,0 +1,63 @@
+/*
+root -l examples/Example1.C\(\"delphes_output.root\"\)
+*/
+
+//------------------------------------------------------------------------------
+
+void Example1(const char *inputFile)
+{
+  gSystem->Load("libDelphes");
+
+  // Create chain of root trees
+  TChain chain("Delphes");
+  chain.Add(inputFile);
+  
+  // Create object of class ExRootTreeReader
+  ExRootTreeReader *treeReader = new ExRootTreeReader(&chain);
+  Long64_t numberOfEntries = treeReader->GetEntries();
+  
+  // Get pointers to branches used in this analysis
+  TClonesArray *branchJet = treeReader->UseBranch("Jet");
+  TClonesArray *branchElectron = treeReader->UseBranch("Electron");
+  
+  // Book histograms
+  TH1 *histJetPT = new TH1F("jet_pt", "jet P_{T}", 100, 0.0, 100.0);
+  TH1 *histMass = new TH1F("mass", "M_{inv}(e_{1}, e_{2})", 100, 40.0, 140.0);
+
+  // Loop over all events
+  for(Int_t entry = 0; entry < numberOfEntries; ++entry)
+  {
+    // Load selected branches with data from specified event
+    treeReader->ReadEntry(entry);
+  
+    // If event contains at least 1 jet
+    if(branchJet->GetEntries() > 0)
+    {
+      // Take first jet
+      Jet *jet = (Jet*) branchJet->At(0);
+      
+      // Plot jet transverse momentum
+      histJetPT->Fill(jet->PT);
+      
+      // Print jet transverse momentum
+      cout << jet->PT << endl;
+    }
+
+    Electron *elec1, *elec2;
+
+    // If event contains at least 2 electrons
+    if(branchElectron->GetEntries() > 1)
+    {
+      // Take first two electrons
+      elec1 = (Electron *) branchElectron->At(0);
+      elec2 = (Electron *) branchElectron->At(1);
+
+      // Plot their invariant mass
+      histMass->Fill(((elec1->P4()) + (elec2->P4())).M());
+    }
+  }
+
+  // Show resulting histograms
+  histJetPT->Draw();
+  histMass->Draw();
+}
Index: trunk/Delphes/Delphes-3.0.9/examples/Example2.C
===================================================================
--- trunk/Delphes/Delphes-3.0.9/examples/Example2.C	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/examples/Example2.C	(revision 5)
@@ -0,0 +1,178 @@
+/*
+root -l examples/Example2.C\(\"delphes_output.root\"\)
+*/
+
+#include "TH1.h"
+#include "TSystem.h"
+
+//------------------------------------------------------------------------------
+
+struct MyPlots
+{
+  TH1 *fJetPT[2];
+  TH1 *fMissingET;
+  TH1 *fElectronPT;
+};
+
+//------------------------------------------------------------------------------
+
+class ExRootResult;
+class ExRootTreeReader;
+
+//------------------------------------------------------------------------------
+
+void BookHistograms(ExRootResult *result, MyPlots *plots)
+{
+  THStack *stack;
+  TLegend *legend;
+  TPaveText *comment;
+
+  // book 2 histograms for PT of 1st and 2nd leading jets
+
+  plots->fJetPT[0] = result->AddHist1D(
+    "jet_pt_0", "leading jet P_{T}",
+    "jet P_{T}, GeV/c", "number of jets",
+    50, 0.0, 100.0);
+
+  plots->fJetPT[1] = result->AddHist1D(
+    "jet_pt_1", "2nd leading jet P_{T}",
+    "jet P_{T}, GeV/c", "number of jets",
+    50, 0.0, 100.0);
+
+  plots->fJetPT[0]->SetLineColor(kRed);
+  plots->fJetPT[1]->SetLineColor(kBlue);
+
+  // book 1 stack of 2 histograms
+
+  stack = result->AddHistStack("jet_pt_all", "1st and 2nd jets P_{T}");
+  stack->Add(plots->fJetPT[0]);
+  stack->Add(plots->fJetPT[1]);
+
+  // book legend for stack of 2 histograms
+
+  legend = result->AddLegend(0.72, 0.86, 0.98, 0.98);
+  legend->AddEntry(plots->fJetPT[0], "leading jet", "l");
+  legend->AddEntry(plots->fJetPT[1], "second jet", "l");
+
+  // attach legend to stack (legend will be printed over stack in .eps file)
+
+  result->Attach(stack, legend);
+
+  // book more histograms
+
+  plots->fElectronPT = result->AddHist1D(
+    "electron_pt", "electron P_{T}",
+    "electron P_{T}, GeV/c", "number of electrons",
+    50, 0.0, 100.0);
+
+  plots->fMissingET = result->AddHist1D(
+    "missing_et", "Missing E_{T}",
+    "Missing E_{T}, GeV", "number of events",
+    60, 0.0, 30.0);
+
+  // book general comment
+
+  comment = result->AddComment(0.64, 0.86, 0.98, 0.98);
+  comment->AddText("demonstration plot");
+  comment->AddText("produced by Example2.C");
+
+  // attach comment to single histograms
+
+  result->Attach(plots->fJetPT[0], comment);
+  result->Attach(plots->fJetPT[1], comment);
+  result->Attach(plots->fElectronPT, comment);
+
+  // show histogram statisics for MissingET
+  plots->fMissingET->SetStats();
+}
+
+//------------------------------------------------------------------------------
+
+void AnalyseEvents(ExRootTreeReader *treeReader, MyPlots *plots)
+{
+  TClonesArray *branchJet = treeReader->UseBranch("Jet");
+  TClonesArray *branchElectron = treeReader->UseBranch("Electron");
+  TClonesArray *branchMissingET = treeReader->UseBranch("MissingET");
+
+  Long64_t allEntries = treeReader->GetEntries();
+
+  cout << "** Chain contains " << allEntries << " events" << endl;
+
+  Jet *jet[2];
+  MissingET *met;
+  Electron *electron;
+
+  Long64_t entry;
+
+  Int_t i;
+
+  // Loop over all events
+  for(entry = 0; entry < allEntries; ++entry)
+  {
+    // Load selected branches with data from specified event
+    treeReader->ReadEntry(entry);
+
+    // Analyse two leading jets
+    if(branchJet->GetEntriesFast() >= 2)
+    {
+      jet[0] = (Jet*) branchJet->At(0);
+      jet[1] = (Jet*) branchJet->At(1);
+
+      plots->fJetPT[0]->Fill(jet[0]->PT);
+      plots->fJetPT[1]->Fill(jet[1]->PT);
+    }
+
+    // Analyse missing ET
+    if(branchMissingET->GetEntriesFast() > 0)
+    {
+      met = (MissingET*) branchMissingET->At(0);
+      plots->fMissingET->Fill(met->MET);
+    }
+
+    // Loop over all electrons in event
+    for(i = 0; i < branchElectron->GetEntriesFast(); ++i)
+    {
+      electron = (Electron*) branchElectron->At(i);
+      plots->fElectronPT->Fill(electron->PT);
+    }
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void PrintHistograms(ExRootResult *result, MyPlots *plots)
+{
+  result->Print("png");
+}
+
+//------------------------------------------------------------------------------
+
+void Example2(const char *inputFile)
+{
+  gSystem->Load("libDelphes");
+
+  TChain *chain = new TChain("Delphes");
+  chain->Add(inputFile);
+
+  ExRootTreeReader *treeReader = new ExRootTreeReader(chain);
+  ExRootResult *result = new ExRootResult();
+
+  MyPlots *plots = new MyPlots;
+
+  BookHistograms(result, plots);
+
+  AnalyseEvents(treeReader, plots);
+
+  PrintHistograms(result, plots);
+
+  result->Write("results.root");
+
+  cout << "** Exiting..." << endl;
+
+  delete plots;
+  delete result;
+  delete treeReader;
+  delete chain;
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/examples/Example3.C
===================================================================
--- trunk/Delphes/Delphes-3.0.9/examples/Example3.C	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/examples/Example3.C	(revision 5)
@@ -0,0 +1,304 @@
+/*
+root -l examples/Example3.C\(\"delphes_output.root\"\)
+*/
+
+//------------------------------------------------------------------------------
+
+struct TestPlots
+{
+  TH1 *fElectronDeltaPT;
+  TH1 *fElectronDeltaEta;
+
+  TH1 *fPhotonDeltaPT;
+  TH1 *fPhotonDeltaEta;
+  TH1 *fPhotonDeltaE;
+
+  TH1 *fMuonDeltaPT;
+  TH1 *fMuonDeltaEta;
+
+  TH1 *fTrackDeltaPT;
+  TH1 *fTrackDeltaEta;
+
+  TH1 *fTowerDeltaEem;
+  TH1 *fTowerDeltaEhad;
+
+  TH1 *fJetDeltaPT;
+};
+
+//------------------------------------------------------------------------------
+
+class ExRootResult;
+class ExRootTreeReader;
+
+//------------------------------------------------------------------------------
+
+void BookHistograms(ExRootResult *result, TestPlots *plots)
+{
+  TLegend *legend;
+  TPaveText *comment;
+
+  plots->fElectronDeltaPT = result->AddHist1D(
+    "electron delta pt", "(p_{T}^{particle} - p_{T}^{electron})/p_{T}^{particle}",
+    "(p_{T}^{particle} - p_{T}^{electron})/p_{T}^{particle}", "number of electrons",
+    100, -0.1, 0.1);
+
+  plots->fElectronDeltaEta = result->AddHist1D(
+    "electron delta eta", "(#eta^{particle} - #eta^{electron})/#eta^{particle}",
+    "(#eta^{particle} - #eta^{electron})/#eta^{particle}", "number of electrons",
+    100, -0.1, 0.1);
+
+  plots->fPhotonDeltaPT = result->AddHist1D(
+    "photon delta pt", "(p_{T}^{particle} - p_{T}^{photon})/p_{T}^{particle}",
+    "(p_{T}^{particle} - p_{T}^{photon})/p_{T}^{particle}", "number of photons",
+    100, -0.1, 0.1);
+
+  plots->fPhotonDeltaEta = result->AddHist1D(
+    "photon delta eta", "(#eta^{particle} - #eta^{photon})/#eta^{particle}",
+    "(#eta^{particle} - #eta^{photon})/#eta^{particle}", "number of photons",
+    100, -0.1, 0.1);
+
+  plots->fPhotonDeltaE = result->AddHist1D(
+    "photon delta energy", "(E^{particle} - E^{photon})/E^{particle}",
+    "(E^{particle} - E^{photon})/E^{particle}", "number of photons",
+    100, -0.1, 0.1);
+
+  plots->fMuonDeltaPT = result->AddHist1D(
+    "muon delta pt", "(p_{T}^{particle} - p_{T}^{muon})/p_{T}^{particle}",
+    "(p_{T}^{particle} - p_{T}^{muon})/p_{T}^{particle}", "number of muons",
+    100, -0.1, 0.1);
+
+  plots->fMuonDeltaEta = result->AddHist1D(
+    "muon delta eta", "(#eta^{particle} - #eta^{muon})/#eta^{particle}",
+    "(#eta^{particle} - #eta^{muon})/#eta^{particle}", "number of muons",
+    100, -0.1, 0.1);
+
+  plots->fTrackDeltaPT = result->AddHist1D(
+    "track delta pt", "(p_{T}^{particle} - p_{T}^{track})/p_{T}^{particle}",
+    "(p_{T}^{particle} - p_{T}^{track})/p_{T}^{particle}", "number of tracks",
+    100, -0.1, 0.1);
+
+  plots->fTrackDeltaEta = result->AddHist1D(
+    "track delta eta", "(#eta^{particle} - #eta^{track})/#eta^{particle}",
+    "(#eta^{particle} - #eta^{track})/#eta^{particle}", "number of tracks",
+    100, -0.1, 0.1);
+
+  plots->fTowerDeltaEem = result->AddHist1D(
+    "tower delta Eem", "(Eem^{particles} - Eem^{tower})/Eem^{particles}",
+    "(Eem^{particles} - Eem^{tower})/Eem^{particles}", "number of tower",
+    100, -0.5, 0.5);
+
+  plots->fTowerDeltaEhad = result->AddHist1D(
+    "tower delta Ehad", "(Ehad^{particles} - Ehad^{tower})/Ehad^{particles}",
+    "(Ehad^{particles} - Ehad^{tower})/Ehad^{particles}", "number of tower",
+    100, -5.0, 5.0);
+
+  plots->fJetDeltaPT = result->AddHist1D(
+    "jet delta pt", "(p_{T}^{jet} - p_{T}^{constituents})/p_{T}^{jet}",
+    "(p_{T}^{jet} - p_{T}^{constituents})/p_{T}^{jet}", "number of jets",
+    100, -1.0e-7, 1.0e-7);
+
+}
+
+//------------------------------------------------------------------------------
+
+void AnalyseEvents(ExRootTreeReader *treeReader, TestPlots *plots)
+{
+  TClonesArray *branchParticle = treeReader->UseBranch("Particle");
+  TClonesArray *branchElectron = treeReader->UseBranch("Electron");
+  TClonesArray *branchPhoton = treeReader->UseBranch("Photon");
+  TClonesArray *branchMuon = treeReader->UseBranch("Muon");
+
+  TClonesArray *branchEFlowTrack = treeReader->UseBranch("EFlowTrack");
+  TClonesArray *branchEFlowTower = treeReader->UseBranch("EFlowTower");
+  TClonesArray *branchEFlowMuon = treeReader->UseBranch("EFlowMuon");
+  TClonesArray *branchJet = treeReader->UseBranch("Jet");
+
+  Long64_t allEntries = treeReader->GetEntries();
+
+  cout << "** Chain contains " << allEntries << " events" << endl;
+
+  GenParticle *particle;
+  Electron *electron;
+  Photon *photon;
+  Muon *muon;
+
+  Track *track;
+  Tower *tower;
+
+  Jet *jet;
+  TObject *object;
+
+  TLorentzVector momentum;
+
+  Float_t Eem, Ehad;
+  Bool_t skip;
+
+  Long64_t entry;
+
+  Int_t i, j, pdgCode;
+
+  // Loop over all events
+  for(entry = 0; entry < allEntries; ++entry)
+  {
+    // Load selected branches with data from specified event
+    treeReader->ReadEntry(entry);
+
+    // Loop over all electrons in event
+    for(i = 0; i < branchElectron->GetEntriesFast(); ++i)
+    {
+      electron = (Electron*) branchElectron->At(i);
+      particle = (GenParticle*) electron->Particle.GetObject();
+
+      plots->fElectronDeltaPT->Fill((particle->PT - electron->PT)/particle->PT);
+      plots->fElectronDeltaEta->Fill((particle->Eta - electron->Eta)/particle->Eta);
+    }
+
+    // Loop over all photons in event
+    for(i = 0; i < branchPhoton->GetEntriesFast(); ++i)
+    {
+      photon = (Photon*) branchPhoton->At(i);
+
+      // skip photons with references to multiple particles
+      if(photon->Particles.GetEntriesFast() != 1) continue;
+
+      particle = (GenParticle*) photon->Particles.At(0);
+
+      plots->fPhotonDeltaPT->Fill((particle->PT - photon->PT)/particle->PT);
+      plots->fPhotonDeltaEta->Fill((particle->Eta - photon->Eta)/particle->Eta);
+      plots->fPhotonDeltaE->Fill((particle->E - photon->E)/particle->E);
+    }
+
+    // Loop over all muons in event
+    for(i = 0; i < branchMuon->GetEntriesFast(); ++i)
+    {
+      muon = (Muon*) branchMuon->At(i);
+      particle = (GenParticle*) muon->Particle.GetObject();
+
+      plots->fMuonDeltaPT->Fill((particle->PT - muon->PT)/particle->PT);
+      plots->fMuonDeltaEta->Fill((particle->Eta - muon->Eta)/particle->Eta);
+    }
+
+    // Loop over all tracks in event
+    for(i = 0; i < branchEFlowTrack->GetEntriesFast(); ++i)
+    {
+      track = (Track*) branchEFlowTrack->At(i);
+      particle = (GenParticle*) track->Particle.GetObject();
+
+      plots->fTrackDeltaPT->Fill((particle->PT - track->PT)/particle->PT);
+      plots->fTrackDeltaEta->Fill((particle->Eta - track->Eta)/particle->Eta);
+    }
+
+    // Loop over all towers in event
+    for(i = 0; i < branchEFlowTower->GetEntriesFast(); ++i)
+    {
+      tower = (Tower*) branchEFlowTower->At(i);
+
+      Eem = 0.0;
+      Ehad = 0.0;
+      skip = kFALSE;
+      for(j = 0; j < tower->Particles.GetEntriesFast(); ++j)
+      {
+        particle = (GenParticle*) tower->Particles.At(j);
+        pdgCode = TMath::Abs(particle->PID);
+
+        // skip muons and neutrinos
+        if(pdgCode == 12 || pdgCode == 13 || pdgCode == 14 || pdgCode == 16)
+        {
+          continue;
+        }
+
+        // skip K0short and Lambda
+        if(pdgCode == 310 || pdgCode == 3122)
+        {
+          skip = kTRUE;
+        }
+
+        if(pdgCode == 11 || pdgCode == 22)
+        {
+          Eem += particle->E;
+        }
+        else
+        {
+          Ehad += particle->E;
+        }
+      }
+      if(skip) continue;
+      if(Eem > 0.0 && tower->Eem > 0.0) plots->fTowerDeltaEem->Fill((Eem - tower->Eem)/Eem);
+      if(Ehad > 0.0 && tower->Ehad > 0.0) plots->fTowerDeltaEhad->Fill((Ehad - tower->Ehad)/Ehad);
+    }
+
+    // Loop over all jets in event
+    for(i = 0; i < branchJet->GetEntriesFast(); ++i)
+    {
+      jet = (Jet*) branchJet->At(i);
+
+      momentum.SetPxPyPzE(0.0, 0.0, 0.0, 0.0);
+
+      // Loop over all jet's constituents
+      for(j = 0; j < jet->Constituents.GetEntriesFast(); ++j)
+      {
+        object = jet->Constituents.At(j);
+
+        // Check if the constituent is accessible
+        if(object == 0) continue;
+
+        if(object->IsA() == GenParticle::Class())
+        {
+          momentum += ((GenParticle*) object)->P4();
+        }
+        else if(object->IsA() == Track::Class())
+        {
+          momentum += ((Track*) object)->P4();
+        }
+        else if(object->IsA() == Tower::Class())
+        {
+          momentum += ((Tower*) object)->P4();
+        }
+        else if(object->IsA() == Muon::Class())
+        {
+          momentum += ((Muon*) object)->P4();
+        }
+      }
+      plots->fJetDeltaPT->Fill((jet->PT - momentum.Pt())/jet->PT );
+    }
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void PrintHistograms(ExRootResult *result, TestPlots *plots)
+{
+  result->Print("png");
+}
+
+//------------------------------------------------------------------------------
+
+void Example3(const char *inputFile)
+{
+  gSystem->Load("libDelphes");
+
+  TChain *chain = new TChain("Delphes");
+  chain->Add(inputFile);
+
+  ExRootTreeReader *treeReader = new ExRootTreeReader(chain);
+  ExRootResult *result = new ExRootResult();
+
+  TestPlots *plots = new TestPlots;
+
+  BookHistograms(result, plots);
+
+  AnalyseEvents(treeReader, plots);
+
+  PrintHistograms(result, plots);
+
+  result->Write("results.root");
+
+  cout << "** Exiting..." << endl;
+
+  delete plots;
+  delete result;
+  delete treeReader;
+  delete chain;
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/examples/ProcessingTime.C
===================================================================
--- trunk/Delphes/Delphes-3.0.9/examples/ProcessingTime.C	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/examples/ProcessingTime.C	(revision 5)
@@ -0,0 +1,32 @@
+/*
+root -l examples/ProcessingTime.C\(\"delphes_output.root\"\)
+*/
+
+//------------------------------------------------------------------------------
+
+TGraphErrors gr;
+
+//------------------------------------------------------------------------------
+
+void ProcessingTime(const char *inputFile)
+{
+  TChain *chain = new TChain("Delphes");
+  chain->Add(inputFile);
+
+  TH1F hist("time", "time", 50, 0, 0.01);
+  Int_t i;
+
+  for(i = 1; i < 8; ++i)
+  {
+    chain->Draw("Event.ProcTime >> time", TString::Format("Jet_size == %d", i+1));
+    gr.SetPoint(i, i+1, hist.GetMean()*1000);
+    gr.SetPointError(i, 0, hist.GetRMS()*1000);
+  }
+
+  gr.GetXaxis()->SetLimits(1.0, 9.0);
+  gr.GetXaxis()->SetTitle("number of jets");
+  gr.GetYaxis()->SetTitle("processing time per event, ms");
+  gr.SetMarkerStyle(kFullDotMedium);
+  gr.Draw("AP");
+}
+
Index: trunk/Delphes/Delphes-3.0.9/examples/converter_card.tcl
===================================================================
--- trunk/Delphes/Delphes-3.0.9/examples/converter_card.tcl	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/examples/converter_card.tcl	(revision 5)
@@ -0,0 +1,17 @@
+#######################################
+# Order of execution of various modules
+#######################################
+
+set ExecutionPath {
+  TreeWriter
+}
+
+##################
+# ROOT tree writer
+##################
+
+module TreeWriter TreeWriter {
+# add Branch InputArray BranchName BranchClass
+  add Branch Delphes/stableParticles Particle GenParticle
+}
+
Index: trunk/Delphes/Delphes-3.0.9/examples/delphes_card_ATLAS.tcl
===================================================================
--- trunk/Delphes/Delphes-3.0.9/examples/delphes_card_ATLAS.tcl	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/examples/delphes_card_ATLAS.tcl	(revision 5)
@@ -0,0 +1,555 @@
+#######################################
+# Order of execution of various modules
+#######################################
+
+set ExecutionPath {
+  ParticlePropagator
+
+  ChargedHadronTrackingEfficiency
+  ElectronTrackingEfficiency
+  MuonTrackingEfficiency
+
+  ChargedHadronMomentumSmearing
+  ElectronEnergySmearing
+  MuonMomentumSmearing
+
+  TrackMerger
+  Calorimeter
+  EFlowMerger
+
+  PhotonEfficiency
+  PhotonIsolation
+
+  ElectronEfficiency
+  ElectronIsolation
+
+  MuonEfficiency
+  MuonIsolation
+
+  MissingET
+
+  GenJetFinder
+  FastJetFinder
+
+  ConstituentFilter
+
+  BTagging
+  TauTagging
+
+  UniqueObjectFinder
+
+  ScalarHT
+
+  TreeWriter
+}
+
+#################################
+# Propagate particles in cylinder
+#################################
+
+module ParticlePropagator ParticlePropagator {
+  set InputArray Delphes/stableParticles
+
+  set OutputArray stableParticles
+  set ChargedHadronOutputArray chargedHadrons
+  set ElectronOutputArray electrons
+  set MuonOutputArray muons
+
+  # radius of the magnetic field coverage, in m
+  set Radius 1.15
+  # half-length of the magnetic field coverage, in m
+  set HalfLength 3.51
+
+  # magnetic field
+  set Bz 2.0
+}
+
+####################################
+# Charged hadron tracking efficiency
+####################################
+
+module Efficiency ChargedHadronTrackingEfficiency {
+  set InputArray ParticlePropagator/chargedHadrons
+  set OutputArray chargedHadrons
+
+  # add EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # tracking efficiency formula for charged hadrons
+  set EfficiencyFormula {                                                    (pt <= 0.1)   * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.70) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0)                  * (0.95) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.60) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0)                  * (0.85) + \
+                         (abs(eta) > 2.5)                                                  * (0.00)}
+}
+
+##############################
+# Electron tracking efficiency
+##############################
+
+module Efficiency ElectronTrackingEfficiency {
+  set InputArray ParticlePropagator/electrons
+  set OutputArray electrons
+
+  # set EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # tracking efficiency formula for electrons
+  set EfficiencyFormula {                                                    (pt <= 0.1)   * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.73) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0   && pt <= 1.0e2) * (0.95) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0e2)                * (0.99) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.50) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0   && pt <= 1.0e2) * (0.83) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0e2)                * (0.90) + \
+                         (abs(eta) > 2.5)                                                  * (0.00)}
+}
+
+##########################
+# Muon tracking efficiency
+##########################
+
+module Efficiency MuonTrackingEfficiency {
+  set InputArray ParticlePropagator/muons
+  set OutputArray muons
+
+  # set EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # tracking efficiency formula for muons
+  set EfficiencyFormula {                                                    (pt <= 0.1)   * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.75) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0)                  * (0.99) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.70) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0)                  * (0.98) + \
+                         (abs(eta) > 2.5)                                                  * (0.00)}
+}
+
+########################################
+# Momentum resolution for charged tracks
+########################################
+
+module MomentumSmearing ChargedHadronMomentumSmearing {
+  set InputArray ChargedHadronTrackingEfficiency/chargedHadrons
+  set OutputArray chargedHadrons
+
+  # set ResolutionFormula {resolution formula as a function of eta and pt}
+
+  # resolution formula for charged hadrons
+  set ResolutionFormula {                  (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.02) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0   && pt <= 1.0e1) * (0.01) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0e1 && pt <= 2.0e2) * (0.03) + \
+                                           (abs(eta) <= 1.5) * (pt > 2.0e2)                * (0.05) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.03) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0   && pt <= 1.0e1) * (0.02) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0e1 && pt <= 2.0e2) * (0.04) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 2.0e2)                * (0.05)}
+}
+
+#################################
+# Energy resolution for electrons
+#################################
+
+module EnergySmearing ElectronEnergySmearing {
+  set InputArray ElectronTrackingEfficiency/electrons
+  set OutputArray electrons
+
+  # set ResolutionFormula {resolution formula as a function of eta and energy}
+
+  set ResolutionFormula {                  (abs(eta) <= 2.5) * (energy > 0.1   && energy <= 2.5e1) * (energy*0.015) + \
+                                           (abs(eta) <= 2.5) * (energy > 2.5e1)                    * sqrt(energy^2*0.005^2 + energy*0.05^2 + 0.25^2) + \
+                         (abs(eta) > 2.5 && abs(eta) <= 3.0)                                       * sqrt(energy^2*0.005^2 + energy*0.05^2 + 0.25^2) + \
+                         (abs(eta) > 3.0 && abs(eta) <= 5.0)                                       * sqrt(energy^2*0.107^2 + energy*2.08^2)}
+
+}
+
+###############################
+# Momentum resolution for muons
+###############################
+
+module MomentumSmearing MuonMomentumSmearing {
+  set InputArray MuonTrackingEfficiency/muons
+  set OutputArray muons
+
+  # set ResolutionFormula {resolution formula as a function of eta and pt}
+
+  # resolution formula for muons
+  set ResolutionFormula {                  (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.03) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0   && pt <= 1.0e1) * (0.02) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0e1 && pt <= 2.0e2) * (0.03) + \
+                                           (abs(eta) <= 1.5) * (pt > 2.0e2)                * (0.05) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.04) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0   && pt <= 1.0e1) * (0.03) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0e1 && pt <= 2.0e2) * (0.04) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 2.0e2)                * (0.05)}
+}
+
+##############
+# Track merger
+##############
+
+module Merger TrackMerger {
+# add InputArray InputArray
+  add InputArray ChargedHadronMomentumSmearing/chargedHadrons
+  add InputArray ElectronEnergySmearing/electrons
+  set OutputArray tracks
+}
+
+#############
+# Calorimeter
+#############
+
+module Calorimeter Calorimeter {
+  set ParticleInputArray ParticlePropagator/stableParticles
+  set TrackInputArray TrackMerger/tracks
+
+  set TowerOutputArray towers
+  set PhotonOutputArray photons
+
+  set EFlowTrackOutputArray eflowTracks
+  set EFlowTowerOutputArray eflowTowers
+
+  set pi [expr {acos(-1)}]
+
+  # lists of the edges of each tower in eta and phi
+  # each list starts with the lower edge of the first tower
+  # the list ends with the higher edged of the last tower
+
+  # 10 degrees towers
+  set PhiBins {}
+  for {set i -18} {$i <= 18} {incr i} {
+    add PhiBins [expr {$i * $pi/18.0}]
+  }
+  foreach eta {-3.2 -2.5 -2.4 -2.3 -2.2 -2.1 -2 -1.9 -1.8 -1.7 -1.6 -1.5 -1.4 -1.3 -1.2 -1.1 -1 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2 2.1 2.2 2.3 2.4 2.5 2.6 3.3} {
+    add EtaPhiBins $eta $PhiBins
+  }
+
+  # 20 degrees towers
+  set PhiBins {}
+  for {set i -9} {$i <= 9} {incr i} {
+    add PhiBins [expr {$i * $pi/9.0}]
+  }
+  foreach eta {-4.9 -4.7 -4.5 -4.3 -4.1 -3.9 -3.7 -3.5 -3.3 -3 -2.8 -2.6 2.8 3 3.2 3.5 3.7 3.9 4.1 4.3 4.5 4.7 4.9} {
+    add EtaPhiBins $eta $PhiBins
+  }
+
+  # default energy fractions {abs(PDG code)} {Fecal Fhcal}
+  add EnergyFraction {0} {0.0 1.0}
+  # energy fractions for e, gamma and pi0
+  add EnergyFraction {11} {1.0 0.0}
+  add EnergyFraction {22} {1.0 0.0}
+  add EnergyFraction {111} {1.0 0.0}
+  # energy fractions for muon, neutrinos and neutralinos
+  add EnergyFraction {12} {0.0 0.0}
+  add EnergyFraction {13} {0.0 0.0}
+  add EnergyFraction {14} {0.0 0.0}
+  add EnergyFraction {16} {0.0 0.0}
+  add EnergyFraction {1000022} {0.0 0.0}
+  add EnergyFraction {1000023} {0.0 0.0}
+  add EnergyFraction {1000025} {0.0 0.0}
+  add EnergyFraction {1000035} {0.0 0.0}
+  add EnergyFraction {1000045} {0.0 0.0}
+  # energy fractions for K0short and Lambda
+  add EnergyFraction {310} {0.3 0.7}
+  add EnergyFraction {3122} {0.3 0.7}
+
+  # set ECalResolutionFormula {resolution formula as a function of eta and energy}
+  # http://arxiv.org/pdf/physics/0608012v1 jinst8_08_s08003
+  # http://villaolmo.mib.infn.it/ICATPP9th_2005/Calorimetry/Schram.p.pdf
+  # http://www.physics.utoronto.ca/~krieger/procs/ComoProceedings.pdf
+  set ECalResolutionFormula {                  (abs(eta) <= 3.2) * sqrt(energy^2*0.0017^2 + energy*0.101^2) + \
+                             (abs(eta) > 3.2 && abs(eta) <= 4.9) * sqrt(energy^2*0.0350^2 + energy*0.285^2)}
+
+  # set HCalResolutionFormula {resolution formula as a function of eta and energy}
+  # http://arxiv.org/pdf/hep-ex/0004009v1
+  # http://villaolmo.mib.infn.it/ICATPP9th_2005/Calorimetry/Schram.p.pdf
+  set HCalResolutionFormula {                  (abs(eta) <= 1.7) * sqrt(energy^2*0.0302^2 + energy*0.5205^2 + 1.59^2) + \
+                             (abs(eta) > 1.7 && abs(eta) <= 3.2) * sqrt(energy^2*0.0500^2 + energy*0.706^2) + \
+                             (abs(eta) > 3.2 && abs(eta) <= 4.9) * sqrt(energy^2*0.9420^2 + energy*0.075^2)}
+}
+
+####################
+# Energy flow merger
+####################
+
+module Merger EFlowMerger {
+# add InputArray InputArray
+  add InputArray Calorimeter/eflowTracks
+  add InputArray Calorimeter/eflowTowers
+  add InputArray MuonMomentumSmearing/muons
+  set OutputArray eflow
+}
+
+###################
+# Photon efficiency
+###################
+
+module Efficiency PhotonEfficiency {
+  set InputArray Calorimeter/photons
+  set OutputArray photons
+
+  # set EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # efficiency formula for photons
+  set EfficiencyFormula {                                      (pt <= 10.0) * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 10.0)  * (0.95) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 10.0)  * (0.85) + \
+                         (abs(eta) > 2.5)                                   * (0.00)}
+}
+
+##################
+# Photon isolation
+##################
+
+module Isolation PhotonIsolation {
+  set CandidateInputArray PhotonEfficiency/photons
+  set IsolationInputArray EFlowMerger/eflow
+
+  set OutputArray photons
+
+  set DeltaRMax 0.5
+
+  set PTMin 0.5
+
+  set PTRatioMax 0.1
+}
+
+#####################
+# Electron efficiency
+#####################
+
+module Efficiency ElectronEfficiency {
+  set InputArray ElectronEnergySmearing/electrons
+  set OutputArray electrons
+
+  # set EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # efficiency formula for electrons
+  set EfficiencyFormula {                                      (pt <= 10.0) * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 10.0)  * (0.95) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 10.0)  * (0.85) + \
+                         (abs(eta) > 2.5)                                   * (0.00)}
+}
+
+####################
+# Electron isolation
+####################
+
+module Isolation ElectronIsolation {
+  set CandidateInputArray ElectronEfficiency/electrons
+  set IsolationInputArray EFlowMerger/eflow
+
+  set OutputArray electrons
+
+  set DeltaRMax 0.5
+
+  set PTMin 0.5
+
+  set PTRatioMax 0.1
+}
+
+#################
+# Muon efficiency
+#################
+
+module Efficiency MuonEfficiency {
+  set InputArray MuonMomentumSmearing/muons
+  set OutputArray muons
+
+  # set EfficiencyFormula {efficiency as a function of eta and pt}
+
+  # efficiency formula for muons
+  set EfficiencyFormula {                                      (pt <= 10.0) * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 10.0)  * (0.95) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.7) * (pt > 10.0)  * (0.85) + \
+                         (abs(eta) > 2.7)                                   * (0.00)}
+}
+
+################
+# Muon isolation
+################
+
+module Isolation MuonIsolation {
+  set CandidateInputArray MuonEfficiency/muons
+  set IsolationInputArray EFlowMerger/eflow
+
+  set OutputArray muons
+
+  set DeltaRMax 0.5
+
+  set PTMin 0.5
+
+  set PTRatioMax 0.1
+}
+
+###################
+# Missing ET merger
+###################
+
+module Merger MissingET {
+# add InputArray InputArray
+  add InputArray EFlowMerger/eflow
+  set MomentumOutputArray momentum
+}
+
+##################
+# Scalar HT merger
+##################
+
+module Merger ScalarHT {
+# add InputArray InputArray
+  add InputArray UniqueObjectFinder/jets
+  add InputArray UniqueObjectFinder/electrons
+  add InputArray UniqueObjectFinder/photons
+  add InputArray MuonIsolation/muons
+  set EnergyOutputArray energy
+}
+
+#####################
+# MC truth jet finder
+#####################
+
+module FastJetFinder GenJetFinder {
+  set InputArray Delphes/stableParticles
+
+  set OutputArray jets
+
+  # algorithm: 1 CDFJetClu, 2 MidPoint, 3 SIScone, 4 kt, 5 Cambridge/Aachen, 6 antikt
+  set JetAlgorithm 6
+  set ParameterR 0.7
+
+  set ConeRadius 0.5
+  set SeedThreshold 1.0
+  set ConeAreaFraction 1.0
+  set AdjacencyCut 2.0
+  set OverlapThreshold 0.75
+
+  set MaxIterations 100
+  set MaxPairSize 2
+  set Iratch 1
+
+  set JetPTMin 20.0
+}
+
+############
+# Jet finder
+############
+
+module FastJetFinder FastJetFinder {
+#  set InputArray Calorimeter/towers
+  set InputArray EFlowMerger/eflow
+
+  set OutputArray jets
+
+  # algorithm: 1 CDFJetClu, 2 MidPoint, 3 SIScone, 4 kt, 5 Cambridge/Aachen, 6 antikt
+  set JetAlgorithm 6
+  set ParameterR 0.7
+
+  set ConeRadius 0.5
+  set SeedThreshold 1.0
+  set ConeAreaFraction 1.0
+  set AdjacencyCut 2.0
+  set OverlapThreshold 0.75
+
+  set MaxIterations 100
+  set MaxPairSize 2
+  set Iratch 1
+
+  set JetPTMin 20.0
+}
+
+####################
+# Constituent filter
+####################
+
+module ConstituentFilter ConstituentFilter {
+
+# add JetInputArray InputArray
+  add JetInputArray GenJetFinder/jets
+  add JetInputArray FastJetFinder/jets
+
+# add ConstituentInputArray InputArray OutputArray
+  add ConstituentInputArray Delphes/stableParticles stableParticles
+  add ConstituentInputArray Calorimeter/eflowTracks eflowTracks
+  add ConstituentInputArray Calorimeter/eflowTowers eflowTowers
+  add ConstituentInputArray MuonMomentumSmearing/muons muons
+}
+
+###########
+# b-tagging
+###########
+
+module BTagging BTagging {
+  set PartonInputArray Delphes/partons
+  set JetInputArray FastJetFinder/jets
+
+  set BitNumber 0
+
+  set DeltaR 0.5
+
+  set PartonPTMin 1.0
+
+  set PartonEtaMax 2.5
+
+  # add EfficiencyFormula {abs(PDG code)} {efficiency formula as a function of eta and pt}
+  # PDG code = the highest PDG code of a quark or gluon inside DeltaR cone around jet axis
+  # gluon's PDG code has the lowest priority
+
+  # default efficiency formula (misidentification rate)
+  add EfficiencyFormula {0} {0.001}
+  # efficiency formula for c-jets (misidentification rate)
+  add EfficiencyFormula {4} {0.1}
+  # efficiency formula for b-jets
+  add EfficiencyFormula {5} {0.4}
+}
+
+module TauTagging TauTagging {
+  set ParticleInputArray Delphes/allParticles
+  set PartonInputArray Delphes/partons
+  set JetInputArray FastJetFinder/jets
+
+  set DeltaR 0.5
+
+  set TauPTMin 1.0
+
+  set TauEtaMax 2.5
+
+  # add EfficiencyFormula {abs(PDG code)} {efficiency formula as a function of eta and pt}
+
+  # default efficiency formula (misidentification rate)
+  add EfficiencyFormula {0} {0.001}
+  # efficiency formula for tau-jets
+  add EfficiencyFormula {15} {0.4}
+}
+
+#####################################################
+# Find uniquely identified photons/electrons/tau/jets
+#####################################################
+
+module UniqueObjectFinder UniqueObjectFinder {
+# earlier arrays take precedence over later ones
+# add InputArray InputArray OutputArray
+  add InputArray PhotonIsolation/photons photons
+  add InputArray ElectronIsolation/electrons electrons
+  add InputArray FastJetFinder/jets jets
+}
+
+##################
+# ROOT tree writer
+##################
+
+module TreeWriter TreeWriter {
+# add Branch InputArray BranchName BranchClass
+  add Branch Delphes/allParticles Particle GenParticle
+  add Branch TrackMerger/tracks Track Track
+  add Branch Calorimeter/towers Tower Tower
+  add Branch ConstituentFilter/eflowTracks EFlowTrack Track
+  add Branch ConstituentFilter/eflowTowers EFlowTower Tower
+  add Branch ConstituentFilter/muons EFlowMuon Muon
+  add Branch GenJetFinder/jets GenJet Jet
+  add Branch UniqueObjectFinder/jets Jet Jet
+  add Branch UniqueObjectFinder/electrons Electron Electron
+  add Branch UniqueObjectFinder/photons Photon Photon
+  add Branch MuonIsolation/muons Muon Muon
+  add Branch MissingET/momentum MissingET MissingET
+  add Branch ScalarHT/energy ScalarHT ScalarHT
+}
+
Index: trunk/Delphes/Delphes-3.0.9/examples/delphes_card_CMS.tcl
===================================================================
--- trunk/Delphes/Delphes-3.0.9/examples/delphes_card_CMS.tcl	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/examples/delphes_card_CMS.tcl	(revision 5)
@@ -0,0 +1,567 @@
+#######################################
+# Order of execution of various modules
+#######################################
+
+set ExecutionPath {
+  ParticlePropagator
+
+  ChargedHadronTrackingEfficiency
+  ElectronTrackingEfficiency
+  MuonTrackingEfficiency
+
+  ChargedHadronMomentumSmearing
+  ElectronEnergySmearing
+  MuonMomentumSmearing
+
+  TrackMerger
+  Calorimeter
+  EFlowMerger
+
+  PhotonEfficiency
+  PhotonIsolation
+
+  ElectronEfficiency
+  ElectronIsolation
+
+  MuonEfficiency
+  MuonIsolation
+
+  MissingET
+
+  GenJetFinder
+  FastJetFinder
+
+  ConstituentFilter
+
+  BTagging
+  TauTagging
+
+  UniqueObjectFinder
+
+  ScalarHT
+
+  TreeWriter
+}
+
+#################################
+# Propagate particles in cylinder
+#################################
+
+module ParticlePropagator ParticlePropagator {
+  set InputArray Delphes/stableParticles
+
+  set OutputArray stableParticles
+  set ChargedHadronOutputArray chargedHadrons
+  set ElectronOutputArray electrons
+  set MuonOutputArray muons
+
+  # radius of the magnetic field coverage, in m
+  set Radius 1.29
+  # half-length of the magnetic field coverage, in m
+  set HalfLength 3.00
+
+  # magnetic field
+  set Bz 3.8
+}
+
+####################################
+# Charged hadron tracking efficiency
+####################################
+
+module Efficiency ChargedHadronTrackingEfficiency {
+  set InputArray ParticlePropagator/chargedHadrons
+  set OutputArray chargedHadrons
+
+  # add EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # tracking efficiency formula for charged hadrons
+  set EfficiencyFormula {                                                    (pt <= 0.1)   * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.70) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0)                  * (0.95) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.60) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0)                  * (0.85) + \
+                         (abs(eta) > 2.5)                                                  * (0.00)}
+}
+
+##############################
+# Electron tracking efficiency
+##############################
+
+module Efficiency ElectronTrackingEfficiency {
+  set InputArray ParticlePropagator/electrons
+  set OutputArray electrons
+
+  # set EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # tracking efficiency formula for electrons
+  set EfficiencyFormula {                                                    (pt <= 0.1)   * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.73) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0   && pt <= 1.0e2) * (0.95) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0e2)                * (0.99) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.50) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0   && pt <= 1.0e2) * (0.83) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0e2)                * (0.90) + \
+                         (abs(eta) > 2.5)                                                  * (0.00)}
+}
+
+##########################
+# Muon tracking efficiency
+##########################
+
+module Efficiency MuonTrackingEfficiency {
+  set InputArray ParticlePropagator/muons
+  set OutputArray muons
+
+  # set EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # tracking efficiency formula for muons
+  set EfficiencyFormula {                                                    (pt <= 0.1)   * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.75) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0)                  * (0.99) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.70) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0)                  * (0.98) + \
+                         (abs(eta) > 2.5)                                                  * (0.00)}
+}
+
+########################################
+# Momentum resolution for charged tracks
+########################################
+
+module MomentumSmearing ChargedHadronMomentumSmearing {
+  set InputArray ChargedHadronTrackingEfficiency/chargedHadrons
+  set OutputArray chargedHadrons
+
+  # set ResolutionFormula {resolution formula as a function of eta and pt}
+
+  # resolution formula for charged hadrons
+  set ResolutionFormula {                  (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.02) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0   && pt <= 1.0e1) * (0.01) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0e1 && pt <= 2.0e2) * (0.03) + \
+                                           (abs(eta) <= 1.5) * (pt > 2.0e2)                * (0.05) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.03) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0   && pt <= 1.0e1) * (0.02) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0e1 && pt <= 2.0e2) * (0.04) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 2.0e2)                * (0.05)}
+}
+
+#################################
+# Energy resolution for electrons
+#################################
+
+module EnergySmearing ElectronEnergySmearing {
+  set InputArray ElectronTrackingEfficiency/electrons
+  set OutputArray electrons
+
+  # set ResolutionFormula {resolution formula as a function of eta and energy}
+
+  set ResolutionFormula {                  (abs(eta) <= 2.5) * (energy > 0.1   && energy <= 2.5e1) * (energy*0.015) + \
+                                           (abs(eta) <= 2.5) * (energy > 2.5e1)                    * sqrt(energy^2*0.005^2 + energy*0.05^2 + 0.25^2) + \
+                         (abs(eta) > 2.5 && abs(eta) <= 3.0)                                       * sqrt(energy^2*0.005^2 + energy*0.05^2 + 0.25^2) + \
+                         (abs(eta) > 3.0 && abs(eta) <= 5.0)                                       * sqrt(energy^2*0.107^2 + energy*2.08^2)}
+
+}
+
+###############################
+# Momentum resolution for muons
+###############################
+
+module MomentumSmearing MuonMomentumSmearing {
+  set InputArray MuonTrackingEfficiency/muons
+  set OutputArray muons
+
+  # set ResolutionFormula {resolution formula as a function of eta and pt}
+
+  # resolution formula for muons
+  set ResolutionFormula {                  (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.03) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0   && pt <= 1.0e1) * (0.02) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0e1 && pt <= 2.0e2) * (0.03) + \
+                                           (abs(eta) <= 1.5) * (pt > 2.0e2)                * (0.05) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.04) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0   && pt <= 1.0e1) * (0.03) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0e1 && pt <= 2.0e2) * (0.04) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 2.0e2)                * (0.05)}
+}
+
+##############
+# Track merger
+##############
+
+module Merger TrackMerger {
+# add InputArray InputArray
+  add InputArray ChargedHadronMomentumSmearing/chargedHadrons
+  add InputArray ElectronEnergySmearing/electrons
+  set OutputArray tracks
+}
+
+#############
+# Calorimeter
+#############
+
+module Calorimeter Calorimeter {
+  set ParticleInputArray ParticlePropagator/stableParticles
+  set TrackInputArray TrackMerger/tracks
+
+  set TowerOutputArray towers
+  set PhotonOutputArray photons
+
+  set EFlowTrackOutputArray eflowTracks
+  set EFlowTowerOutputArray eflowTowers
+
+  set pi [expr {acos(-1)}]
+
+  # lists of the edges of each tower in eta and phi
+  # each list starts with the lower edge of the first tower
+  # the list ends with the higher edged of the last tower
+
+  # 5 degrees towers
+  set PhiBins {}
+  for {set i -36} {$i <= 36} {incr i} {
+    add PhiBins [expr {$i * $pi/36.0}]
+  }
+  foreach eta {-1.566 -1.479 -1.392 -1.305 -1.218 -1.131 -1.044 -0.957 -0.87 -0.783 -0.696 -0.609 -0.522 -0.435 -0.348 -0.261 -0.174 -0.087 0 0.087 0.174 0.261 0.348 0.435 0.522 0.609 0.696 0.783 0.87 0.957 1.044 1.131 1.218 1.305 1.392 1.479 1.566 1.653} {
+    add EtaPhiBins $eta $PhiBins
+  }
+
+  # 10 degrees towers
+  set PhiBins {}
+  for {set i -18} {$i <= 18} {incr i} {
+    add PhiBins [expr {$i * $pi/18.0}]
+  }
+  foreach eta {-4.35 -4.175 -4 -3.825 -3.65 -3.475 -3.3 -3.125 -2.95 -2.868 -2.65 -2.5 -2.322 -2.172 -2.043 -1.93 -1.83 -1.74 -1.653 1.74 1.83 1.93 2.043 2.172 2.322 2.5 2.65 2.868 2.95 3.125 3.3 3.475 3.65 3.825 4 4.175 4.35 4.525} {
+    add EtaPhiBins $eta $PhiBins
+  }
+
+  # 20 degrees towers
+  set PhiBins {}
+  for {set i -9} {$i <= 9} {incr i} {
+    add PhiBins [expr {$i * $pi/9.0}]
+  }
+  foreach eta {-5 -4.7 -4.525 4.7 5} {
+    add EtaPhiBins $eta $PhiBins
+  }
+
+  # default energy fractions {abs(PDG code)} {Fecal Fhcal}
+  add EnergyFraction {0} {0.0 1.0}
+  # energy fractions for e, gamma and pi0
+  add EnergyFraction {11} {1.0 0.0}
+  add EnergyFraction {22} {1.0 0.0}
+  add EnergyFraction {111} {1.0 0.0}
+  # energy fractions for muon, neutrinos and neutralinos
+  add EnergyFraction {12} {0.0 0.0}
+  add EnergyFraction {13} {0.0 0.0}
+  add EnergyFraction {14} {0.0 0.0}
+  add EnergyFraction {16} {0.0 0.0}
+  add EnergyFraction {1000022} {0.0 0.0}
+  add EnergyFraction {1000023} {0.0 0.0}
+  add EnergyFraction {1000025} {0.0 0.0}
+  add EnergyFraction {1000035} {0.0 0.0}
+  add EnergyFraction {1000045} {0.0 0.0}
+  # energy fractions for K0short and Lambda
+  add EnergyFraction {310} {0.3 0.7}
+  add EnergyFraction {3122} {0.3 0.7}
+
+  # set ECalResolutionFormula {resolution formula as a function of eta and energy}
+  set ECalResolutionFormula {                  (abs(eta) <= 3.0) * sqrt(energy^2*0.005^2 + energy*0.05^2 + 0.25^2) + \
+                             (abs(eta) > 3.0 && abs(eta) <= 5.0) * sqrt(energy^2*0.107^2 + energy*2.08^2)}
+
+  # set HCalResolutionFormula {resolution formula as a function of eta and energy}
+  set HCalResolutionFormula {                  (abs(eta) <= 3.0) * sqrt(energy^2*0.050^2 + energy*1.50^2) + \
+                             (abs(eta) > 3.0 && abs(eta) <= 5.0) * sqrt(energy^2*0.130^2 + energy*2.70^2)}
+}
+
+####################
+# Energy flow merger
+####################
+
+module Merger EFlowMerger {
+# add InputArray InputArray
+  add InputArray Calorimeter/eflowTracks
+  add InputArray Calorimeter/eflowTowers
+  add InputArray MuonMomentumSmearing/muons
+  set OutputArray eflow
+}
+
+###################
+# Photon efficiency
+###################
+
+module Efficiency PhotonEfficiency {
+  set InputArray Calorimeter/photons
+  set OutputArray photons
+
+  # set EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # efficiency formula for photons
+  set EfficiencyFormula {                                      (pt <= 10.0) * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 10.0)  * (0.95) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 10.0)  * (0.85) + \
+                         (abs(eta) > 2.5)                                   * (0.00)}
+}
+
+##################
+# Photon isolation
+##################
+
+module Isolation PhotonIsolation {
+  set CandidateInputArray PhotonEfficiency/photons
+  set IsolationInputArray EFlowMerger/eflow
+
+  set OutputArray photons
+
+  set DeltaRMax 0.5
+
+  set PTMin 0.5
+
+  set PTRatioMax 0.1
+}
+
+#####################
+# Electron efficiency
+#####################
+
+module Efficiency ElectronEfficiency {
+  set InputArray ElectronEnergySmearing/electrons
+  set OutputArray electrons
+
+  # set EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # efficiency formula for electrons
+  set EfficiencyFormula {                                      (pt <= 10.0) * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 10.0)  * (0.95) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 10.0)  * (0.85) + \
+                         (abs(eta) > 2.5)                                   * (0.00)}
+}
+
+####################
+# Electron isolation
+####################
+
+module Isolation ElectronIsolation {
+  set CandidateInputArray ElectronEfficiency/electrons
+  set IsolationInputArray EFlowMerger/eflow
+
+  set OutputArray electrons
+
+  set DeltaRMax 0.5
+
+  set PTMin 0.5
+
+  set PTRatioMax 0.1
+}
+
+#################
+# Muon efficiency
+#################
+
+module Efficiency MuonEfficiency {
+  set InputArray MuonMomentumSmearing/muons
+  set OutputArray muons
+
+  # set EfficiencyFormula {efficiency as a function of eta and pt}
+
+  # efficiency formula for muons
+  set EfficiencyFormula {                                      (pt <= 10.0) * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 10.0)  * (0.95) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.4) * (pt > 10.0)  * (0.85) + \
+                         (abs(eta) > 2.4)                                   * (0.00)}
+}
+
+################
+# Muon isolation
+################
+
+module Isolation MuonIsolation {
+  set CandidateInputArray MuonEfficiency/muons
+  set IsolationInputArray EFlowMerger/eflow
+
+  set OutputArray muons
+
+  set DeltaRMax 0.5
+
+  set PTMin 0.5
+
+  set PTRatioMax 0.1
+}
+
+###################
+# Missing ET merger
+###################
+
+module Merger MissingET {
+# add InputArray InputArray
+  add InputArray EFlowMerger/eflow
+  set MomentumOutputArray momentum
+}
+
+##################
+# Scalar HT merger
+##################
+
+module Merger ScalarHT {
+# add InputArray InputArray
+  add InputArray UniqueObjectFinder/jets
+  add InputArray UniqueObjectFinder/electrons
+  add InputArray UniqueObjectFinder/photons
+  add InputArray MuonIsolation/muons
+  set EnergyOutputArray energy
+}
+
+#####################
+# MC truth jet finder
+#####################
+
+module FastJetFinder GenJetFinder {
+  set InputArray Delphes/stableParticles
+
+  set OutputArray jets
+
+  # algorithm: 1 CDFJetClu, 2 MidPoint, 3 SIScone, 4 kt, 5 Cambridge/Aachen, 6 antikt
+  set JetAlgorithm 6
+  set ParameterR 0.7
+
+  set ConeRadius 0.5
+  set SeedThreshold 1.0
+  set ConeAreaFraction 1.0
+  set AdjacencyCut 2.0
+  set OverlapThreshold 0.75
+
+  set MaxIterations 100
+  set MaxPairSize 2
+  set Iratch 1
+
+  set JetPTMin 20.0
+}
+
+############
+# Jet finder
+############
+
+module FastJetFinder FastJetFinder {
+#  set InputArray Calorimeter/towers
+  set InputArray EFlowMerger/eflow
+
+  set OutputArray jets
+
+  # algorithm: 1 CDFJetClu, 2 MidPoint, 3 SIScone, 4 kt, 5 Cambridge/Aachen, 6 antikt
+  set JetAlgorithm 6
+  set ParameterR 0.7
+
+  set ConeRadius 0.5
+  set SeedThreshold 1.0
+  set ConeAreaFraction 1.0
+  set AdjacencyCut 2.0
+  set OverlapThreshold 0.75
+
+  set MaxIterations 100
+  set MaxPairSize 2
+  set Iratch 1
+
+  set JetPTMin 20.0
+}
+
+####################
+# Constituent filter
+####################
+
+module ConstituentFilter ConstituentFilter {
+
+# add JetInputArray InputArray
+  add JetInputArray GenJetFinder/jets
+  add JetInputArray FastJetFinder/jets
+
+# add ConstituentInputArray InputArray OutputArray
+  add ConstituentInputArray Delphes/stableParticles stableParticles
+  add ConstituentInputArray Calorimeter/eflowTracks eflowTracks
+  add ConstituentInputArray Calorimeter/eflowTowers eflowTowers
+  add ConstituentInputArray MuonMomentumSmearing/muons muons
+}
+
+###########
+# b-tagging
+###########
+
+module BTagging BTagging {
+  set PartonInputArray Delphes/partons
+  set JetInputArray FastJetFinder/jets
+
+  set BitNumber 0
+
+  set DeltaR 0.5
+
+  set PartonPTMin 1.0
+
+  set PartonEtaMax 2.5
+
+  # add EfficiencyFormula {abs(PDG code)} {efficiency formula as a function of eta and pt}
+  # PDG code = the highest PDG code of a quark or gluon inside DeltaR cone around jet axis
+  # gluon's PDG code has the lowest priority
+
+  # https://twiki.cern.ch/twiki/bin/view/CMSPublic/PhysicsResultsBTV
+  # default efficiency formula (misidentification rate)
+  add EfficiencyFormula {0} {0.001}
+
+  # efficiency formula for c-jets (misidentification rate)
+  add EfficiencyFormula {4} {                                      (pt <= 15.0) * (0.000) + \
+                                                (abs(eta) <= 1.2) * (pt > 15.0) * (0.2*tanh(pt*0.03 - 0.4)) + \
+                              (abs(eta) > 1.2 && abs(eta) <= 2.5) * (pt > 15.0) * (0.1*tanh(pt*0.03 - 0.4)) + \
+                              (abs(eta) > 2.5)                                  * (0.000)}
+
+  # efficiency formula for b-jets
+  add EfficiencyFormula {5} {                                      (pt <= 15.0) * (0.000) + \
+                                                (abs(eta) <= 1.2) * (pt > 15.0) * (0.5*tanh(pt*0.03 - 0.4)) + \
+                              (abs(eta) > 1.2 && abs(eta) <= 2.5) * (pt > 15.0) * (0.4*tanh(pt*0.03 - 0.4)) + \
+                              (abs(eta) > 2.5)                                  * (0.000)}
+}
+
+module TauTagging TauTagging {
+  set ParticleInputArray Delphes/allParticles
+  set PartonInputArray Delphes/partons
+  set JetInputArray FastJetFinder/jets
+
+  set DeltaR 0.5
+
+  set TauPTMin 1.0
+
+  set TauEtaMax 2.5
+
+  # add EfficiencyFormula {abs(PDG code)} {efficiency formula as a function of eta and pt}
+
+  # default efficiency formula (misidentification rate)
+  add EfficiencyFormula {0} {0.001}
+  # efficiency formula for tau-jets
+  add EfficiencyFormula {15} {0.4}
+}
+
+#####################################################
+# Find uniquely identified photons/electrons/tau/jets
+#####################################################
+
+module UniqueObjectFinder UniqueObjectFinder {
+# earlier arrays take precedence over later ones
+# add InputArray InputArray OutputArray
+  add InputArray PhotonIsolation/photons photons
+  add InputArray ElectronIsolation/electrons electrons
+  add InputArray FastJetFinder/jets jets
+}
+
+##################
+# ROOT tree writer
+##################
+
+module TreeWriter TreeWriter {
+# add Branch InputArray BranchName BranchClass
+  add Branch Delphes/allParticles Particle GenParticle
+  add Branch TrackMerger/tracks Track Track
+  add Branch Calorimeter/towers Tower Tower
+  add Branch ConstituentFilter/eflowTracks EFlowTrack Track
+  add Branch ConstituentFilter/eflowTowers EFlowTower Tower
+  add Branch ConstituentFilter/muons EFlowMuon Muon
+  add Branch GenJetFinder/jets GenJet Jet
+  add Branch UniqueObjectFinder/jets Jet Jet
+  add Branch UniqueObjectFinder/electrons Electron Electron
+  add Branch UniqueObjectFinder/photons Photon Photon
+  add Branch MuonIsolation/muons Muon Muon
+  add Branch MissingET/momentum MissingET MissingET
+  add Branch ScalarHT/energy ScalarHT ScalarHT
+}
+
Index: trunk/Delphes/Delphes-3.0.9/examples/delphes_card_CMS_NoVFC.tcl
===================================================================
--- trunk/Delphes/Delphes-3.0.9/examples/delphes_card_CMS_NoVFC.tcl	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/examples/delphes_card_CMS_NoVFC.tcl	(revision 5)
@@ -0,0 +1,555 @@
+#######################################
+# Order of execution of various modules
+#######################################
+
+set ExecutionPath {
+  ParticlePropagator
+
+  ChargedHadronTrackingEfficiency
+  ElectronTrackingEfficiency
+  MuonTrackingEfficiency
+
+  ChargedHadronMomentumSmearing
+  ElectronEnergySmearing
+  MuonMomentumSmearing
+
+  TrackMerger
+  Calorimeter
+  EFlowMerger
+
+  PhotonEfficiency
+  PhotonIsolation
+
+  ElectronEfficiency
+  ElectronIsolation
+
+  MuonEfficiency
+  MuonIsolation
+
+  MissingET
+
+  GenJetFinder
+  FastJetFinder
+
+  ConstituentFilter
+
+  BTagging
+  TauTagging
+
+  UniqueObjectFinder
+
+  ScalarHT
+
+  TreeWriter
+}
+
+#################################
+# Propagate particles in cylinder
+#################################
+
+module ParticlePropagator ParticlePropagator {
+  set InputArray Delphes/stableParticles
+
+  set OutputArray stableParticles
+  set ChargedHadronOutputArray chargedHadrons
+  set ElectronOutputArray electrons
+  set MuonOutputArray muons
+
+  # radius of the magnetic field coverage, in m
+  set Radius 1.29
+  # half-length of the magnetic field coverage, in m
+  set HalfLength 3.00
+
+  # magnetic field
+  set Bz 3.8
+}
+
+####################################
+# Charged hadron tracking efficiency
+####################################
+
+module Efficiency ChargedHadronTrackingEfficiency {
+  set InputArray ParticlePropagator/chargedHadrons
+  set OutputArray chargedHadrons
+
+  # add EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # tracking efficiency formula for charged hadrons
+  set EfficiencyFormula {                                                    (pt <= 0.1)   * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.70) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0)                  * (0.95) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.60) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0)                  * (0.85) + \
+                         (abs(eta) > 2.5)                                                  * (0.00)}
+}
+
+##############################
+# Electron tracking efficiency
+##############################
+
+module Efficiency ElectronTrackingEfficiency {
+  set InputArray ParticlePropagator/electrons
+  set OutputArray electrons
+
+  # set EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # tracking efficiency formula for electrons
+  set EfficiencyFormula {                                                    (pt <= 0.1)   * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.73) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0   && pt <= 1.0e2) * (0.95) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0e2)                * (0.99) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.50) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0   && pt <= 1.0e2) * (0.83) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0e2)                * (0.90) + \
+                         (abs(eta) > 2.5)                                                  * (0.00)}
+}
+
+##########################
+# Muon tracking efficiency
+##########################
+
+module Efficiency MuonTrackingEfficiency {
+  set InputArray ParticlePropagator/muons
+  set OutputArray muons
+
+  # set EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # tracking efficiency formula for muons
+  set EfficiencyFormula {                                                    (pt <= 0.1)   * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.75) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0)                  * (0.99) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.70) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0)                  * (0.98) + \
+                         (abs(eta) > 2.5)                                                  * (0.00)}
+}
+
+########################################
+# Momentum resolution for charged tracks
+########################################
+
+module MomentumSmearing ChargedHadronMomentumSmearing {
+  set InputArray ChargedHadronTrackingEfficiency/chargedHadrons
+  set OutputArray chargedHadrons
+
+  # set ResolutionFormula {resolution formula as a function of eta and pt}
+
+  # resolution formula for charged hadrons
+  set ResolutionFormula {                  (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.02) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0   && pt <= 1.0e1) * (0.01) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0e1 && pt <= 2.0e2) * (0.03) + \
+                                           (abs(eta) <= 1.5) * (pt > 2.0e2)                * (0.05) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.03) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0   && pt <= 1.0e1) * (0.02) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0e1 && pt <= 2.0e2) * (0.04) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 2.0e2)                * (0.05)}
+}
+
+#################################
+# Energy resolution for electrons
+#################################
+
+module EnergySmearing ElectronEnergySmearing {
+  set InputArray ElectronTrackingEfficiency/electrons
+  set OutputArray electrons
+
+  # set ResolutionFormula {resolution formula as a function of eta and energy}
+
+  set ResolutionFormula {                  (abs(eta) <= 2.5) * (energy > 0.1   && energy <= 2.5e1) * (energy*0.015) + \
+                                           (abs(eta) <= 2.5) * (energy > 2.5e1)                    * sqrt(energy^2*0.005^2 + energy*0.05^2 + 0.25^2) + \
+                         (abs(eta) > 2.5 && abs(eta) <= 3.0)                                       * sqrt(energy^2*0.005^2 + energy*0.05^2 + 0.25^2)}
+
+}
+
+###############################
+# Momentum resolution for muons
+###############################
+
+module MomentumSmearing MuonMomentumSmearing {
+  set InputArray MuonTrackingEfficiency/muons
+  set OutputArray muons
+
+  # set ResolutionFormula {resolution formula as a function of eta and pt}
+
+  # resolution formula for muons
+  set ResolutionFormula {                  (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.03) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0   && pt <= 1.0e1) * (0.02) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0e1 && pt <= 2.0e2) * (0.03) + \
+                                           (abs(eta) <= 1.5) * (pt > 2.0e2)                * (0.05) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.04) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0   && pt <= 1.0e1) * (0.03) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0e1 && pt <= 2.0e2) * (0.04) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 2.0e2)                * (0.05)}
+}
+
+##############
+# Track merger
+##############
+
+module Merger TrackMerger {
+# add InputArray InputArray
+  add InputArray ChargedHadronMomentumSmearing/chargedHadrons
+  add InputArray ElectronEnergySmearing/electrons
+  set OutputArray tracks
+}
+
+#############
+# Calorimeter
+#############
+
+module Calorimeter Calorimeter {
+  set ParticleInputArray ParticlePropagator/stableParticles
+  set TrackInputArray TrackMerger/tracks
+
+  set TowerOutputArray towers
+  set PhotonOutputArray photons
+
+  set EFlowTrackOutputArray eflowTracks
+  set EFlowTowerOutputArray eflowTowers
+
+  set pi [expr {acos(-1)}]
+
+  # lists of the edges of each tower in eta and phi
+  # each list starts with the lower edge of the first tower
+  # the list ends with the higher edged of the last tower
+
+  # 5 degrees towers
+  set PhiBins {}
+  for {set i -36} {$i <= 36} {incr i} {
+    add PhiBins [expr {$i * $pi/36.0}]
+  }
+  foreach eta {-1.566 -1.479 -1.392 -1.305 -1.218 -1.131 -1.044 -0.957 -0.87 -0.783 -0.696 -0.609 -0.522 -0.435 -0.348 -0.261 -0.174 -0.087 0 0.087 0.174 0.261 0.348 0.435 0.522 0.609 0.696 0.783 0.87 0.957 1.044 1.131 1.218 1.305 1.392 1.479 1.566 1.653} {
+    add EtaPhiBins $eta $PhiBins
+  }
+
+  # 10 degrees towers
+  set PhiBins {}
+  for {set i -18} {$i <= 18} {incr i} {
+    add PhiBins [expr {$i * $pi/18.0}]
+  }
+  foreach eta {-3.0 -2.65 -2.5 -2.322 -2.172 -2.043 -1.93 -1.83 -1.74 -1.653 1.74 1.83 1.93 2.043 2.172 2.322 2.5 2.65 3.0} {
+    add EtaPhiBins $eta $PhiBins
+  }
+
+  # default energy fractions {abs(PDG code)} {Fecal Fhcal}
+  add EnergyFraction {0} {0.0 1.0}
+  # energy fractions for e, gamma and pi0
+  add EnergyFraction {11} {1.0 0.0}
+  add EnergyFraction {22} {1.0 0.0}
+  add EnergyFraction {111} {1.0 0.0}
+  # energy fractions for muon, neutrinos and neutralinos
+  add EnergyFraction {12} {0.0 0.0}
+  add EnergyFraction {13} {0.0 0.0}
+  add EnergyFraction {14} {0.0 0.0}
+  add EnergyFraction {16} {0.0 0.0}
+  add EnergyFraction {1000022} {0.0 0.0}
+  add EnergyFraction {1000023} {0.0 0.0}
+  add EnergyFraction {1000025} {0.0 0.0}
+  add EnergyFraction {1000035} {0.0 0.0}
+  add EnergyFraction {1000045} {0.0 0.0}
+  # energy fractions for K0short and Lambda
+  add EnergyFraction {310} {0.3 0.7}
+  add EnergyFraction {3122} {0.3 0.7}
+
+  # set ECalResolutionFormula {resolution formula as a function of eta and energy}
+  set ECalResolutionFormula {sqrt(energy^2*0.005^2 + energy*0.05^2 + 0.25^2)}
+
+  # set HCalResolutionFormula {resolution formula as a function of eta and energy}
+  set HCalResolutionFormula {sqrt(energy^2*0.050^2 + energy*1.50^2)}
+}
+
+####################
+# Energy flow merger
+####################
+
+module Merger EFlowMerger {
+# add InputArray InputArray
+  add InputArray Calorimeter/eflowTracks
+  add InputArray Calorimeter/eflowTowers
+  add InputArray MuonMomentumSmearing/muons
+  set OutputArray eflow
+}
+
+###################
+# Photon efficiency
+###################
+
+module Efficiency PhotonEfficiency {
+  set InputArray Calorimeter/photons
+  set OutputArray photons
+
+  # set EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # efficiency formula for photons
+  set EfficiencyFormula {                                      (pt <= 10.0) * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 10.0)  * (0.95) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 10.0)  * (0.85) + \
+                         (abs(eta) > 2.5)                                   * (0.00)}
+}
+
+##################
+# Photon isolation
+##################
+
+module Isolation PhotonIsolation {
+  set CandidateInputArray PhotonEfficiency/photons
+  set IsolationInputArray EFlowMerger/eflow
+
+  set OutputArray photons
+
+  set DeltaRMax 0.5
+
+  set PTMin 0.5
+
+  set PTRatioMax 0.1
+}
+
+#####################
+# Electron efficiency
+#####################
+
+module Efficiency ElectronEfficiency {
+  set InputArray ElectronEnergySmearing/electrons
+  set OutputArray electrons
+
+  # set EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # efficiency formula for electrons
+  set EfficiencyFormula {                                      (pt <= 10.0) * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 10.0)  * (0.95) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 10.0)  * (0.85) + \
+                         (abs(eta) > 2.5)                                   * (0.00)}
+}
+
+####################
+# Electron isolation
+####################
+
+module Isolation ElectronIsolation {
+  set CandidateInputArray ElectronEfficiency/electrons
+  set IsolationInputArray EFlowMerger/eflow
+
+  set OutputArray electrons
+
+  set DeltaRMax 0.5
+
+  set PTMin 0.5
+
+  set PTRatioMax 0.1
+}
+
+#################
+# Muon efficiency
+#################
+
+module Efficiency MuonEfficiency {
+  set InputArray MuonMomentumSmearing/muons
+  set OutputArray muons
+
+  # set EfficiencyFormula {efficiency as a function of eta and pt}
+
+  # efficiency formula for muons
+  set EfficiencyFormula {                                      (pt <= 10.0) * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 10.0)  * (0.95) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.4) * (pt > 10.0)  * (0.85) + \
+                         (abs(eta) > 2.4)                                   * (0.00)}
+}
+
+################
+# Muon isolation
+################
+
+module Isolation MuonIsolation {
+  set CandidateInputArray MuonEfficiency/muons
+  set IsolationInputArray EFlowMerger/eflow
+
+  set OutputArray muons
+
+  set DeltaRMax 0.5
+
+  set PTMin 0.5
+
+  set PTRatioMax 0.1
+}
+
+###################
+# Missing ET merger
+###################
+
+module Merger MissingET {
+# add InputArray InputArray
+  add InputArray EFlowMerger/eflow
+  set MomentumOutputArray momentum
+}
+
+##################
+# Scalar HT merger
+##################
+
+module Merger ScalarHT {
+# add InputArray InputArray
+  add InputArray UniqueObjectFinder/jets
+  add InputArray UniqueObjectFinder/electrons
+  add InputArray UniqueObjectFinder/photons
+  add InputArray MuonIsolation/muons
+  set EnergyOutputArray energy
+}
+
+#####################
+# MC truth jet finder
+#####################
+
+module FastJetFinder GenJetFinder {
+  set InputArray Delphes/stableParticles
+
+  set OutputArray jets
+
+  # algorithm: 1 CDFJetClu, 2 MidPoint, 3 SIScone, 4 kt, 5 Cambridge/Aachen, 6 antikt
+  set JetAlgorithm 6
+  set ParameterR 0.7
+
+  set ConeRadius 0.5
+  set SeedThreshold 1.0
+  set ConeAreaFraction 1.0
+  set AdjacencyCut 2.0
+  set OverlapThreshold 0.75
+
+  set MaxIterations 100
+  set MaxPairSize 2
+  set Iratch 1
+
+  set JetPTMin 20.0
+}
+
+############
+# Jet finder
+############
+
+module FastJetFinder FastJetFinder {
+#  set InputArray Calorimeter/towers
+  set InputArray EFlowMerger/eflow
+
+  set OutputArray jets
+
+  # algorithm: 1 CDFJetClu, 2 MidPoint, 3 SIScone, 4 kt, 5 Cambridge/Aachen, 6 antikt
+  set JetAlgorithm 6
+  set ParameterR 0.7
+
+  set ConeRadius 0.5
+  set SeedThreshold 1.0
+  set ConeAreaFraction 1.0
+  set AdjacencyCut 2.0
+  set OverlapThreshold 0.75
+
+  set MaxIterations 100
+  set MaxPairSize 2
+  set Iratch 1
+
+  set JetPTMin 20.0
+}
+
+####################
+# Constituent filter
+####################
+
+module ConstituentFilter ConstituentFilter {
+
+# add JetInputArray InputArray
+  add JetInputArray GenJetFinder/jets
+  add JetInputArray FastJetFinder/jets
+
+# add ConstituentInputArray InputArray OutputArray
+  add ConstituentInputArray Delphes/stableParticles stableParticles
+  add ConstituentInputArray Calorimeter/eflowTracks eflowTracks
+  add ConstituentInputArray Calorimeter/eflowTowers eflowTowers
+  add ConstituentInputArray MuonMomentumSmearing/muons muons
+}
+
+###########
+# b-tagging
+###########
+
+module BTagging BTagging {
+  set PartonInputArray Delphes/partons
+  set JetInputArray FastJetFinder/jets
+
+  set BitNumber 0
+
+  set DeltaR 0.5
+
+  set PartonPTMin 1.0
+
+  set PartonEtaMax 2.5
+
+  # add EfficiencyFormula {abs(PDG code)} {efficiency formula as a function of eta and pt}
+  # PDG code = the highest PDG code of a quark or gluon inside DeltaR cone around jet axis
+  # gluon's PDG code has the lowest priority
+
+  # https://twiki.cern.ch/twiki/bin/view/CMSPublic/PhysicsResultsBTV
+  # default efficiency formula (misidentification rate)
+  add EfficiencyFormula {0} {0.001}
+
+  # efficiency formula for c-jets (misidentification rate)
+  add EfficiencyFormula {4} {                                      (pt <= 15.0) * (0.000) + \
+                                                (abs(eta) <= 1.2) * (pt > 15.0) * (0.2*tanh(pt*0.03 - 0.4)) + \
+                              (abs(eta) > 1.2 && abs(eta) <= 2.5) * (pt > 15.0) * (0.1*tanh(pt*0.03 - 0.4)) + \
+                              (abs(eta) > 2.5)                                  * (0.000)}
+
+  # efficiency formula for b-jets
+  add EfficiencyFormula {5} {                                      (pt <= 15.0) * (0.000) + \
+                                                (abs(eta) <= 1.2) * (pt > 15.0) * (0.5*tanh(pt*0.03 - 0.4)) + \
+                              (abs(eta) > 1.2 && abs(eta) <= 2.5) * (pt > 15.0) * (0.4*tanh(pt*0.03 - 0.4)) + \
+                              (abs(eta) > 2.5)                                  * (0.000)}
+}
+
+module TauTagging TauTagging {
+  set ParticleInputArray Delphes/allParticles
+  set PartonInputArray Delphes/partons
+  set JetInputArray FastJetFinder/jets
+
+  set DeltaR 0.5
+
+  set TauPTMin 1.0
+
+  set TauEtaMax 2.5
+
+  # add EfficiencyFormula {abs(PDG code)} {efficiency formula as a function of eta and pt}
+
+  # default efficiency formula (misidentification rate)
+  add EfficiencyFormula {0} {0.001}
+  # efficiency formula for tau-jets
+  add EfficiencyFormula {15} {0.4}
+}
+
+#####################################################
+# Find uniquely identified photons/electrons/tau/jets
+#####################################################
+
+module UniqueObjectFinder UniqueObjectFinder {
+# earlier arrays take precedence over later ones
+# add InputArray InputArray OutputArray
+  add InputArray PhotonIsolation/photons photons
+  add InputArray ElectronIsolation/electrons electrons
+  add InputArray FastJetFinder/jets jets
+}
+
+##################
+# ROOT tree writer
+##################
+
+module TreeWriter TreeWriter {
+# add Branch InputArray BranchName BranchClass
+  add Branch Delphes/allParticles Particle GenParticle
+  add Branch TrackMerger/tracks Track Track
+  add Branch Calorimeter/towers Tower Tower
+  add Branch ConstituentFilter/eflowTracks EFlowTrack Track
+  add Branch ConstituentFilter/eflowTowers EFlowTower Tower
+  add Branch ConstituentFilter/muons EFlowMuon Muon
+  add Branch GenJetFinder/jets GenJet Jet
+  add Branch UniqueObjectFinder/jets Jet Jet
+  add Branch UniqueObjectFinder/electrons Electron Electron
+  add Branch UniqueObjectFinder/photons Photon Photon
+  add Branch MuonIsolation/muons Muon Muon
+  add Branch MissingET/momentum MissingET MissingET
+  add Branch ScalarHT/energy ScalarHT ScalarHT
+}
+
Index: trunk/Delphes/Delphes-3.0.9/examples/delphes_card_CMS_PileUp.tcl
===================================================================
--- trunk/Delphes/Delphes-3.0.9/examples/delphes_card_CMS_PileUp.tcl	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/examples/delphes_card_CMS_PileUp.tcl	(revision 5)
@@ -0,0 +1,630 @@
+#######################################
+# Order of execution of various modules
+#######################################
+
+set ExecutionPath {
+
+  PileUpMerger
+  ParticlePropagator
+
+  ChargedHadronTrackingEfficiency
+  ElectronTrackingEfficiency
+  MuonTrackingEfficiency
+
+  ChargedHadronMomentumSmearing
+  ElectronEnergySmearing
+  MuonMomentumSmearing
+
+  TrackMerger
+  Calorimeter
+  TrackPileUpSubtractor
+  EFlowMerger
+
+  GenJetFinder
+
+  Rho
+  FastJetFinder
+  JetPileUpSubtractor
+
+  ConstituentFilter
+
+  PhotonEfficiency
+  PhotonIsolation
+
+  ElectronEfficiency
+  ElectronIsolation
+
+  MuonEfficiency
+  MuonIsolation
+
+  MissingET
+
+  BTagging
+  TauTagging
+
+  UniqueObjectFinder
+
+  ScalarHT
+
+  TreeWriter
+}
+
+###############
+# PileUp Merger
+###############
+
+module PileUpMerger PileUpMerger {
+  set InputArray Delphes/stableParticles
+
+  set OutputArray stableParticles
+
+  # pre-generated minbias input file
+  set PileUpFile MinBias.pileup
+
+  # average expected pile up
+  set MeanPileUp 50
+  # spread in the beam direction in m (assumes gaussian)
+  set ZVertexSpread 0.07
+}
+
+#################################
+# Propagate particles in cylinder
+#################################
+
+module ParticlePropagator ParticlePropagator {
+  set InputArray PileUpMerger/stableParticles
+
+  set OutputArray stableParticles
+  set ChargedHadronOutputArray chargedHadrons
+  set ElectronOutputArray electrons
+  set MuonOutputArray muons
+
+  # radius of the magnetic field coverage, in m
+  set Radius 1.29
+  # half-length of the magnetic field coverage, in m
+  set HalfLength 3.00
+
+  # magnetic field
+  set Bz 3.8
+}
+
+####################################
+# Charged hadron tracking efficiency
+####################################
+
+module Efficiency ChargedHadronTrackingEfficiency {
+  set InputArray ParticlePropagator/chargedHadrons
+  set OutputArray chargedHadrons
+
+  # add EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # tracking efficiency formula for charged hadrons
+  set EfficiencyFormula {                                                    (pt <= 0.1)   * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.70) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0)                  * (0.95) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.60) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0)                  * (0.85) + \
+                         (abs(eta) > 2.5)                                                  * (0.00)}
+}
+
+##############################
+# Electron tracking efficiency
+##############################
+
+module Efficiency ElectronTrackingEfficiency {
+  set InputArray ParticlePropagator/electrons
+  set OutputArray electrons
+
+  # set EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # tracking efficiency formula for electrons
+  set EfficiencyFormula {                                                    (pt <= 0.1)   * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.73) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0   && pt <= 1.0e2) * (0.95) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0e2)                * (0.99) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.50) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0   && pt <= 1.0e2) * (0.83) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0e2)                * (0.90) + \
+                         (abs(eta) > 2.5)                                                  * (0.00)}
+}
+
+##########################
+# Muon tracking efficiency
+##########################
+
+module Efficiency MuonTrackingEfficiency {
+  set InputArray ParticlePropagator/muons
+  set OutputArray muons
+
+  # set EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # tracking efficiency formula for muons
+  set EfficiencyFormula {                                                    (pt <= 0.1)   * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.75) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0)                  * (0.99) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.70) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0)                  * (0.98) + \
+                         (abs(eta) > 2.5)                                                  * (0.00)}
+}
+
+########################################
+# Momentum resolution for charged tracks
+########################################
+
+module MomentumSmearing ChargedHadronMomentumSmearing {
+  set InputArray ChargedHadronTrackingEfficiency/chargedHadrons
+  set OutputArray chargedHadrons
+
+  # set ResolutionFormula {resolution formula as a function of eta and pt}
+
+  # resolution formula for charged hadrons
+  set ResolutionFormula {                  (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.02) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0   && pt <= 1.0e1) * (0.01) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0e1 && pt <= 2.0e2) * (0.03) + \
+                                           (abs(eta) <= 1.5) * (pt > 2.0e2)                * (0.05) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.03) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0   && pt <= 1.0e1) * (0.02) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0e1 && pt <= 2.0e2) * (0.04) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 2.0e2)                * (0.05)}
+}
+
+#################################
+# Energy resolution for electrons
+#################################
+
+module EnergySmearing ElectronEnergySmearing {
+  set InputArray ElectronTrackingEfficiency/electrons
+  set OutputArray electrons
+
+  # set ResolutionFormula {resolution formula as a function of eta and energy}
+
+  set ResolutionFormula {                  (abs(eta) <= 2.5) * (energy > 0.1   && energy <= 2.5e1) * (energy*0.015) + \
+                                           (abs(eta) <= 2.5) * (energy > 2.5e1)                    * sqrt(energy^2*0.005^2 + energy*0.05^2 + 0.25^2) + \
+                         (abs(eta) > 2.5 && abs(eta) <= 3.0)                                       * sqrt(energy^2*0.005^2 + energy*0.05^2 + 0.25^2) + \
+                         (abs(eta) > 3.0 && abs(eta) <= 5.0)                                       * sqrt(energy^2*0.107^2 + energy*2.08^2)}
+
+}
+
+###############################
+# Momentum resolution for muons
+###############################
+
+module MomentumSmearing MuonMomentumSmearing {
+  set InputArray MuonTrackingEfficiency/muons
+  set OutputArray muons
+
+  # set ResolutionFormula {resolution formula as a function of eta and pt}
+
+  # resolution formula for muons
+  set ResolutionFormula {                  (abs(eta) <= 1.5) * (pt > 0.1   && pt <= 1.0)   * (0.03) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0   && pt <= 1.0e1) * (0.02) + \
+                                           (abs(eta) <= 1.5) * (pt > 1.0e1 && pt <= 2.0e2) * (0.03) + \
+                                           (abs(eta) <= 1.5) * (pt > 2.0e2)                * (0.05) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 0.1   && pt <= 1.0)   * (0.04) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0   && pt <= 1.0e1) * (0.03) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 1.0e1 && pt <= 2.0e2) * (0.04) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 2.0e2)                * (0.05)}
+}
+
+##############
+# Track merger
+##############
+
+module Merger TrackMerger {
+# add InputArray InputArray
+  add InputArray ChargedHadronMomentumSmearing/chargedHadrons
+  add InputArray ElectronEnergySmearing/electrons
+  set OutputArray tracks
+}
+
+#############
+# Calorimeter
+#############
+
+module Calorimeter Calorimeter {
+  set ParticleInputArray ParticlePropagator/stableParticles
+  set TrackInputArray TrackMerger/tracks
+
+  set TowerOutputArray towers
+  set PhotonOutputArray photons
+
+  set EFlowTrackOutputArray eflowTracks
+  set EFlowTowerOutputArray eflowTowers
+
+  set pi [expr {acos(-1)}]
+
+  # lists of the edges of each tower in eta and phi
+  # each list starts with the lower edge of the first tower
+  # the list ends with the higher edged of the last tower
+
+  # 5 degrees towers
+  set PhiBins {}
+  for {set i -36} {$i <= 36} {incr i} {
+    add PhiBins [expr {$i * $pi/36.0}]
+  }
+  foreach eta {-1.566 -1.479 -1.392 -1.305 -1.218 -1.131 -1.044 -0.957 -0.87 -0.783 -0.696 -0.609 -0.522 -0.435 -0.348 -0.261 -0.174 -0.087 0 0.087 0.174 0.261 0.348 0.435 0.522 0.609 0.696 0.783 0.87 0.957 1.044 1.131 1.218 1.305 1.392 1.479 1.566 1.653} {
+    add EtaPhiBins $eta $PhiBins
+  }
+
+  # 10 degrees towers
+  set PhiBins {}
+  for {set i -18} {$i <= 18} {incr i} {
+    add PhiBins [expr {$i * $pi/18.0}]
+  }
+  foreach eta {-4.35 -4.175 -4 -3.825 -3.65 -3.475 -3.3 -3.125 -2.95 -2.868 -2.65 -2.5 -2.322 -2.172 -2.043 -1.93 -1.83 -1.74 -1.653 1.74 1.83 1.93 2.043 2.172 2.322 2.5 2.65 2.868 2.95 3.125 3.3 3.475 3.65 3.825 4 4.175 4.35 4.525} {
+    add EtaPhiBins $eta $PhiBins
+  }
+
+  # 20 degrees towers
+  set PhiBins {}
+  for {set i -9} {$i <= 9} {incr i} {
+    add PhiBins [expr {$i * $pi/9.0}]
+  }
+  foreach eta {-5 -4.7 -4.525 4.7 5} {
+    add EtaPhiBins $eta $PhiBins
+  }
+
+  # default energy fractions {abs(PDG code)} {Fecal Fhcal}
+  add EnergyFraction {0} {0.0 1.0}
+  # energy fractions for e, gamma and pi0
+  add EnergyFraction {11} {1.0 0.0}
+  add EnergyFraction {22} {1.0 0.0}
+  add EnergyFraction {111} {1.0 0.0}
+  # energy fractions for muon, neutrinos and neutralinos
+  add EnergyFraction {12} {0.0 0.0}
+  add EnergyFraction {13} {0.0 0.0}
+  add EnergyFraction {14} {0.0 0.0}
+  add EnergyFraction {16} {0.0 0.0}
+  add EnergyFraction {1000022} {0.0 0.0}
+  add EnergyFraction {1000023} {0.0 0.0}
+  add EnergyFraction {1000025} {0.0 0.0}
+  add EnergyFraction {1000035} {0.0 0.0}
+  add EnergyFraction {1000045} {0.0 0.0}
+  # energy fractions for K0short and Lambda
+  add EnergyFraction {310} {0.3 0.7}
+  add EnergyFraction {3122} {0.3 0.7}
+
+  # set ECalResolutionFormula {resolution formula as a function of eta and energy}
+  set ECalResolutionFormula {                  (abs(eta) <= 3.0) * sqrt(energy^2*0.005^2 + energy*0.05^2 + 0.25^2) + \
+                             (abs(eta) > 3.0 && abs(eta) <= 5.0) * sqrt(energy^2*0.107^2 + energy*2.08^2)}
+
+  # set HCalResolutionFormula {resolution formula as a function of eta and energy}
+  set HCalResolutionFormula {                  (abs(eta) <= 3.0) * sqrt(energy^2*0.050^2 + energy*1.50^2) + \
+                             (abs(eta) > 3.0 && abs(eta) <= 5.0) * sqrt(energy^2*0.130^2 + energy*2.70^2)}
+}
+
+##########################
+# Track pile-up subtractor
+##########################
+
+module TrackPileUpSubtractor TrackPileUpSubtractor {
+# add InputArray InputArray OutputArray
+  add InputArray Calorimeter/eflowTracks eflowTracks
+  add InputArray ElectronEnergySmearing/electrons electrons
+  add InputArray MuonMomentumSmearing/muons muons
+
+  # assume perfect pile-up subtraction for tracks with |z| > fZVertexResolution
+  # Z vertex resolution in m
+  set ZVertexResolution 0.0001
+}
+
+####################
+# Energy flow merger
+####################
+
+module Merger EFlowMerger {
+# add InputArray InputArray
+  add InputArray TrackPileUpSubtractor/eflowTracks
+  add InputArray Calorimeter/eflowTowers
+  add InputArray MuonMomentumSmearing/muons
+  set OutputArray eflow
+}
+
+#############
+# Rho pile-up
+#############
+
+module FastJetFinder Rho {
+#  set InputArray Calorimeter/towers
+  set InputArray EFlowMerger/eflow
+
+  set ComputeRho true
+  set RhoOutputArray rho
+
+  # area algorithm: 0 Do not compute area, 1 Active area explicit ghosts, 2 One ghost passive area, 3 Passive area, 4 Voronoi, 5 Active area
+  set AreaAlgorithm 5
+
+  # jet algorithm: 1 CDFJetClu, 2 MidPoint, 3 SIScone, 4 kt, 5 Cambridge/Aachen, 6 antikt
+  set JetAlgorithm 4
+  set ParameterR 0.6
+  set GhostEtaMax 5.0
+  set RhoEtaMax 5.0
+
+  set JetPTMin 0.0
+}
+
+#####################
+# MC truth jet finder
+#####################
+
+module FastJetFinder GenJetFinder {
+  set InputArray Delphes/stableParticles
+
+  set OutputArray jets
+
+  # algorithm: 1 CDFJetClu, 2 MidPoint, 3 SIScone, 4 kt, 5 Cambridge/Aachen, 6 antikt
+  set JetAlgorithm 6
+  set ParameterR 0.5
+
+  set JetPTMin 20.0
+}
+
+############
+# Jet finder
+############
+
+module FastJetFinder FastJetFinder {
+#  set InputArray Calorimeter/towers
+  set InputArray EFlowMerger/eflow
+
+  set OutputArray jets
+
+  # area algorithm: 0 Do not compute area, 1 Active area explicit ghosts, 2 One ghost passive area, 3 Passive area, 4 Voronoi, 5 Active area
+  set AreaAlgorithm 5
+
+  # jet algorithm: 1 CDFJetClu, 2 MidPoint, 3 SIScone, 4 kt, 5 Cambridge/Aachen, 6 antikt
+  set JetAlgorithm 6
+  set ParameterR 0.5
+
+  set JetPTMin 20.0
+}
+
+####################
+# Constituent filter
+####################
+
+module ConstituentFilter ConstituentFilter {
+
+# add JetInputArray InputArray
+  add JetInputArray GenJetFinder/jets
+  add JetInputArray FastJetFinder/jets
+
+# add ConstituentInputArray InputArray OutputArray
+  add ConstituentInputArray Delphes/stableParticles stableParticles
+  add ConstituentInputArray TrackPileUpSubtractor/eflowTracks eflowTracks
+  add ConstituentInputArray Calorimeter/eflowTowers eflowTowers
+  add ConstituentInputArray MuonMomentumSmearing/muons muons
+}
+
+###########################
+# Jet Pile-Up Subtraction
+###########################
+
+module JetPileUpSubtractor JetPileUpSubtractor {
+  set JetInputArray FastJetFinder/jets
+  set RhoInputArray Rho/rho
+
+  set OutputArray jets
+
+  set JetPTMin 20.0
+}
+
+###################
+# Photon efficiency
+###################
+
+module Efficiency PhotonEfficiency {
+  set InputArray Calorimeter/photons
+  set OutputArray photons
+
+  # set EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # efficiency formula for photons
+  set EfficiencyFormula {                                      (pt <= 10.0) * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 10.0)  * (0.95) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 10.0)  * (0.85) + \
+                         (abs(eta) > 2.5)                                   * (0.00)}
+}
+
+##################
+# Photon isolation
+##################
+
+module Isolation PhotonIsolation {
+  set CandidateInputArray PhotonEfficiency/photons
+  set IsolationInputArray EFlowMerger/eflow
+  set RhoInputArray Rho/rho
+
+  set OutputArray photons
+
+  set DeltaRMax 0.5
+
+  set PTMin 0.5
+
+  set PTRatioMax 0.1
+}
+
+#####################
+# Electron efficiency
+#####################
+
+module Efficiency ElectronEfficiency {
+  set InputArray TrackPileUpSubtractor/electrons
+  set OutputArray electrons
+
+  # set EfficiencyFormula {efficiency formula as a function of eta and pt}
+
+  # efficiency formula for electrons
+  set EfficiencyFormula {                                      (pt <= 10.0) * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 10.0)  * (0.95) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.5) * (pt > 10.0)  * (0.85) + \
+                         (abs(eta) > 2.5)                                   * (0.00)}
+}
+
+####################
+# Electron isolation
+####################
+
+module Isolation ElectronIsolation {
+  set CandidateInputArray ElectronEfficiency/electrons
+  set IsolationInputArray EFlowMerger/eflow
+  set RhoInputArray Rho/rho
+
+  set OutputArray electrons
+
+  set DeltaRMax 0.5
+
+  set PTMin 0.5
+
+  set PTRatioMax 0.1
+}
+
+#################
+# Muon efficiency
+#################
+
+module Efficiency MuonEfficiency {
+  set InputArray TrackPileUpSubtractor/muons
+  set OutputArray muons
+
+  # set EfficiencyFormula {efficiency as a function of eta and pt}
+
+  # efficiency formula for muons
+  set EfficiencyFormula {                                      (pt <= 10.0) * (0.00) + \
+                                           (abs(eta) <= 1.5) * (pt > 10.0)  * (0.95) + \
+                         (abs(eta) > 1.5 && abs(eta) <= 2.4) * (pt > 10.0)  * (0.85) + \
+                         (abs(eta) > 2.4)                                   * (0.00)}
+}
+
+################
+# Muon isolation
+################
+
+module Isolation MuonIsolation {
+  set CandidateInputArray MuonEfficiency/muons
+  set IsolationInputArray EFlowMerger/eflow
+  set RhoInputArray Rho/rho
+
+  set OutputArray muons
+
+  set DeltaRMax 0.5
+
+  set PTMin 0.5
+
+  set PTRatioMax 0.1
+}
+
+###################
+# Missing ET merger
+###################
+
+module Merger MissingET {
+# add InputArray InputArray
+  add InputArray EFlowMerger/eflow
+  set MomentumOutputArray momentum
+}
+
+##################
+# Scalar HT merger
+##################
+
+module Merger ScalarHT {
+# add InputArray InputArray
+  add InputArray UniqueObjectFinder/jets
+  add InputArray UniqueObjectFinder/electrons
+  add InputArray UniqueObjectFinder/photons
+  add InputArray MuonIsolation/muons
+  set EnergyOutputArray energy
+}
+
+
+###########
+# b-tagging
+###########
+
+module BTagging BTagging {
+  set PartonInputArray Delphes/partons
+  set JetInputArray FastJetFinder/jets
+
+  set BitNumber 0
+
+  set DeltaR 0.5
+
+  set PartonPTMin 1.0
+
+  set PartonEtaMax 2.5
+
+  # add EfficiencyFormula {abs(PDG code)} {efficiency formula as a function of eta and pt}
+  # PDG code = the highest PDG code of a quark or gluon inside DeltaR cone around jet axis
+  # gluon's PDG code has the lowest priority
+
+  # https://twiki.cern.ch/twiki/bin/view/CMSPublic/PhysicsResultsBTV
+  # default efficiency formula (misidentification rate)
+  add EfficiencyFormula {0} {0.001}
+
+  # efficiency formula for c-jets (misidentification rate)
+  add EfficiencyFormula {4} {                                      (pt <= 15.0) * (0.000) + \
+                                                (abs(eta) <= 1.2) * (pt > 15.0) * (0.2*tanh(pt*0.03 - 0.4)) + \
+                              (abs(eta) > 1.2 && abs(eta) <= 2.5) * (pt > 15.0) * (0.1*tanh(pt*0.03 - 0.4)) + \
+                              (abs(eta) > 2.5)                                  * (0.000)}
+
+  # efficiency formula for b-jets
+  add EfficiencyFormula {5} {                                      (pt <= 15.0) * (0.000) + \
+                                                (abs(eta) <= 1.2) * (pt > 15.0) * (0.5*tanh(pt*0.03 - 0.4)) + \
+                              (abs(eta) > 1.2 && abs(eta) <= 2.5) * (pt > 15.0) * (0.4*tanh(pt*0.03 - 0.4)) + \
+                              (abs(eta) > 2.5)                                  * (0.000)}
+}
+
+module TauTagging TauTagging {
+  set ParticleInputArray Delphes/allParticles
+  set PartonInputArray Delphes/partons
+  set JetInputArray FastJetFinder/jets
+
+  set DeltaR 0.5
+
+  set TauPTMin 1.0
+
+  set TauEtaMax 2.5
+
+  # add EfficiencyFormula {abs(PDG code)} {efficiency formula as a function of eta and pt}
+
+  # default efficiency formula (misidentification rate)
+  add EfficiencyFormula {0} {0.001}
+  # efficiency formula for tau-jets
+  add EfficiencyFormula {15} {0.4}
+}
+
+#####################################################
+# Find uniquely identified photons/electrons/tau/jets
+#####################################################
+
+module UniqueObjectFinder UniqueObjectFinder {
+# earlier arrays take precedence over later ones
+# add InputArray InputArray OutputArray
+  add InputArray PhotonIsolation/photons photons
+  add InputArray ElectronIsolation/electrons electrons
+  add InputArray JetPileUpSubtractor/jets jets
+}
+
+##################
+# ROOT tree writer
+##################
+
+module TreeWriter TreeWriter {
+# add Branch InputArray BranchName BranchClass
+  add Branch Delphes/allParticles Particle GenParticle
+  add Branch TrackMerger/tracks Track Track
+  add Branch Calorimeter/towers Tower Tower
+  add Branch ConstituentFilter/eflowTracks EFlowTrack Track
+  add Branch ConstituentFilter/eflowTowers EFlowTower Tower
+  add Branch ConstituentFilter/muons EFlowMuon Muon
+  add Branch GenJetFinder/jets GenJet Jet
+  add Branch UniqueObjectFinder/jets Jet Jet
+  add Branch UniqueObjectFinder/electrons Electron Electron
+  add Branch UniqueObjectFinder/photons Photon Photon
+  add Branch MuonIsolation/muons Muon Muon
+  add Branch MissingET/momentum MissingET MissingET
+  add Branch ScalarHT/energy ScalarHT ScalarHT
+  add Branch Rho/rho Rho Rho
+}
+
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootAnalysisLinkDef.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootAnalysisLinkDef.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootAnalysisLinkDef.h	(revision 5)
@@ -0,0 +1,48 @@
+
+/** \class ExRootAnalysisLinkDef
+ *
+ *  Lists classes to be included in cint dicitonary
+ *
+ *  $Date: 2008-07-08 12:01:52 $
+ *  $Revision: 1.2 $
+ *
+ *  
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "ExRootAnalysis/ExRootTreeReader.h"
+#include "ExRootAnalysis/ExRootTreeWriter.h"
+#include "ExRootAnalysis/ExRootTreeBranch.h"
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootUtilities.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+
+#include "ExRootAnalysis/ExRootProgressBar.h"
+#include "ExRootAnalysis/ExRootConfReader.h"
+#include "ExRootAnalysis/ExRootTask.h"
+
+#ifdef __CINT__
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+#pragma link C++ class ExRootTreeReader+;
+#pragma link C++ class ExRootTreeBranch+;
+#pragma link C++ class ExRootTreeWriter+;
+#pragma link C++ class ExRootResult+;
+#pragma link C++ class ExRootClassifier+;
+#pragma link C++ class ExRootFilter+;
+
+#pragma link C++ class ExRootProgressBar+;
+#pragma link C++ class ExRootConfReader+;
+#pragma link C++ class ExRootConfParam+;
+#pragma link C++ class ExRootTask+;
+
+#pragma link C++ function HistStyle;
+#pragma link C++ function FillChain;
+
+#endif
+
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootClassifier.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootClassifier.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootClassifier.h	(revision 5)
@@ -0,0 +1,17 @@
+#ifndef ExRootClassifier_h
+#define ExRootClassifier_h
+
+#include <Rtypes.h>
+
+class TObject;
+
+class ExRootClassifier
+{
+public:
+  virtual ~ExRootClassifier() {}
+  virtual Int_t GetCategory(TObject *object) = 0;
+
+};
+
+#endif /* ExRootClassifier */
+
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootConfReader.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootConfReader.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootConfReader.cc	(revision 5)
@@ -0,0 +1,326 @@
+
+/** \class ExRootConfReader
+ *
+ *  Class handling output ROOT tree
+ *
+ *  $Date: 2008-06-04 13:57:54 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "ExRootAnalysis/ExRootConfReader.h"
+
+#include "tcl/tcl.h"
+
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <string>
+#include <stdexcept>
+#include <sstream>
+
+using namespace std;
+
+static Tcl_ObjCmdProc ModuleObjCmdProc;
+
+//------------------------------------------------------------------------------
+
+ExRootConfReader::ExRootConfReader() :
+  fTclInterp(0)
+{
+  fTclInterp = Tcl_CreateInterp();
+
+  Tcl_CreateObjCommand(fTclInterp, "module", ModuleObjCmdProc, this, 0);
+}
+
+//------------------------------------------------------------------------------
+
+ExRootConfReader::~ExRootConfReader()
+{
+  Tcl_DeleteInterp(fTclInterp);
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootConfReader::ReadFile(const char *fileName)
+{
+/*
+  ifstream inputFileStream(fileName);
+  string cmdBuffer = string(istreambuf_iterator<char>(inputFileStream), istreambuf_iterator<char>());
+
+  Tcl_Obj *cmdObjPtr = Tcl_NewObj();
+  cmdObjPtr->bytes = const_cast<char *>(cmdBuffer.c_str());
+  cmdObjPtr->length = cmdBuffer.size();
+*/
+  stringstream message;
+
+  ifstream inputFileStream(fileName, ios::in | ios::ate);
+  if(!inputFileStream.is_open())
+  {
+    message << "can't open configuration file " << fileName;
+    throw runtime_error(message.str());
+  }
+
+  int file_length = inputFileStream.tellg();
+  inputFileStream.seekg(0, ios::beg);
+  inputFileStream.clear();
+  char *cmdBuffer = new char[file_length];
+  inputFileStream.read(cmdBuffer, file_length);
+
+  Tcl_Obj *cmdObjPtr = Tcl_NewObj();
+  cmdObjPtr->bytes = cmdBuffer;
+  cmdObjPtr->length = file_length;
+
+  Tcl_IncrRefCount(cmdObjPtr);
+
+  if(Tcl_EvalObj(fTclInterp, cmdObjPtr) != TCL_OK)
+  {
+    message << "can't read configuration file " << fileName << endl;
+    message << Tcl_GetStringResult(fTclInterp);
+    throw runtime_error(message.str());
+  }
+
+  cmdObjPtr->bytes = 0;
+  cmdObjPtr->length = 0;
+
+  Tcl_DecrRefCount(cmdObjPtr);
+
+  delete[] cmdBuffer;
+}
+
+//------------------------------------------------------------------------------
+
+ExRootConfParam ExRootConfReader::GetParam(const char *name)
+{
+  Tcl_Obj *object;
+  Tcl_Obj *variableName = Tcl_NewStringObj(const_cast<char *>(name),-1);
+  object = Tcl_ObjGetVar2(fTclInterp, variableName, 0, TCL_GLOBAL_ONLY);
+  return ExRootConfParam(name, object, fTclInterp);
+}
+
+//------------------------------------------------------------------------------
+
+int ExRootConfReader::GetInt(const char *name, int defaultValue, int index)
+{
+  ExRootConfParam object = GetParam(name);
+  if(index >= 0)
+  {
+    object = object[index];
+  }
+
+  return object.GetInt(defaultValue);
+}
+
+//------------------------------------------------------------------------------
+
+long ExRootConfReader::GetLong(const char *name, long defaultValue, int index)
+{
+  ExRootConfParam object = GetParam(name);
+  if(index >= 0)
+  {
+    object = object[index];
+  }
+
+  return object.GetLong(defaultValue);
+}
+
+//------------------------------------------------------------------------------
+
+double ExRootConfReader::GetDouble(const char *name, double defaultValue, int index)
+{
+  ExRootConfParam object = GetParam(name);
+  if(index >= 0)
+  {
+    object = object[index];
+  }
+
+  return object.GetDouble(defaultValue);
+}
+
+//------------------------------------------------------------------------------
+
+bool ExRootConfReader::GetBool(const char *name, bool defaultValue, int index)
+{
+  ExRootConfParam object = GetParam(name);
+  if(index >= 0)
+  {
+    object = object[index];
+  }
+
+  return object.GetBool(defaultValue);
+}
+
+//------------------------------------------------------------------------------
+
+const char *ExRootConfReader::GetString(const char *name, const char *defaultValue, int index)
+{
+  ExRootConfParam object = GetParam(name);
+  if(index >= 0)
+  {
+    object = object[index];
+  }
+
+  return object.GetString(defaultValue);
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootConfReader::AddModule(const char *className, const char *moduleName)
+{
+  ExRootTaskMap::iterator itMoudles = fModules.find(moduleName);
+
+  if(itMoudles != fModules.end())
+  {
+    cout << "** WARNING: module '" << moduleName << "' is already configured.";
+    cout << " Only first entry will be used." << endl;
+  }
+  else
+  {
+    fModules.insert(make_pair(moduleName, className));
+    cout << left;
+    cout << setw(30) << "** INFO: adding module";
+    cout << setw(25) << className;
+    cout << setw(25) << moduleName << endl;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+int ModuleObjCmdProc(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+  if(objc < 3)
+  {
+/*
+    Tcl_SetResult(interp, "wrong # args: should be \"module className moduleName arg ?arg...?\"", 0);
+*/
+    Tcl_WrongNumArgs(interp, 1, objv, "className moduleName ?arg...?");
+		return TCL_ERROR;
+  }
+
+  ExRootConfReader *test = (ExRootConfReader*) clientData;
+
+  // add module to a list of modules to be created
+
+  test->AddModule(Tcl_GetStringFromObj(objv[1], 0), Tcl_GetStringFromObj(objv[2], 0));
+
+  if(objc > 3)
+  {
+    Tcl_Obj *object = Tcl_NewListObj(0, 0);
+    Tcl_ListObjAppendElement(interp, object, Tcl_NewStringObj("namespace", -1));
+    Tcl_ListObjAppendElement(interp, object, Tcl_NewStringObj("eval", -1));
+    Tcl_ListObjAppendList(interp, object, Tcl_NewListObj(objc-2, objv+2));
+
+    return Tcl_GlobalEvalObj(interp, object);
+  }
+
+  return TCL_OK;
+}
+
+//------------------------------------------------------------------------------
+
+ExRootConfParam::ExRootConfParam(const char *name, Tcl_Obj *object, Tcl_Interp *interp) :
+  fName(name), fObject(object), fTclInterp(interp)
+{
+}
+
+//------------------------------------------------------------------------------
+
+int ExRootConfParam::GetInt(int defaultValue)
+{
+  stringstream message;
+  int result = defaultValue;
+  if(fObject && TCL_OK != Tcl_GetIntFromObj(fTclInterp, fObject, &result))
+  {
+    message << "parameter '"<< fName << "' is not an integer." << endl;
+    message << fName << " = " << Tcl_GetStringFromObj(fObject, 0);
+    throw runtime_error(message.str());
+  }
+  return result;
+}
+
+//------------------------------------------------------------------------------
+
+long ExRootConfParam::GetLong(long defaultValue)
+{
+  stringstream message;
+  long result = defaultValue;
+  if(fObject && TCL_OK != Tcl_GetLongFromObj(fTclInterp, fObject, &result))
+  {
+    message << "parameter '"<< fName << "' is not an long integer." << endl;
+    message << fName << " = " << Tcl_GetStringFromObj(fObject, 0);
+    throw runtime_error(message.str());
+  }
+  return result;
+}
+
+//------------------------------------------------------------------------------
+
+double ExRootConfParam::GetDouble(double defaultValue)
+{
+  stringstream message;
+  double result = defaultValue;
+  if(fObject && TCL_OK != Tcl_GetDoubleFromObj(fTclInterp, fObject, &result))
+  {
+    message << "parameter '"<< fName << "' is not a number." << endl;
+    message << fName << " = " << Tcl_GetStringFromObj(fObject, 0);
+    throw runtime_error(message.str());
+  }
+  return result;
+}
+
+//------------------------------------------------------------------------------
+
+bool ExRootConfParam::GetBool(bool defaultValue)
+{
+  stringstream message;
+  int result = defaultValue;
+  if(fObject && TCL_OK != Tcl_GetBooleanFromObj(fTclInterp, fObject, &result))
+  {
+    message << "parameter '"<< fName << "' is not a boolean." << endl;
+    message << fName << " = " << Tcl_GetStringFromObj(fObject, 0);
+    throw runtime_error(message.str());
+  }
+  return result;
+}
+
+//------------------------------------------------------------------------------
+
+const char *ExRootConfParam::GetString(const char *defaultValue)
+{
+  const char *result = defaultValue;
+  if(fObject) result = Tcl_GetStringFromObj(fObject, 0);
+  return result;  
+}
+
+//------------------------------------------------------------------------------
+
+int ExRootConfParam::GetSize()
+{
+  stringstream message;
+  int length = 0;
+  if(fObject && TCL_OK != Tcl_ListObjLength(fTclInterp, fObject, &length))
+  {
+    message << "parameter '"<< fName << "' is not a list." << endl;
+    message << fName << " = " << Tcl_GetStringFromObj(fObject, 0);
+    throw runtime_error(message.str());
+  }
+  return length;  
+}
+
+//------------------------------------------------------------------------------
+
+ExRootConfParam ExRootConfParam::operator[](int index)
+{
+  stringstream message;
+  Tcl_Obj *object = 0;
+  if(fObject && TCL_OK != Tcl_ListObjIndex(fTclInterp, fObject, index, &object))
+  {
+    message << "parameter '"<< fName << "' is not a list." << endl;
+    message << fName << " = " << Tcl_GetStringFromObj(fObject, 0);
+    throw runtime_error(message.str());
+  }
+  return ExRootConfParam(fName, object, fTclInterp);
+}
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootConfReader.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootConfReader.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootConfReader.h	(revision 5)
@@ -0,0 +1,79 @@
+#ifndef ExRootConfReader_h
+#define ExRootConfReader_h
+
+/** \class ExRootConfReader
+ *
+ *  Class handling output ROOT tree
+ *
+ *  $Date: 2008-06-04 13:57:24 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "TNamed.h"
+
+#include <map>
+#include <utility>
+
+struct Tcl_Obj;
+struct Tcl_Interp;
+
+class ExRootConfParam
+{
+public:
+
+  ExRootConfParam(const char *name = 0, Tcl_Obj *object = 0, Tcl_Interp *interp = 0);
+
+  int GetInt(int defaultValue = 0);
+  long GetLong(long defaultValue = 0);
+  double GetDouble(double defaultValue = 0.0);
+  bool GetBool(bool defaultValue = false);
+  const char *GetString(const char *defaultValue = "");
+
+  int GetSize();
+  ExRootConfParam operator[](int index);
+
+private:
+
+  const char *fName; //!
+  Tcl_Obj *fObject; //!
+  Tcl_Interp *fTclInterp; //!
+};
+
+//------------------------------------------------------------------------------
+
+class ExRootConfReader : public TNamed
+{
+public:
+  typedef std::map<TString, TString> ExRootTaskMap;
+
+  ExRootConfReader();
+  ~ExRootConfReader();
+
+  void ReadFile(const char *fileName);
+
+  int GetInt(const char *name, int defaultValue, int index = -1);
+  long GetLong(const char *name, long defaultValue, int index = -1);
+  double GetDouble(const char *name, double defaultValue, int index = -1);
+  bool GetBool(const char *name, bool defaultValue, int index = -1);
+  const char *GetString(const char *name, const char *defaultValue, int index = -1);
+  ExRootConfParam GetParam(const char *name);
+
+  const ExRootTaskMap *GetModules() const { return &fModules; }
+
+  void AddModule(const char *className, const char *moduleName);
+
+private:
+
+  Tcl_Interp *fTclInterp; //!
+
+  ExRootTaskMap fModules; //!
+
+  ClassDef(ExRootConfReader, 1)
+};
+
+#endif
+
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootFilter.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootFilter.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootFilter.cc	(revision 5)
@@ -0,0 +1,138 @@
+
+/** \class ExRootFilter
+ *
+ *  Class simplifying classification and subarrays handling
+ *
+ *  $Date: 2008-06-04 13:57:55 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TSeqCollection.h"
+#include "TObjArray.h"
+
+#include <iostream>
+#include <stdexcept>
+#include <sstream>
+
+using namespace std;
+
+typedef map<Int_t, TObjArray*> TCategoryMap;
+typedef map<ExRootClassifier*, pair<Bool_t, TCategoryMap> > TClassifierMap;
+
+ExRootFilter::ExRootFilter(const TSeqCollection *collection) :
+  fCollection(collection)
+{
+  fIter = fCollection->MakeIterator();
+}
+
+//------------------------------------------------------------------------------
+
+ExRootFilter::~ExRootFilter()
+{
+  TClassifierMap::iterator itMap;
+  TCategoryMap::iterator itSubMap;
+  for(itMap = fMap.begin(); itMap != fMap.end(); ++itMap)
+  {
+    for(itSubMap = itMap->second.second.begin();
+        itSubMap != itMap->second.second.end(); ++itSubMap)
+    {
+      delete (itSubMap->second);
+    }
+  }
+
+  delete fIter;
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootFilter::Reset(ExRootClassifier *classifier)
+{
+  TClassifierMap::iterator itMap;
+  TCategoryMap::iterator itSubMap;
+  if(classifier)
+  {
+    itMap = fMap.find(classifier);
+    if(itMap != fMap.end())
+    {
+      itMap->second.first = kTRUE;
+      for(itSubMap = itMap->second.second.begin();
+          itSubMap != itMap->second.second.end(); ++itSubMap)
+      {
+        itSubMap->second->Clear();
+      }
+    }
+  }
+  else
+  {
+    for(itMap = fMap.begin(); itMap != fMap.end(); ++itMap)
+    {
+      itMap->second.first = kTRUE;
+      for(itSubMap = itMap->second.second.begin();
+          itSubMap != itMap->second.second.end(); ++itSubMap)
+      {
+        itSubMap->second->Clear();
+      }
+    }
+  }
+}
+
+//------------------------------------------------------------------------------
+
+TObjArray *ExRootFilter::GetSubArray(ExRootClassifier *classifier, Int_t category)
+{
+  Int_t result;
+  TObject *element;
+  TObjArray *array;
+  TCategoryMap::iterator itSubMap;
+  pair<TCategoryMap::iterator, bool> pairSubMap;
+  pair<TClassifierMap::iterator, bool> pairMap;
+
+  TClassifierMap::iterator itMap = fMap.find(classifier);
+  if(itMap == fMap.end())
+  {
+    pairMap = fMap.insert(make_pair(classifier, make_pair(kTRUE, TCategoryMap())));
+    if(!pairMap.second)
+    {
+      throw runtime_error("can't insert category map");
+    }
+
+    itMap = pairMap.first;
+  }
+
+  if(itMap->second.first)
+  {
+    itMap->second.first = kFALSE;
+    fIter->Reset();
+    while((element = fIter->Next()) != 0)
+    {
+      result = classifier->GetCategory(element);
+      if(result < 0) continue;
+      itSubMap = itMap->second.second.find(result);
+      if(itSubMap == itMap->second.second.end())
+      {
+        array = new TObjArray(fCollection->GetSize());
+        pairSubMap = itMap->second.second.insert(make_pair(result, array));
+        if(!pairSubMap.second)
+        {
+          throw runtime_error("can't insert category");
+        }
+
+        itSubMap = pairSubMap.first;
+      }
+      itSubMap->second->Add(element);
+    }
+  }
+
+  itSubMap = itMap->second.second.find(category);
+  return (itSubMap != itMap->second.second.end()) ? itSubMap->second : 0;
+}
+
+//------------------------------------------------------------------------------
+
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootFilter.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootFilter.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootFilter.h	(revision 5)
@@ -0,0 +1,34 @@
+#ifndef ExRootFilter_h
+#define ExRootFilter_h
+
+#include "Rtypes.h"
+
+#include <map>
+
+class ExRootClassifier;
+class TSeqCollection;
+class TObjArray;
+class TIterator;
+
+class ExRootFilter
+{
+public:
+
+  ExRootFilter(const TSeqCollection *collection);
+  ~ExRootFilter();
+
+  void Reset(ExRootClassifier *classifier = 0);
+
+  TObjArray *GetSubArray(ExRootClassifier *classifier, Int_t category);
+
+private:
+
+  const TSeqCollection *fCollection; //!
+  TIterator *fIter; //!
+
+  std::map<ExRootClassifier*, std::pair<Bool_t, std::map<Int_t, TObjArray*> > > fMap; //!
+
+};
+
+#endif /* ExRootFilter */
+
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootProgressBar.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootProgressBar.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootProgressBar.cc	(revision 5)
@@ -0,0 +1,83 @@
+
+/** \class ExRootProgressBar
+ *
+ *  Class showing progress bar
+ *
+ *  $Date: 2008-06-04 13:57:55 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "ExRootAnalysis/ExRootProgressBar.h"
+
+#include "TSystem.h"
+
+#include <iostream>
+
+#include <string.h>
+#include <stdio.h>
+
+using namespace std;
+
+ExRootProgressBar::ExRootProgressBar(Long64_t entries, Int_t width) :
+  fEntries(entries), fEventCounter(0), fWidth(width), fTime(0), fHashes(-1), fBar(0)
+{
+  fBar = new char[width + 1];
+  memset(fBar, '-', width);
+  fBar[width] = 0;
+}
+
+//------------------------------------------------------------------------------
+
+ExRootProgressBar::~ExRootProgressBar()
+{
+  if(fBar) delete[] fBar;
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootProgressBar::Update(Long64_t entry, Long64_t eventCounter, Bool_t last)
+{
+  ULong64_t time = gSystem->Now();
+
+  if(time < fTime + 500 && entry < fEntries && !last) return;
+
+  fTime = time;
+
+  if(fEntries > 0)
+  {
+    Int_t hashes = Int_t(Double_t(entry)/fEntries*fWidth);
+    if(hashes > fWidth) hashes = fWidth;
+    if(hashes != fHashes)
+    {
+      memset(fBar, '#', hashes);
+      memset(fBar + hashes, '-', fWidth - hashes);
+      fHashes = hashes;
+      fprintf(stderr, "** [%s] (%.2f%%)\r", fBar, Float_t(entry)/fEntries*100.0);
+    }
+  }
+  else
+  {
+    if(eventCounter > fEventCounter)
+    {
+      fEventCounter = eventCounter;
+      fprintf(stderr, "** %lld events processed\r", eventCounter);
+    }
+  }
+
+  fflush(stderr);
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootProgressBar::Finish()
+{
+  fprintf(stderr, "\n");
+  fflush(stderr);
+}
+
+//------------------------------------------------------------------------------
+
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootProgressBar.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootProgressBar.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootProgressBar.h	(revision 5)
@@ -0,0 +1,29 @@
+#ifndef ExRootProgressBar_h
+#define ExRootProgressBar_h
+
+#include "Rtypes.h"
+
+class ExRootProgressBar
+{
+public:
+
+  ExRootProgressBar(Long64_t entries, Int_t width = 64);
+  ~ExRootProgressBar();
+
+  void Update(Long64_t entry, Long64_t eventCounter = 0, Bool_t last = kFALSE);
+  void Finish();
+
+private:
+
+  Long64_t fEntries, fEventCounter;
+  Int_t fWidth;
+
+  ULong64_t fTime;
+  Int_t fHashes;
+
+  char *fBar; //!
+
+};
+
+#endif /* ExRootProgressBar */
+
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootResult.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootResult.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootResult.cc	(revision 5)
@@ -0,0 +1,450 @@
+
+/** \class ExRootResult
+ *
+ *  Class simplifying work with histograms
+ *
+ *  $Date: 2008-06-04 13:57:56 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "ExRootAnalysis/ExRootResult.h"
+
+#include "ExRootAnalysis/ExRootUtilities.h"
+
+#include "TROOT.h"
+#include "TFile.h"
+#include "TClass.h"
+#include "TStyle.h"
+#include "TCanvas.h"
+#include "TLegend.h"
+#include "TPaveText.h"
+#include "TPaveStats.h"
+#include "TList.h"
+#include "TH2.h"
+#include "THStack.h"
+#include "TProfile.h"
+#include "TObjArray.h"
+#include "TFolder.h"
+
+#include <iostream>
+
+using namespace std;
+
+static const Font_t kExRootFont = 42;
+static const Float_t kExRootFontSize = 0.04;
+static const Color_t kExRootBackgroundColor = 10;
+
+//------------------------------------------------------------------------------
+
+ExRootResult::ExRootResult() : fCanvas(0), fFolder(0)
+{
+}
+
+//------------------------------------------------------------------------------
+
+ExRootResult::~ExRootResult()
+{
+  set<TObject*>::iterator itPool;
+  for(itPool = fPool.begin(); itPool != fPool.end(); ++itPool)
+  {
+    delete *itPool;
+  }
+
+  if(fCanvas) delete fCanvas;
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootResult::Reset()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootResult::Write(const char *fileName)
+{
+  TObject *object;
+  TDirectory *currentDirectory = gDirectory;
+  TFile *file = new TFile(fileName, "RECREATE");
+  file->cd();
+  std::map<TObject*, PlotSettings>::iterator itPlotMap;
+  for(itPlotMap = fPlotMap.begin(); itPlotMap != fPlotMap.end(); ++itPlotMap)
+  {
+    object = itPlotMap->first;
+    object->Write();
+  }
+  currentDirectory->cd();
+  delete file;
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootResult::CreateCanvas()
+{
+  TDirectory *currentDirectory = gDirectory;
+
+  // Graphics style parameters to avoid grey background on figures
+  gStyle->SetCanvasColor(kExRootBackgroundColor);
+  gStyle->SetStatColor(kExRootBackgroundColor);
+  //  gStyle->SetTitleColor(kExRootBackgroundColor);
+  gStyle->SetPadColor(kExRootBackgroundColor);
+
+  gStyle->SetPadTopMargin(0.10);
+  gStyle->SetPadRightMargin(0.10);
+  gStyle->SetPadBottomMargin(0.15);
+  gStyle->SetPadLeftMargin(0.15);
+
+  gStyle->SetStatFont(kExRootFont);
+  gStyle->SetStatFontSize(kExRootFontSize);
+
+  gStyle->SetTitleFont(kExRootFont, "");
+  gStyle->SetTitleFont(kExRootFont, "X");
+  gStyle->SetTitleFont(kExRootFont, "Y");
+  gStyle->SetTitleFont(kExRootFont, "Z");
+  gStyle->SetTitleSize(kExRootFontSize, "");
+  gStyle->SetTitleSize(kExRootFontSize, "X");
+  gStyle->SetTitleSize(kExRootFontSize, "Y");
+  gStyle->SetTitleSize(kExRootFontSize, "Z");
+
+  gStyle->SetLabelFont(kExRootFont, "X");
+  gStyle->SetLabelFont(kExRootFont, "Y");
+  gStyle->SetLabelFont(kExRootFont, "Z");
+  gStyle->SetLabelSize(kExRootFontSize, "X");
+  gStyle->SetLabelSize(kExRootFontSize, "Y");
+  gStyle->SetLabelSize(kExRootFontSize, "Z");
+
+  gStyle->SetPadTickX(1);
+  gStyle->SetPadTickY(1);
+
+  gStyle->SetTextFont(kExRootFont);
+  gStyle->SetTextSize(kExRootFontSize);
+
+  gStyle->SetOptStat(111110);
+  // gStyle->SetOptFit(101);
+
+  fCanvas = static_cast<TCanvas*>(gROOT->FindObject("c1"));
+  if(fCanvas)
+  {
+    fCanvas->Clear();
+    fCanvas->UseCurrentStyle();
+    fCanvas->SetWindowSize(800, 650);
+  }
+  else
+  {
+    fCanvas = new TCanvas("c1", "c1", 800, 650);
+  }
+  fCanvas->SetLogy(0);
+  fCanvas->SetHighLightColor(kExRootBackgroundColor);
+
+  currentDirectory->cd();
+}
+
+//------------------------------------------------------------------------------
+
+TCanvas *ExRootResult::GetCanvas()
+{
+  if(!fCanvas) CreateCanvas();
+  return fCanvas;
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootResult::Attach(TObject *plot, TObject *object)
+{
+  if(!plot) return;
+
+  std::map<TObject*, PlotSettings>::iterator itPlotMap = fPlotMap.find(plot);
+  if(itPlotMap != fPlotMap.end())
+  {
+    TObjArray *attachments = itPlotMap->second.attachments;
+    if(!attachments)
+    {
+      attachments = new TObjArray();
+      itPlotMap->second.attachments = attachments;
+    }
+    attachments->Add(object);
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootResult::PrintPlot(TObject *plot, const char *sufix, const char *format)
+{
+  if(!plot) return;
+
+  TCanvas *canvas = GetCanvas();
+  TH1 *histogram = 0;
+
+  if(plot->IsA()->InheritsFrom(TH1::Class()))
+  {
+    histogram = static_cast<TH1*>(plot);
+  }
+
+  map<TObject*, PlotSettings>::iterator itPlotMap = fPlotMap.find(plot);
+  if(itPlotMap != fPlotMap.end())
+  {
+    PlotSettings settings = itPlotMap->second;
+
+    canvas->SetLogx(settings.logx);
+    if(histogram == 0 || histogram->Integral() > 0.0)
+    {
+      canvas->SetLogy(settings.logy);
+    }
+    else
+    {
+      canvas->SetLogy(0);
+    }
+
+    if(settings.attachments)
+    {
+      TIter iterator(settings.attachments);
+      TObject *object;
+      while((object = iterator()))
+      {
+        object->Draw();
+      }
+    }
+  }
+
+  TString name = plot->GetName();
+  canvas->Print(name + sufix + "." + format);
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootResult::Print(const char *format)
+{
+  PlotSettings settings;
+  TObject *object;
+  TH1 *histogram;
+  THStack *stack;
+  TPaveStats *stats;
+  TString name;
+
+  TCanvas *canvas = GetCanvas();
+
+  map<TObject*, PlotSettings>::iterator itPlotMap;
+
+  for(itPlotMap = fPlotMap.begin(); itPlotMap != fPlotMap.end(); ++itPlotMap)
+  {
+    object = itPlotMap->first;
+    settings = itPlotMap->second;
+    name = object->GetName();
+    histogram = 0;
+    stack = 0;
+
+    if(object->IsA()->InheritsFrom(TH1::Class()))
+    {
+      histogram = static_cast<TH1*>(object);
+    }
+    else if(object->IsA()->InheritsFrom(THStack::Class()))
+    {
+      stack = static_cast<THStack*>(object);
+      histogram = static_cast<TH1*>(stack->GetHists()->First());
+    }
+
+    canvas->SetLogx(settings.logx);
+    if(histogram == 0 || histogram->Integral() > 0.0)
+    {
+      canvas->SetLogy(settings.logy);
+    }
+    else
+    {
+      canvas->SetLogy(0);
+    }
+
+    if(object->IsA()->InheritsFrom(THStack::Class()))
+    {
+      object->Draw("nostack");
+      stack->GetXaxis()->SetTitle(histogram->GetXaxis()->GetTitle());
+      stack->GetYaxis()->SetTitle(histogram->GetYaxis()->GetTitle());
+      stack->GetXaxis()->SetTitleOffset(1.5);
+      stack->GetYaxis()->SetTitleOffset(1.75);
+    }
+    else
+    {
+      object->Draw();
+    }
+
+    canvas->Update();
+
+    if(histogram)
+    {
+      stats = static_cast<TPaveStats*>(histogram->FindObject("stats"));
+      if(stats)
+      {
+        stats->SetX1NDC(0.67);
+        stats->SetX2NDC(0.99);
+        stats->SetY1NDC(0.77);
+        stats->SetY2NDC(0.99);
+        stats->SetTextFont(kExRootFont);
+        stats->SetTextSize(kExRootFontSize);
+        canvas->Draw();
+      }
+    }
+
+    if(settings.attachments)
+    {
+      TIter iterator(settings.attachments);
+      while((object = iterator()))
+      {
+        object->Draw();
+      }
+    }
+
+    canvas->Print(name + "." + format);
+  }
+}
+
+//------------------------------------------------------------------------------
+
+TH1 *ExRootResult::AddHist1D(const char *name, const char *title,
+                             const char *xlabel, const char *ylabel,
+                             Int_t nxbins, Axis_t xmin, Axis_t xmax,
+                             Int_t logx, Int_t logy)
+{
+  TH1F *hist = new TH1F(name, title, nxbins, xmin, xmax);
+  PlotSettings settings;
+  settings.logx = logx;
+  settings.logy = logy;
+  settings.attachments = 0;
+
+  hist->GetXaxis()->SetTitle(xlabel);
+  hist->GetYaxis()->SetTitle(ylabel);
+
+  fPool.insert(hist);
+  fPlotMap[hist] = settings;
+
+  HistStyle(hist, kFALSE);
+  if(fFolder) fFolder->Add(hist);
+  return hist;
+}
+
+//------------------------------------------------------------------------------
+
+TH1 *ExRootResult::AddHist1D(const char *name, const char *title,
+                             const char *xlabel, const char *ylabel,
+                             Int_t nxbins, const Float_t *bins,
+                             Int_t logx, Int_t logy)
+{
+  TH1F *hist = new TH1F(name, title, nxbins, bins);
+  PlotSettings settings;
+  settings.logx = logx;
+  settings.logy = logy;
+  settings.attachments = 0;
+
+  hist->GetXaxis()->SetTitle(xlabel);
+  hist->GetYaxis()->SetTitle(ylabel);
+
+  fPool.insert(hist);
+  fPlotMap[hist] = settings;
+
+  HistStyle(hist, kFALSE);
+  if(fFolder) fFolder->Add(hist);
+  return hist;
+}
+
+//------------------------------------------------------------------------------
+
+TProfile *ExRootResult::AddProfile(const char *name, const char *title,
+                                   const char *xlabel, const char *ylabel,
+                                   Int_t nxbins, Axis_t xmin, Axis_t xmax,
+                                   Int_t logx, Int_t logy)
+{
+  TProfile *profile = new TProfile(name, title, nxbins, xmin, xmax);
+  PlotSettings settings;
+  settings.logx = logx;
+  settings.logy = logy;
+  settings.attachments = 0;
+
+  profile->GetXaxis()->SetTitle(xlabel);
+  profile->GetYaxis()->SetTitle(ylabel);
+
+  fPool.insert(profile);
+  fPlotMap[profile] = settings;
+
+  HistStyle(profile, kFALSE);
+  if(fFolder) fFolder->Add(profile);
+  return profile;
+}
+
+//------------------------------------------------------------------------------
+
+TH2 *ExRootResult::AddHist2D(const char *name, const char *title,
+                             const char *xlabel, const char *ylabel,
+                             Int_t nxbins, Axis_t xmin, Axis_t xmax,
+                             Int_t nybins, Axis_t ymin, Axis_t ymax,
+                             Int_t logx, Int_t logy)
+{
+  TH2F *hist = new TH2F(name, title, nxbins, xmin, xmax, nybins, ymin, ymax);
+  PlotSettings settings;
+  settings.logx = logx;
+  settings.logy = logy;
+  settings.attachments = 0;
+
+  hist->GetXaxis()->SetTitle(xlabel);
+  hist->GetYaxis()->SetTitle(ylabel);
+
+  fPool.insert(hist);
+  fPlotMap[hist] = settings;
+
+  HistStyle(hist, kFALSE);
+  if(fFolder) fFolder->Add(hist);
+  return hist;
+}
+
+//------------------------------------------------------------------------------
+
+THStack *ExRootResult::AddHistStack(const char *name, const char *title)
+{
+  THStack *stack = new THStack(name, title);
+  PlotSettings settings;
+  settings.logx = 0;
+  settings.logy = 0;
+  settings.attachments = 0;
+
+  fPool.insert(stack);
+  fPlotMap[stack] = settings;
+
+  if(fFolder) fFolder->Add(stack);
+  return stack;
+}
+
+//------------------------------------------------------------------------------
+
+TPaveText *ExRootResult::AddComment(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
+{
+  TPaveText *comment = new TPaveText(x1, y1, x2, y2, "brNDC");
+
+  comment->SetTextSize(kExRootFontSize);
+  comment->SetTextFont(kExRootFont);
+  comment->SetTextAlign(22);
+  comment->SetFillColor(kExRootBackgroundColor);
+  comment->SetBorderSize(2);
+
+  fPool.insert(comment);
+
+  return comment;
+}
+
+//------------------------------------------------------------------------------
+
+TLegend *ExRootResult::AddLegend(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
+{
+  TLegend *legend = new TLegend(x1, y1, x2, y2);
+
+  legend->SetTextSize(kExRootFontSize);
+  legend->SetTextFont(kExRootFont);
+  legend->SetFillColor(kExRootBackgroundColor);
+  legend->SetBorderSize(2);
+
+  fPool.insert(legend);
+
+  return legend;
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootResult.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootResult.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootResult.h	(revision 5)
@@ -0,0 +1,90 @@
+#ifndef ExRootResult_h
+#define ExRootResult_h
+
+#include "Rtypes.h"
+#include "Gtypes.h"
+#include "TMath.h"
+
+#include <set>
+#include <map>
+
+class TH1;
+class TH2;
+class THStack;
+class TCanvas;
+class TLegend;
+class TProfile;
+class TPaveText;
+class TObjArray;
+class TFolder;
+
+class ExRootResult
+{
+
+public:
+
+  ExRootResult();
+  ~ExRootResult();
+
+  void Reset();
+  void Write(const char *fileName = "results.root");
+  void Print(const char *format = "eps");
+
+  TH1 *AddHist1D(const char *name, const char *title,
+                 const char *xlabel, const char *ylabel,
+                 Int_t nxbins, Axis_t xmin, Axis_t xmax,
+                 Int_t logx = 0, Int_t logy = 0);
+
+  TH1 *AddHist1D(const char *name, const char *title,
+                 const char *xlabel, const char *ylabel,
+                 Int_t nxbins, const Float_t *bins,
+                 Int_t logx = 0, Int_t logy = 0);
+
+  TProfile *AddProfile(const char *name, const char *title,
+                       const char *xlabel, const char *ylabel,
+                       Int_t nxbins, Axis_t xmin, Axis_t xmax,
+                       Int_t logx = 0, Int_t logy = 0);
+
+  TH2 *AddHist2D(const char *name, const char *title,
+                 const char *xlabel, const char *ylabel,
+                 Int_t nxbins, Axis_t xmin, Axis_t xmax,
+                 Int_t nybins, Axis_t ymin, Axis_t ymax,
+                 Int_t logx = 0, Int_t logy = 0);
+
+  THStack *AddHistStack(const char *name, const char *title);
+
+  TLegend *AddLegend(Double_t x1, Double_t y1, Double_t x2, Double_t y2);
+
+  TPaveText *AddComment(Double_t x1, Double_t y1, Double_t x2, Double_t y2);
+
+  void Attach(TObject *plot, TObject *object);
+
+  TCanvas *GetCanvas();
+
+  void PrintPlot(TObject *plot, const char *sufix = "",  const char *format = "eps");
+
+  void SetFolder(TFolder *folder) { fFolder = folder; }
+
+private:
+
+  struct PlotSettings
+  {
+    Int_t logx;
+    Int_t logy;
+    TObjArray *attachments;
+  };
+
+  void CreateCanvas();
+
+  TCanvas *fCanvas; //!
+
+  std::set<TObject*> fPool; //!
+
+  std::map<TObject*, PlotSettings> fPlotMap; //!
+
+  TFolder *fFolder; //!
+
+};
+
+#endif /* ExRootResult_h */
+
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTask.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTask.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTask.cc	(revision 5)
@@ -0,0 +1,316 @@
+
+/** \class ExRootTask
+ *
+ *  Class handling output ROOT tree
+ *
+ *  $Date: 2008-06-04 13:57:56 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "ExRootAnalysis/ExRootTask.h"
+#include "ExRootAnalysis/ExRootConfReader.h"
+
+#include "TROOT.h"
+#include "TClass.h"
+#include "TFolder.h"
+#include "TString.h"
+
+#include <iostream>
+#include <iomanip>
+#include <stdexcept>
+#include <sstream>
+
+static const char *const kINIT = "0";
+static const char *const kPROCESS = "1";
+static const char *const kFINISH = "2";
+
+using namespace std;
+
+ExRootTask::ExRootTask() :
+  TTask("", ""), fFolder(0), fConfReader(0)
+{
+}
+
+//------------------------------------------------------------------------------
+
+ExRootTask::~ExRootTask()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootTask::Init()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootTask::Process()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootTask::Finish()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootTask::Exec(Option_t *option)
+{
+  if(option == kINIT)
+  {
+    cout << left;
+    cout << setw(30) << "** INFO: initializing module";
+    cout << setw(25) << GetName() << endl;
+    Init();
+  }
+  else if(option == kPROCESS)
+  {
+    Process();
+  }
+  else if(option == kFINISH)
+  {
+    Finish();
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootTask::InitTask()
+{
+  ExecuteTask(kINIT);
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootTask::ProcessTask()
+{
+  ExecuteTask(kPROCESS);
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootTask::FinishTask()
+{
+  ExecuteTask(kFINISH);
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootTask::InitSubTasks()
+{
+  ExecuteTasks(kINIT);
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootTask::ProcessSubTasks()
+{
+  ExecuteTasks(kPROCESS);
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootTask::FinishSubTasks()
+{
+  ExecuteTasks(kFINISH);
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootTask::Add(TTask *task)
+{
+  stringstream message;
+
+  if(!task) return;
+
+  if(!task->IsA()->InheritsFrom(ExRootTask::Class()))
+  {
+    message << "task '" << task->IsA()->GetName();
+    message << "' does not inherit from ExRootTask";
+    throw runtime_error(message.str());
+  }
+
+  TTask::Add(task);
+}
+
+//------------------------------------------------------------------------------
+
+ExRootTask *ExRootTask::NewTask(TClass *cl, const char *taskName)
+{
+  stringstream message;
+
+  if(!cl) return 0;
+ 
+  if(!cl->InheritsFrom(ExRootTask::Class()))
+  {
+    message << "task '" << cl->GetName();
+    message << "' does not inherit from ExRootTask";
+    throw runtime_error(message.str());
+  }
+
+  ExRootTask *task = static_cast<ExRootTask *>(cl->New());
+  task->SetName(taskName);
+  task->SetFolder(fFolder);
+  task->SetConfReader(fConfReader);
+
+  return task;
+}
+
+//------------------------------------------------------------------------------
+
+ExRootTask *ExRootTask::NewTask(const char *className, const char *taskName)
+{
+  stringstream message;
+  TClass *cl = gROOT->GetClass(className);
+  if(!cl)
+  {
+    message << "can't find class '" << className << "'";
+    throw runtime_error(message.str());
+  }
+
+  return NewTask(cl, taskName);
+}
+
+//------------------------------------------------------------------------------
+
+const ExRootConfReader::ExRootTaskMap *ExRootTask::GetModules()
+{
+  if(fConfReader)
+  {
+    return fConfReader->GetModules();
+  }
+  else
+  {
+    return 0;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+ExRootConfParam ExRootTask::GetParam(const char *name)
+{
+  if(fConfReader)
+  {
+    return fConfReader->GetParam(TString(GetName()) + "::" + name);
+  }
+  else
+  {
+    return ExRootConfParam(TString(GetName()) + "::" + name, 0, 0);
+  }
+}
+
+//------------------------------------------------------------------------------
+
+int ExRootTask::GetInt(const char *name, int defaultValue, int index)
+{
+  if(fConfReader)
+  {
+    return fConfReader->GetInt(TString(GetName()) + "::" + name, defaultValue, index);
+  }
+  else
+  {
+    return defaultValue;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+long ExRootTask::GetLong(const char *name, long defaultValue, int index)
+{
+  if(fConfReader)
+  {
+    return fConfReader->GetLong(TString(GetName()) + "::" + name, defaultValue, index);
+  }
+  else
+  {
+    return defaultValue;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+double ExRootTask::GetDouble(const char *name, double defaultValue, int index)
+{
+  if(fConfReader)
+  {
+    return fConfReader->GetDouble(TString(GetName()) + "::" + name, defaultValue, index);
+  }
+  else
+  {
+    return defaultValue;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+bool ExRootTask::GetBool(const char *name, bool defaultValue, int index)
+{
+  if(fConfReader)
+  {
+    return fConfReader->GetBool(TString(GetName()) + "::" + name, defaultValue, index);
+  }
+  else
+  {
+    return defaultValue;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+const char *ExRootTask::GetString(const char *name, const char *defaultValue, int index)
+{
+  if(fConfReader)
+  {
+    return fConfReader->GetString(TString(GetName()) + "::" + name, defaultValue, index);
+  }
+  else
+  {
+    return defaultValue;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+TFolder *ExRootTask::NewFolder(const char *name)
+{
+  stringstream message;
+  TFolder *folder;
+  folder = static_cast<TFolder *>(GetObject(name, TFolder::Class()));
+  if(!folder) folder = GetFolder()->AddFolder(name, "");
+  if(!folder)
+  {
+    message << "can't create folder '" << name << "'";
+    throw runtime_error(message.str());
+  }
+  folder = folder->AddFolder(GetName(), GetTitle());
+  if(!folder)
+  {
+    message << "can't create folder '";
+    message << name << "/" << GetName() << "'";
+    throw runtime_error(message.str());
+  }
+  return folder;
+}
+
+//------------------------------------------------------------------------------
+
+TObject *ExRootTask::GetObject(const char *name, TClass *cl)
+{
+  stringstream message;
+  TObject *object = GetFolder()->FindObject(name);
+  if(object && object->IsA() != cl)
+  {
+    message << "object '" << name;
+    message << "' is not of class '" << cl->GetName() << "'";
+    throw runtime_error(message.str());
+  }
+  return object;
+}
+
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTask.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTask.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTask.h	(revision 5)
@@ -0,0 +1,77 @@
+#ifndef ExRootTask_h
+#define ExRootTask_h
+
+/** \class ExRootTask
+ *
+ *  Class handling output ROOT tree
+ *
+ *  $Date: 2008-06-04 13:57:26 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "TTask.h"
+
+#include "ExRootAnalysis/ExRootConfReader.h"
+
+class TClass;
+class TFolder;
+
+class ExRootTask : public TTask
+{
+public:
+
+  ExRootTask();
+  virtual ~ExRootTask();
+
+  virtual void Init();
+  virtual void Process();
+  virtual void Finish();
+
+  virtual void InitTask();
+  virtual void ProcessTask();
+  virtual void FinishTask();
+
+  virtual void InitSubTasks();
+  virtual void ProcessSubTasks();
+  virtual void FinishSubTasks();
+
+  void Add(TTask *task);
+
+  ExRootTask *NewTask(TClass *cl, const char *name);
+  ExRootTask *NewTask(const char *className, const char *taskName);
+
+  void Exec(Option_t* option);
+
+  int GetInt(const char *name, int defaultValue, int index = -1);
+  long GetLong(const char *name, long defaultValue, int index = -1);
+  double GetDouble(const char *name, double defaultValue, int index = -1);
+  bool GetBool(const char *name, bool defaultValue, int index = -1);
+  const char *GetString(const char *name, const char *defaultValue, int index = -1);
+  ExRootConfParam GetParam(const char *name);
+  const ExRootConfReader::ExRootTaskMap *GetModules();
+
+  void SetFolder(TFolder *folder) { fFolder = folder; }
+  void SetConfReader(ExRootConfReader *conf) { fConfReader = conf; }
+
+protected:
+
+  TFolder *GetFolder() const { return fFolder; }
+  ExRootConfReader *GetConfReader() const { return fConfReader; }
+
+  TFolder *NewFolder(const char *name);
+  TObject *GetObject(const char *name, TClass *cl);
+
+private:
+
+  TFolder *fFolder; //!
+  ExRootConfReader *fConfReader; //!
+
+  ClassDef(ExRootTask, 1)
+};
+
+#endif /* ExRootTask */
+
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeBranch.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeBranch.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeBranch.cc	(revision 5)
@@ -0,0 +1,95 @@
+
+/** \class ExRootTreeBranch
+*
+*  Class handling object creation
+*  It is also used for output ROOT tree branches
+*
+*  $Date: 2008-06-04 13:57:56 $
+*  $Revision: 1.1 $
+*
+*
+*  \author P. Demin - UCL, Louvain-la-Neuve
+*
+*/
+
+#include "ExRootAnalysis/ExRootTreeBranch.h"
+
+#include "TFile.h"
+#include "TTree.h"
+#include "TString.h"
+#include "TClonesArray.h"
+
+#include <iostream>
+#include <stdexcept>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+ExRootTreeBranch::ExRootTreeBranch(const char *name, TClass *cl, TTree *tree) :
+  fSize(0), fCapacity(1), fData(0)
+{
+  stringstream message;
+//  cl->IgnoreTObjectStreamer();
+//  cl->BypassStreamer();
+  fData = new TClonesArray(cl, fCapacity);
+
+  if(fData)
+  {
+    fData->SetName(name);
+    fData->ExpandCreateFast(fCapacity);
+    fData->Clear();
+    if(tree)
+    {
+      tree->Branch(name, &fData, 64000);
+      tree->Branch(TString(name) + "_size", &fSize, TString(name) + "_size/I");
+    }
+  }
+  else
+  {
+    message << "can't create TClonesArray for branch '" << name << "'";
+    throw runtime_error(message.str());
+  }
+}
+
+//------------------------------------------------------------------------------
+
+ExRootTreeBranch::~ExRootTreeBranch()
+{
+  if(fData) delete fData;
+}
+
+//------------------------------------------------------------------------------
+
+TObject *ExRootTreeBranch::NewEntry()
+{
+  if(!fData) return 0;
+
+  if(fSize >= fCapacity)
+  {
+    if(fCapacity < 10) fCapacity = 10;
+    else if(fCapacity < 30) fCapacity = 30;
+    else if(fCapacity < 100) fCapacity = 100;
+    else if(fCapacity < 250) fCapacity = 250;
+    else fCapacity *= 2;
+
+    fData->ExpandCreateFast(fCapacity);
+
+    fData->Clear();
+    fData->ExpandCreateFast(fSize);
+  }
+  
+  return fData->AddrAt(fSize++);
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootTreeBranch::Clear()
+{
+  fSize = 0;
+  if(fData) fData->Clear();
+}
+
+//------------------------------------------------------------------------------
+
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeBranch.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeBranch.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeBranch.h	(revision 5)
@@ -0,0 +1,39 @@
+#ifndef ExRootTreeBranch_h
+#define ExRootTreeBranch_h
+
+/** \class ExRootTreeBranch
+ *
+ *  Class handling object creation.
+ *  It is also used for output ROOT tree branches
+ *
+ *  $Date: 2008-06-04 13:57:27 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "Rtypes.h"
+
+class TTree;
+class TClonesArray;
+
+class ExRootTreeBranch
+{
+public:
+
+  ExRootTreeBranch(const char *name, TClass *cl, TTree *tree = 0);
+  ~ExRootTreeBranch();
+
+  TObject *NewEntry();
+  void Clear();
+
+private:
+
+  Int_t fSize, fCapacity; //!
+  TClonesArray *fData; //!
+};
+
+#endif /* ExRootTreeBranch */
+
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeReader.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeReader.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeReader.cc	(revision 5)
@@ -0,0 +1,151 @@
+
+/** \class ExRootTreeReader
+ *
+ *  Class simplifying access to ROOT tree branches
+ *
+ *  $Date: 2008-06-04 13:57:57 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "ExRootAnalysis/ExRootTreeReader.h"
+
+#include "TH2.h"
+#include "TStyle.h"
+#include "TCanvas.h"
+#include "TClonesArray.h"
+#include "TBranchElement.h"
+
+#include <iostream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+ExRootTreeReader::ExRootTreeReader(TTree *tree) :
+  fChain(tree), fCurrentTree(-1)
+{
+}
+
+//------------------------------------------------------------------------------
+
+ExRootTreeReader::~ExRootTreeReader()
+{
+  TBranchMap::iterator itBranchMap;
+
+  for(itBranchMap = fBranchMap.begin(); itBranchMap != fBranchMap.end(); ++itBranchMap)
+  {
+    delete itBranchMap->second.second;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+Bool_t ExRootTreeReader::ReadEntry(Long64_t entry)
+{
+  // Read contents of entry.
+  if(!fChain) return kFALSE;
+
+  Int_t treeEntry = fChain->LoadTree(entry);
+  if(treeEntry < 0) return kFALSE;
+
+  if(fChain->IsA() == TChain::Class())
+  {
+    TChain *chain = static_cast<TChain*>(fChain);
+    if(chain->GetTreeNumber() != fCurrentTree)
+    {
+      fCurrentTree = chain->GetTreeNumber();
+      Notify();
+    }
+  }
+
+  TBranchMap::iterator itBranchMap;
+  TBranch *branch;
+
+  for(itBranchMap = fBranchMap.begin(); itBranchMap != fBranchMap.end(); ++itBranchMap)
+  {
+    branch = itBranchMap->second.first;
+    if(branch)
+    {
+      branch->GetEntry(treeEntry);
+    }
+  }
+
+  return kTRUE;
+}
+
+//------------------------------------------------------------------------------
+
+TClonesArray *ExRootTreeReader::UseBranch(const char *branchName)
+{
+  TClonesArray *array = 0;
+
+  TBranchMap::iterator itBranchMap = fBranchMap.find(branchName);
+
+  if(itBranchMap != fBranchMap.end())
+  {
+    cout << "** WARNING: branch '" << branchName << "' is already in use" << endl;
+    array = itBranchMap->second.second;
+  }
+  else
+  {
+    TBranch *branch = fChain->GetBranch(branchName);
+    if(branch)
+    {
+      if(branch->IsA() == TBranchElement::Class())
+      {
+        TBranchElement *element = static_cast<TBranchElement*>(branch);
+        const char *className = element->GetClonesName();
+        Int_t size = element->GetMaximum();
+        TClass *cl = gROOT->GetClass(className);
+        if(cl)
+        {
+          array = new TClonesArray(cl, size);
+          array->SetName(branchName);
+          fBranchMap.insert(make_pair(branchName, make_pair(branch, array)));
+          branch->SetAddress(&array);
+        }
+      }
+    }
+  }
+
+  if(!array)
+  {
+    cout << "** WARNING: cannot access branch '" << branchName << "', return NULL pointer" << endl;
+  }
+
+  return array;
+}
+
+//------------------------------------------------------------------------------
+
+Bool_t ExRootTreeReader::Notify()
+{
+  // Called when loading a new file.
+  // Get branch pointers.
+  if(!fChain) return kFALSE;
+
+  TBranchMap::iterator itBranchMap;
+  TBranch *branch;
+
+  for(itBranchMap = fBranchMap.begin(); itBranchMap != fBranchMap.end(); ++itBranchMap)
+  {
+    branch = fChain->GetBranch(itBranchMap->first);
+    if(branch)
+    {
+      itBranchMap->second.first = branch;
+      branch->SetAddress(&(itBranchMap->second.second));
+    }
+    else
+    {
+      cout << "** WARNING: cannot get branch '" << itBranchMap->first << "'" << endl;
+    }
+  }
+  return kTRUE;
+}
+
+//------------------------------------------------------------------------------
+
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeReader.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeReader.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeReader.h	(revision 5)
@@ -0,0 +1,51 @@
+#ifndef ExRootTreeReader_h
+#define ExRootTreeReader_h
+
+/** \class ExRootTreeReader
+ *
+ *  Class simplifying access to ROOT tree branches
+ *
+ *  $Date: 2008-06-04 13:57:27 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "TROOT.h"
+#include "TNamed.h"
+#include "TChain.h"
+#include "TFile.h"
+
+#include <map>
+
+class ExRootTreeReader : public TNamed
+{
+public :
+
+  ExRootTreeReader(TTree *tree = 0);
+  ~ExRootTreeReader();
+
+  void SetTree(TTree *tree) { fChain = tree; }
+
+  Long64_t GetEntries() const { return fChain ? static_cast<Long64_t>(fChain->GetEntries()) : 0; }
+  Bool_t ReadEntry(Long64_t entry);
+
+  TClonesArray *UseBranch(const char *branchName);
+
+private:
+
+  Bool_t Notify();
+
+  TTree *fChain; //! pointer to the analyzed TTree or TChain
+  Int_t fCurrentTree; //! current Tree number in a TChain
+
+  typedef std::map<TString, std::pair<TBranch*, TClonesArray*> > TBranchMap;
+
+  TBranchMap fBranchMap; //!
+
+  ClassDef(ExRootTreeReader, 1)
+};
+
+#endif // ExRootTreeReader_h
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeWriter.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeWriter.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeWriter.cc	(revision 5)
@@ -0,0 +1,104 @@
+
+/** \class ExRootTreeWriter
+ *
+ *  Class handling output ROOT tree
+ *
+ *  $Date: 2008-06-04 13:57:57 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "ExRootAnalysis/ExRootTreeWriter.h"
+#include "ExRootAnalysis/ExRootTreeBranch.h"
+
+#include "TROOT.h"
+#include "TFile.h"
+#include "TTree.h"
+#include "TClonesArray.h"
+
+#include <iostream>
+#include <stdexcept>
+#include <sstream>
+
+using namespace std;
+
+ExRootTreeWriter::ExRootTreeWriter(TFile *file, const char *treeName) :
+  fFile(file), fTree(0), fTreeName(treeName)
+{
+}
+
+//------------------------------------------------------------------------------
+
+ExRootTreeWriter::~ExRootTreeWriter()
+{
+  set<ExRootTreeBranch*>::iterator itBranches;
+  for(itBranches = fBranches.begin(); itBranches != fBranches.end(); ++itBranches)
+  {
+    delete (*itBranches);
+  }
+
+  if(fTree) delete fTree;
+}
+
+//------------------------------------------------------------------------------
+
+ExRootTreeBranch *ExRootTreeWriter::NewBranch(const char *name, TClass *cl)
+{
+  if(!fTree) fTree = NewTree();
+  ExRootTreeBranch *branch = new ExRootTreeBranch(name, cl, fTree);
+  fBranches.insert(branch);
+  return branch;
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootTreeWriter::Fill()
+{
+  if(fTree) fTree->Fill();
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootTreeWriter::Write()
+{
+  fFile = fTree ? fTree->GetCurrentFile() : 0;
+  if(fFile) fFile->Write();
+}
+
+//------------------------------------------------------------------------------
+
+void ExRootTreeWriter::Clear()
+{
+  set<ExRootTreeBranch*>::iterator itBranches;
+  for(itBranches = fBranches.begin(); itBranches != fBranches.end(); ++itBranches)
+  {
+    (*itBranches)->Clear();
+  }
+}
+
+//------------------------------------------------------------------------------
+
+TTree *ExRootTreeWriter::NewTree()
+{
+  if(!fFile) return 0;
+
+  TTree *tree = 0;
+  TDirectory *dir = gDirectory;
+
+  fFile->cd();
+  tree = new TTree(fTreeName, "Analysis tree");
+  dir->cd();
+
+  if(!tree)
+  {
+    throw runtime_error("can't create output ROOT tree");
+  }
+
+  tree->SetDirectory(fFile);
+  tree->SetAutoSave(10000000);  // autosave when 10 MB written
+
+  return tree;
+}
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeWriter.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeWriter.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootTreeWriter.h	(revision 5)
@@ -0,0 +1,56 @@
+#ifndef ExRootTreeWriter_h
+#define ExRootTreeWriter_h
+
+/** \class ExRootTreeWriter
+ *
+ *  Class handling output ROOT tree
+ *
+ *  $Date: 2008-06-04 13:57:27 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "TNamed.h"
+
+#include <set>
+
+class TFile;
+class TTree;
+class TClass;
+class ExRootTreeBranch;
+
+class ExRootTreeWriter : public TNamed
+{
+public:
+
+  ExRootTreeWriter(TFile *file = 0, const char *treeName = "Analysis");
+  ~ExRootTreeWriter();
+
+  void SetTreeFile(TFile *file) { fFile = file; }
+  void SetTreeName(const char *name) { fTreeName = name; }
+
+  ExRootTreeBranch *NewBranch(const char *name, TClass *cl);
+
+  void Clear();
+  void Fill();
+  void Write();
+
+private:
+
+  TTree *NewTree();
+
+  TFile *fFile; //!
+  TTree *fTree; //!
+
+  TString fTreeName; //!
+
+  std::set<ExRootTreeBranch*> fBranches; //!
+
+  ClassDef(ExRootTreeWriter, 1)
+};
+
+#endif /* ExRootTreeWriter */
+
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootUtilities.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootUtilities.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootUtilities.cc	(revision 5)
@@ -0,0 +1,80 @@
+
+/** \class ExRootUtilities
+ *
+ *  Functions simplifying ROOT tree analysis
+ *
+ *  $Date: 2008-06-04 13:57:57 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "ExRootAnalysis/ExRootUtilities.h"
+
+#include "TROOT.h"
+#include "TH1.h"
+#include "TChain.h"
+
+#include <iostream>
+#include <fstream>
+
+using namespace std;
+
+static const Font_t kExRootFont = 42;
+static const Float_t kExRootFontSize = 0.04;
+
+void HistStyle(TH1 *hist, Bool_t stats)
+{
+  hist->SetLineWidth(2);
+  hist->SetLineColor(kBlack);
+  hist->SetMarkerStyle(kFullSquare);
+  hist->SetMarkerColor(kBlack);
+
+  hist->GetXaxis()->SetTitleOffset(1.5);
+  hist->GetYaxis()->SetTitleOffset(1.75);
+  hist->GetZaxis()->SetTitleOffset(1.5);
+
+  hist->GetXaxis()->SetTitleFont(kExRootFont);
+  hist->GetYaxis()->SetTitleFont(kExRootFont);
+  hist->GetZaxis()->SetTitleFont(kExRootFont);
+  hist->GetXaxis()->SetTitleSize(kExRootFontSize);
+  hist->GetYaxis()->SetTitleSize(kExRootFontSize);
+  hist->GetZaxis()->SetTitleSize(kExRootFontSize);
+
+  hist->GetXaxis()->SetLabelFont(kExRootFont);
+  hist->GetYaxis()->SetLabelFont(kExRootFont);
+  hist->GetZaxis()->SetLabelFont(kExRootFont);
+  hist->GetXaxis()->SetLabelSize(kExRootFontSize);
+  hist->GetYaxis()->SetLabelSize(kExRootFontSize);
+  hist->GetZaxis()->SetLabelSize(kExRootFontSize);
+
+  hist->SetStats(stats);
+}
+
+//------------------------------------------------------------------------------
+
+Bool_t FillChain(TChain *chain, const char *inputFileList)
+{
+  ifstream infile(inputFileList);
+  string buffer;
+
+  if(!infile.is_open())
+  {
+    cerr << "** ERROR: Can't open '" << inputFileList << "' for input" << endl;
+    return kFALSE;
+  }
+
+  while(1)
+  {
+    infile >> buffer;
+    if(!infile.good()) break;
+    chain->Add(buffer.c_str());
+  }
+
+  return kTRUE;
+}
+
+//------------------------------------------------------------------------------
+
Index: trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootUtilities.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootUtilities.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/ExRootAnalysis/ExRootUtilities.h	(revision 5)
@@ -0,0 +1,25 @@
+#ifndef ExRootUtilities_h
+#define ExRootUtilities_h
+
+/** \class ExRootUtilities
+ *
+ *  Functions simplifying ROOT tree analysis
+ *
+ *  $Date: 2008-06-04 13:57:28 $
+ *  $Revision: 1.1 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "Rtypes.h"
+
+class TH1;
+class TChain;
+
+void HistStyle(TH1 *hist, Bool_t stats = kTRUE);
+
+Bool_t FillChain(TChain *chain, const char *inputFileList);
+
+#endif // ExRootUtilities_h
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/AUTHORS
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/AUTHORS	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/AUTHORS	(revision 5)
@@ -0,0 +1,41 @@
+FastJet was written and is maintained and developed by 
+
+Matteo Cacciari
+Gavin P. Salam
+Gregory Soyez
+
+See http://fastjet.fr/ for further details, and the FastJet manual
+at http://arxiv.org/abs/1111.6097
+
+----------------------------------------------------------------------
+
+Many people have provided bug reports, suggestions for development and
+in some cases explicit code for plugin algorithms. We would in
+particular like to thank
+
+Vanya Belyaev
+Andy Buckley
+Timothy Chan
+Pierre-Antoine Delsart
+Olivier Devillers
+Robert Harris
+Joey Huston
+Sue Ann Koay
+Andreas Oehler
+Sal Rappoccio
+Juan Rojo
+Sebastian Sapeta
+Mike Seymour
+Jessie Shelton
+Torbjorn Sjostrand
+Lars Sonnenschein
+Hartmut Stadie
+Mark Sutton
+Chris Vermilion
+Markus Wobisch 
+
+----------------------------------------------------------------------
+
+This package uses T.Chan's closest pair algorithm, Proc.13th ACM-SIAM
+Symp. Discr. Alg, p.472 (2002), S.Fortune's Voronoi algorithm and code,
+and CGAL: http://www.cgal.org/
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ActiveAreaSpec.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ActiveAreaSpec.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ActiveAreaSpec.hh	(revision 5)
@@ -0,0 +1,57 @@
+//STARTHEADER
+// $Id: ActiveAreaSpec.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_ACTIVEAREASPEC_HH__
+#define __FASTJET_ACTIVEAREASPEC_HH__
+
+// for backwards compatibility fastjet/ActiveAreaSpec.hh provides the
+// ActiveAreSpec class that is equivalent to GhostedAreaSpec. The
+// latter should now be used (defined in the
+// fastjet/GhostedAreaSpec.hh header). ActiveAreaSpec is not
+// guaranteed to work in future release of FastJet
+#warning This file includes fastjet/ActiveAreaSpec.hh, \
+a deprecated FastJet header provided only for backward compatibility. \
+This is not guaranteed to work in future releases of FastJet. \
+Please consider including fastjet/GhostedAreaSpec.hh directly. \
+Similarily, if you use the (deprecated) class ActiveAreaSpec, \
+please switch to the equivalent GhostedAreaSpec instead.
+
+
+#include "fastjet/GhostedAreaSpec.hh"
+
+// NB: ActiveAreaSpec is left over from FJ 2.0 and 2.1;
+//     In FJ 2.3 and 2.4 it was just typedefed to GhostedAreaSpec.
+//     That's still the case in FJ 3.0, but the typedef has moved
+//     from this header into the GhostedAreaSpec.hh header. This way,
+//     anyone including ActiveAreaSpec.hh will get a deprecated warning, but
+//     people who relied on getting ActiveAreaSpec indirectly will not 
+//     have their code broken.
+
+
+#endif // __FASTJET_ACTIVEAREASPEC_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/AreaDefinition.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/AreaDefinition.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/AreaDefinition.cc	(revision 5)
@@ -0,0 +1,77 @@
+//STARTHEADER
+// $Id: AreaDefinition.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/AreaDefinition.hh"
+#include<sstream>
+#include<string>
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+string VoronoiAreaSpec::description() const {
+  ostringstream ostr;
+  ostr << "Voronoi area with effective_Rfact = " << effective_Rfact() ;
+  return ostr.str();
+}
+
+
+//----------------------------------------------------------------------
+///  return info about the type of area being used by this defn
+string AreaDefinition::description() const {
+  ostringstream ostr;
+
+  switch(area_type()) {
+  case active_area:
+    ostr << "Active area (hidden ghosts) with " ;
+    ostr << ghost_spec().description();
+    break;
+  case active_area_explicit_ghosts:
+    ostr << "Active area (explicit ghosts) with " ;
+    ostr << ghost_spec().description();
+    break;
+  case one_ghost_passive_area:
+    ostr << "Passive area (one ghost at a time) with " ;
+    ostr << ghost_spec().description();
+    break;
+  case passive_area:
+    ostr << "Passive area (optimal alg. based on jet.def.), where relevant with " ;
+    ostr << ghost_spec().description()  ;
+    break;
+  case voronoi_area:
+    ostr << voronoi_spec().description();
+    break;
+  default:
+    cerr << "Error: unrecognized area_type in AreaDefinition::description():" 
+         << area_type() << endl;
+    exit(-1);
+  }
+  return ostr.str();
+}
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/AreaDefinition.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/AreaDefinition.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/AreaDefinition.hh	(revision 5)
@@ -0,0 +1,155 @@
+//STARTHEADER
+// $Id: AreaDefinition.hh 2687 2011-11-14 11:17:51Z soyez $
+//
+// Copyright (c) 2006-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_AREADEFINITION_HH__
+#define __FASTJET_AREADEFINITION_HH__
+
+#include "fastjet/GhostedAreaSpec.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+//
+/// @ingroup area_classes
+/// \class VoronoiAreaSpec
+/// Specification for the computation of the Voronoi jet area
+///
+/// class for holding a "Voronoi area" specification; an area will be
+/// assigned to each particle, which is the area of the intersection
+/// of the particle's Voronoi cell with a circle of radius
+/// R*effective_Rfact.
+///
+class VoronoiAreaSpec {
+public:
+
+  /// default constructor (effective_Rfact = 1);
+  VoronoiAreaSpec() : _effective_Rfact(1.0) {};
+  
+  /// constructor that allows you to set effective_Rfact.
+  VoronoiAreaSpec(double effective_Rfact_in) : 
+    _effective_Rfact(effective_Rfact_in) {};
+
+  /// return the value of effective_Rfact
+  double effective_Rfact() const {return _effective_Rfact;}
+
+  /// return a textual description of the area definition.
+  std::string description() const;
+
+private:
+  double _effective_Rfact;
+};
+
+
+/// the different types of area that are supported
+enum AreaType {invalid_area = -1, 
+               active_area = 0, active_area_explicit_ghosts = 1,
+               one_ghost_passive_area = 10, passive_area = 11, 
+               voronoi_area=20};
+
+
+//----------------------------------------------------------------------
+/// @ingroup area_classes
+/// \class AreaDefinition
+/// class that holds a generic area definition
+class AreaDefinition {
+public:
+  
+  /// default constructor, which provides a ghosted active area, with
+  /// sensible defaults for the ghosts.
+  AreaDefinition() {
+    _area_type  = active_area;
+    _ghost_spec = GhostedAreaSpec();
+  }
+
+  /// constructor for an area definition based on an area type and a
+  /// ghosted area specification
+  AreaDefinition(AreaType type, const GhostedAreaSpec & spec) {
+    _ghost_spec = spec;
+    _area_type   = type;
+    assert(type != voronoi_area);
+  }
+
+  /// constructor for an area definition based on an area type and a
+  /// voronoi area specification (type must be voronoi_area)
+  AreaDefinition(AreaType type, const VoronoiAreaSpec & spec) {
+    _voronoi_spec = spec;
+    _area_type   = type;
+    assert(type == voronoi_area);
+  }
+
+  /// constructor for an area definition based on an area type and 
+  /// which attempts to provide sensible defaults for everything else
+  AreaDefinition(AreaType type) {
+    _area_type   = type;
+    if (type == voronoi_area) {
+      _voronoi_spec = VoronoiAreaSpec();
+    } else {
+      _ghost_spec = GhostedAreaSpec();
+    }
+  }
+
+  /// constructor for an area definition based on an ghosted area
+  /// specification, and an option to select which ghosted area you want
+  AreaDefinition(const GhostedAreaSpec & spec, AreaType type = active_area) {
+    _ghost_spec = spec;
+    _area_type   = type;
+    assert(type != voronoi_area);
+  }
+
+  /// constructor for an area definition based on a voronoi area
+  /// specification
+  AreaDefinition(const VoronoiAreaSpec & spec) {
+    _voronoi_spec = spec;
+    _area_type    = voronoi_area;
+  }
+
+  /// return a description of the current area definition
+  std::string description() const;
+
+  /// return info about the type of area being used by this defn
+  AreaType area_type() const {return _area_type;}
+
+  /// return a reference to the active area spec
+  const GhostedAreaSpec  & ghost_spec()  const {return _ghost_spec;}
+  GhostedAreaSpec & ghost_spec()  {return _ghost_spec;}
+
+  /// return a reference to the voronoi area spec
+  const VoronoiAreaSpec & voronoi_spec() const {return _voronoi_spec;}
+  
+private:
+
+  AreaType        _area_type;
+  GhostedAreaSpec  _ghost_spec;
+  VoronoiAreaSpec _voronoi_spec;
+};
+
+FASTJET_END_NAMESPACE        // defined in fastjet/internal/base.hh
+
+
+#endif // __FASTJET_AREADEFINITION_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/BasicRandom.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/BasicRandom.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/BasicRandom.cc	(revision 5)
@@ -0,0 +1,55 @@
+//STARTHEADER
+// simple random number generator class taken from nlojet++.
+// $Id: BasicRandom.cc 859 2012-11-28 01:49:23Z pavel $
+//
+//  Copyright (C) 2002 Zoltan Nagy
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//ENDHEADER
+
+//   nlo includes
+#include "fastjet/internal/BasicRandom.hh"
+
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+
+//
+//                   random number generator
+//  uses method of L'Ecuyer, (via F.James, comp. phys. comm. 60(1990)329)
+//
+int __default_random_generator(int *__iseed) 
+{
+  int __k = __iseed[0]/53668;
+  __iseed[0] = (__iseed[0] - __k*53668)*40014 - __k*12211;
+  if(__iseed[0] < 0) __iseed[0] += 2147483563;
+  
+  __k = __iseed[1]/52774;
+  __iseed[1] = (__iseed[1] - __k*52774)*40692 - __k*3791;
+  if(__iseed[1] < 0) __iseed[1] += 2147483399;
+  
+  int __iz = __iseed[0] - __iseed[1];
+  if(__iz < 1) __iz += 2147483562;
+  
+  return __iz;
+}
+
+//   global defined random number generator
+BasicRandom<int>     _G_random_int;
+BasicRandom<double>  _G_random_double;
+
+
+FASTJET_END_NAMESPACE
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/COPYING
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/COPYING	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/COPYING	(revision 5)
@@ -0,0 +1,508 @@
+FastJet is released under the terms of the GNU General Public License
+v2 (GPLv2). FastJet includes a significant body of third-party code,
+for example for third party plugin algorithms and for computational
+geometry methods. These too are usually released under the GPL or
+permissive licenses. Details are given below on a case-by-case basis.
+
+A copy of the GPLv2 is to be found at the end of this file.
+
+While the GPL license grants you considerable freedom, please bear in
+mind that FastJet's use falls under guidelines similar to those that
+are standard for Monte Carlo event generators
+(http://www.montecarlonet.org/GUIDELINES). In particular, if you use
+this code as part of work towards a scientific publication, whether
+directly or contained within another program (e.g. Delphes, SpartyJet,
+Rivet, LHC collaboration software frameworks, etc.), you should
+include a citation to
+
+  arXiv:1111.6097 (FastJet User Manual)
+  and, optionally, Phys.Lett.B641 (2006) 57 [arXiv:hep-ph/0512210]
+
+A number of other citations may also be relevant, for example for jet
+areas and subtraction, boosted object taggers, plugins and the
+underlying computational geometry methods and codes. Plugins generally
+indicate the appropriate reference in a banner. References for other
+features are to be found in the FastJet manual.
+
+
+======================================================================
+Plugins 
+======================================================================
+
+For the plugin jet finders, the licensing situation is as follows:
+
+----------------------------------------------------------------------
+. ATLAS Cone: the code was taken from SpartyJet v1.20. (GPLv2?)
+  Licensing situation currently undergoing confirmation.
+
+----------------------------------------------------------------------
+. CDF code: originally provided by J.Huston 
+
+  See http://www.pa.msu.edu/~huston/Les_Houches_2005/JetClu+Midpoint-StandAlone.tgz
+  for the original code.
+
+  Informal agreement for distribution under the terms of the GPL was
+  obtained from Robert Roser on 13 April 2011. We are awaiting final
+  confirmation.
+  
+
+----------------------------------------------------------------------
+. CMS Iterative Cone: 
+  Code taken from http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW
+  GPL(v2) (permission granted by R.Harris)
+
+  From: Robert M Harris <rharris@fnal.gov>
+  To: Gregory Soyez <soyez@fastjet.fr>, 
+      Matteo Cacciari <cacciari@lpthe.jussieu.fr>, 
+      Gavin Salam <salam@lpthe.jussieu.fr>
+  Cc: Daniele.Del.Re@cern.ch, 
+      Salvatore Rappoccio <rappoccio@gmail.com>, 
+      Robert M Harris <rharris@fnal.gov>
+  Subject: Re: CMS Iterative Cone license
+  Date: Mon, 21 Nov 2011 14:05:55 -0600
+  
+  Dear Gregory, Matteo and Gavin,
+    
+     As a jet object coordinator for the CMS collaboration, and having
+  consulted and obtained the consent of the other authors, I hereby
+  grant you permission to distribute our code for the CMS Iterative
+  Cone jet algorithm under the terms of the GNU Public License (v2).
+  
+  Best Regards,
+  Robert Harris
+
+
+----------------------------------------------------------------------
+. D0 RunI and RunII cone plugins: 
+  Standalone version provided by Lars Sonnenschein. 
+  Permission to distribute it under the terms of the GPL(v2) granted
+  by Lars Sonnenschein on behalf of the D0 collaboration
+
+  From: Lars Sonnenschein <sonne@mail.cern.ch>
+  To: Gregory Soyez <soyez@fastjet.fr>
+  Cc: Matteo Cacciari <matteo.cacciari@cern.ch>, 
+      Gavin Salam <salam@lpthe.jussieu.fr>
+  Subject: Re: D0 cone license
+  Date: Mon, 12 Dec 2011 18:17:05 +0100
+  
+  Dear Gregory, all,
+  after some iterations with the D0 spoke persons and other programmers who 
+  have been involved in writing the C++ implementation within the D0 
+  software framework, the conclusion is that D0 grants the permission:
+  
+  "As an author of the D0 Run I and D0 Run II cone code, and having
+  consulted and obtained the consent of the other authors (D0 collaboration),
+  I hereby grant you permission to distribute my/our code for the
+  D0 Run I and Run II cone jet algorithms under the terms of the GNU 
+  General Public License (v2).".
+  
+  Citation and/or banner should then also give credit to the D0 
+  collaboration.
+  
+  Kind regards
+  Lars
+
+
+----------------------------------------------------------------------
+. PxCone code: GPL(v2) (permission granted by M.H.Seymour)
+
+  From: Mike Seymour <Michael.Seymour@cern.ch>
+  To: Gavin Salam <gavin.salam@cern.ch>
+  Subject: Re: PxCone licence
+  Date: Wed, 9 Nov 2011 15:15:08 +0000
+  
+  Dear Gavin, 
+
+  As an author of the PxCone code, and having checked that this is
+  acceptable with the other authors of PxCone (Luis Del Pozo and his
+  then PhD supervisor David Ward), I hereby grant you the right to
+  distribute PxCone together with FastJet under a GPL (v2) license.
+
+  Many thanks for dealing with this,
+  Mike. 
+
+----------------------------------------------------------------------
+. SISCone code: GPL(v2)
+  see http://projects.hepforge.org/siscone/ for details
+
+----------------------------------------------------------------------
+. TrackJet: available under the GPL (v2) from Rivet (v1.1.2)
+  see http://projects.hepforge.org/rivet/
+
+----------------------------------------------------------------------
+. EECambridge, GridJet, Jade and NestedDefs have been written by the
+  FastJet authors and are thus distributed under the GNU Public
+  License (v2).
+
+----------------------------------------------------------------------
+The "interface" parts of the plugins are GPL (v2).
+
+======================================================================
+CGAL
+======================================================================
+
+CGAL is not distributed with FastJet. Some parts of CGAL are released
+under a QPL license. Given this license's compatibility issues with
+the GPL, and for the purpose of resolving any ambiguity on this point,
+we explicitly grant permission for FastJet to be linked with CGAL.
+
+======================================================================
+Fortune's Voronoi code
+======================================================================
+
+This code, Copyright(c)1994 by AT&T Bell Laboratories is distributed
+under a non-restrictive license that allows for copying, modification
+and distribution as long as the original copyright notice is left
+unchanged. Modifications made subsequently by Shane O'Sullivan and
+Gregory Soyez are distributed under similar conditions.
+
+======================================================================
+Chan's closest neighbour algorithm
+======================================================================
+
+The code for this has been written by the FastJet authors.
+
+
+======================================================================
+======================================================================
+======================================================================
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/CircularRange.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/CircularRange.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/CircularRange.hh	(revision 5)
@@ -0,0 +1,115 @@
+//STARTHEADER
+// $Id: CircularRange.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_CIRCULARRANGE_HH__
+#define __FASTJET_CIRCULARRANGE_HH__
+
+#include "fastjet/RangeDefinition.hh"
+#include "fastjet/Error.hh"
+
+// for backwards compatibility: one should now use SelectorCircle,
+// defined in fastjet/Selector.hh, instead CircularRange
+#warning This file includes fastjet/CircularRange.hh, \
+a deprecated FastJet header provided only for backward compatibility. \
+This is not guaranteed to work in future releases of FastJet. \
+From FastJet 3.0 onwards, please consider using Selector, defined in \
+fastjet/Selector.hh, instead of RangeDefinition and, in particular, \
+SelectorCircle instead of CircularRange.
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+class CircularRange : public fastjet::RangeDefinition {
+public:
+  /// constructor
+  CircularRange() {_set_invalid_rapphi();}
+  
+  /// initialise CircularRange with a jet
+  CircularRange(const fastjet::PseudoJet & jet, double distance) {
+                _distance = distance;
+		_rapjet = jet.rap();
+		_phijet = jet.phi();
+		_total_area = fastjet::pi*_distance*_distance;  }
+
+  /// initialise CircularRange with a (rap,phi) point
+  CircularRange(double rap, double phi, double distance) {
+                _distance = distance;
+		_rapjet = rap;
+		_phijet = phi;
+		_total_area = fastjet::pi*_distance*_distance;  }
+
+  /// initialise CircularRange with just the radius parameter
+  CircularRange(double distance) {
+                _set_invalid_rapphi();
+                _distance = distance;
+		_total_area = fastjet::pi*_distance*_distance;  }
+  
+  /// destructor
+  virtual ~CircularRange() {}
+  
+  /// return description of range
+  virtual inline std::string description() const {
+    std::ostringstream ostr;
+    ostr << "CircularRange: within distance "<< _distance << " of given jet or point." ;
+    return ostr.str(); }
+
+  /// returns true since this range is localizable (i.e. set_position
+  /// does something meaningful)
+  virtual inline bool is_localizable() const { return true; }
+  
+  /// return bool according to whether (rap,phi) is in range
+  virtual inline bool is_in_range(double rap, double phi) const {
+     if (! _rapphi_are_valid()) {
+       throw Error("Circular range used without a center having being defined (use set_position())");
+     }
+     double deltaphi = _phijet - phi;
+     if ( deltaphi > pi) { deltaphi -= twopi; }
+     else if ( deltaphi < -pi) { deltaphi += twopi; }
+     bool inrange = ( (rap-_rapjet)*(rap-_rapjet) +
+                deltaphi*deltaphi <= _distance*_distance );
+     return inrange; }
+
+  /// return the minimal and maximal rapidity of this range
+  virtual inline void get_rap_limits(double & rapmin, double & rapmax) const {
+     rapmin = _rapjet - _distance;
+     rapmax = _rapjet + _distance; }
+
+private:
+  double _distance;
+
+  /// value for phi that marks it as invalid
+  const static double _invalid_phi = -1000.0;
+  /// set internal phi so as to mark things as invalid
+  void _set_invalid_rapphi() {_phijet = _invalid_phi;}
+  /// true if rap,phi are valid (tests only phi)
+  bool _rapphi_are_valid() const {return _phijet != _invalid_phi;}
+};
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_CIRCULARRANGE_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClosestPair2D.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClosestPair2D.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClosestPair2D.cc	(revision 5)
@@ -0,0 +1,494 @@
+//STARTHEADER
+// $Id: ClosestPair2D.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/internal/ClosestPair2D.hh"
+
+#include<limits>
+#include<iostream>
+#include<iomanip>
+#include<algorithm>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+const unsigned int huge_unsigned = 4294967295U;
+const unsigned int twopow31      = 2147483648U;
+
+using namespace std;
+
+//----------------------------------------------------------------------
+/// takes a point and sets a shuffle with the given shift...
+void ClosestPair2D::_point2shuffle(Point & point, Shuffle & shuffle, 
+				  unsigned int shift) {
+  
+  Coord2D renorm_point = (point.coord - _left_corner)/_range;
+  // make sure the point is sensible
+  //cerr << point.coord.x <<" "<<point.coord.y<<endl;
+  assert(renorm_point.x >=0);
+  assert(renorm_point.x <=1);
+  assert(renorm_point.y >=0);
+  assert(renorm_point.y <=1);
+  
+  shuffle.x = static_cast<unsigned int>(twopow31 * renorm_point.x) + shift;
+  shuffle.y = static_cast<unsigned int>(twopow31 * renorm_point.y) + shift;
+  shuffle.point = &point;
+}
+
+//----------------------------------------------------------------------
+/// compares this shuffle with the other one
+bool ClosestPair2D::Shuffle::operator<(const Shuffle & q) const {
+
+  if (floor_ln2_less(x ^ q.x, y ^ q.y)) {
+    // i = 2 in Chan's algorithm
+    return (y < q.y);
+  } else {
+    // i = 1 in Chan's algorithm
+    return (x < q.x);
+  }
+}
+
+
+
+//----------------------------------------------------------------------
+void ClosestPair2D::_initialize(const std::vector<Coord2D> & positions, 
+			     const Coord2D & left_corner, 
+			     const Coord2D & right_corner,
+			     unsigned int max_size) {
+
+  unsigned int n_positions = positions.size();
+  assert(max_size >= n_positions);
+
+  //_points(positions.size())
+
+  // allow the points array to grow to the following size
+  _points.resize(max_size);
+  // currently unused points are immediately made available on the
+  // stack
+  for (unsigned int i = n_positions; i < max_size; i++) {
+    _available_points.push(&(_points[i]));
+  }
+
+  _left_corner = left_corner;
+  _range       = max((right_corner.x - left_corner.x),
+		     (right_corner.y - left_corner.y));
+
+  // initialise the coordinates for the points and create the zero-shifted
+  // shuffle array
+  vector<Shuffle> shuffles(n_positions);
+  for (unsigned int i = 0; i < n_positions; i++) {
+    // set up the points
+    _points[i].coord = positions[i];
+    _points[i].neighbour_dist2 = numeric_limits<double>::max();
+    _points[i].review_flag = 0;
+
+    // create shuffle with 0 shift.
+    _point2shuffle(_points[i], shuffles[i], 0);
+  }
+
+  // establish what our shifts will be
+  for (unsigned ishift = 0; ishift < _nshift; ishift++) {
+    // make sure we use double-precision for calculating the shifts
+    // since otherwise we will hit integer overflow.
+   _shifts[ishift] = static_cast<unsigned int>(((twopow31*1.0)*ishift)/_nshift);
+    if (ishift == 0) {_rel_shifts[ishift] = 0;}
+    else {_rel_shifts[ishift] = _shifts[ishift] - _shifts[ishift-1];}
+  }
+  //_shifts[0] = 0;
+  //_shifts[1] = static_cast<unsigned int>((twopow31*1.0)/3.0);
+  //_shifts[2] = static_cast<unsigned int>((twopow31*2.0)/3.0);
+  //_rel_shifts[0] = 0;
+  //_rel_shifts[1] = _shifts[1];
+  //_rel_shifts[2] = _shifts[2]-_shifts[1];
+
+  // and how we will search...
+  //_cp_search_range = 49;
+  _cp_search_range = 30;
+  _points_under_review.reserve(_nshift * _cp_search_range);
+
+  // now initialise the three trees
+  for (unsigned int ishift = 0; ishift < _nshift; ishift++) {
+
+    // shift the shuffles if need be.
+    if (ishift > 0) {
+      unsigned rel_shift = _rel_shifts[ishift];
+      for (unsigned int i = 0; i < shuffles.size(); i++) {
+	shuffles[i] += rel_shift; }
+    }
+
+    // sort the shuffles
+    sort(shuffles.begin(), shuffles.end());
+
+    // and create the search tree
+    _trees[ishift] = auto_ptr<Tree>(new Tree(shuffles, max_size));
+
+    // now we look for the closest-pair candidates on this tree
+    circulator circ = _trees[ishift]->somewhere(), start=circ;
+    // the actual range in which we search 
+    unsigned int CP_range = min(_cp_search_range, n_positions-1);
+    do {
+      Point * this_point = circ->point;
+      //cout << _ID(this_point) << " ";
+      this_point->circ[ishift] = circ;
+      // run over all points within _cp_search_range of this_point on tree
+      circulator other = circ;
+      for (unsigned i=0; i < CP_range; i++) {
+	++other;
+	double dist2 = this_point->distance2(*other->point);
+	if (dist2 < this_point->neighbour_dist2) {
+	  this_point->neighbour_dist2 = dist2;
+	  this_point->neighbour       = other->point;
+	}
+      }
+    } while (++circ != start);
+    //cout << endl<<endl;
+  }
+
+  // now initialise the heap object...
+  vector<double> mindists2(n_positions);
+  for (unsigned int i = 0; i < n_positions; i++) {
+    mindists2[i] = _points[i].neighbour_dist2;}
+  
+  _heap = auto_ptr<MinHeap>(new MinHeap(mindists2, max_size));
+}
+
+
+//----------------------------------------------------------------------=
+void ClosestPair2D::closest_pair(unsigned int & ID1, unsigned int & ID2, 
+				 double & distance2) const {
+  ID1 = _heap->minloc();
+  ID2 = _ID(_points[ID1].neighbour);
+  distance2 = _points[ID1].neighbour_dist2;
+  if (ID1 > ID2) swap(ID1,ID2);
+}
+
+
+//----------------------------------------------------------------------
+inline void ClosestPair2D::_add_label(Point * point, unsigned int review_flag) {
+
+  // if it's not already under review, then put it on the list of
+  // points needing review
+  if (point->review_flag == 0) _points_under_review.push_back(point);
+
+  // OR the point's current flag with the requested review flag
+  point->review_flag |= review_flag;
+}
+
+//----------------------------------------------------------------------
+inline void ClosestPair2D::_set_label(Point * point, unsigned int review_flag) {
+
+  // if it's not already under review, then put it on the list of
+  // points needing review
+  if (point->review_flag == 0) _points_under_review.push_back(point);
+
+  // SET the point's current flag to the requested review flag
+  point->review_flag = review_flag;
+}
+
+//----------------------------------------------------------------------
+void ClosestPair2D::remove(unsigned int ID) {
+
+  //cout << "While removing " << ID <<endl;
+
+  Point * point_to_remove = & (_points[ID]);
+
+  // remove this point from the search tree
+  _remove_from_search_tree(point_to_remove);
+
+  // the above statement labels certain points as needing "review" --
+  // deal with them...
+  _deal_with_points_to_review();
+}
+
+
+//----------------------------------------------------------------------
+void ClosestPair2D::_remove_from_search_tree(Point * point_to_remove) {
+
+  // add this point to the list of "available" points (this is
+  // relevant also from the point of view of determining the range
+  // over which we circulate).
+  _available_points.push(point_to_remove);
+
+  // label it so that it goes from the heap
+  _set_label(point_to_remove, _remove_heap_entry);
+
+  // establish the range over which we search (a) for points that have
+  // acquired a new neighbour and (b) for points which had ID as their
+  // neighbour;
+  
+  unsigned int CP_range = min(_cp_search_range, size()-1);
+
+  // then, for each shift
+  for (unsigned int ishift = 0; ishift < _nshift; ishift++) {
+    //cout << "   ishift = " << ishift <<endl;
+    // get the circulator for the point we'll remove and its successor
+    circulator removed_circ = point_to_remove->circ[ishift];
+    circulator right_end = removed_circ.next();
+    // remove the point
+    _trees[ishift]->remove(removed_circ);
+    
+    // next find the point CP_range points to the left
+    circulator left_end  = right_end, orig_right_end = right_end;
+    for (unsigned int i = 0; i < CP_range; i++) {left_end--;}
+
+    if (size()-1 < _cp_search_range) {
+      // we have a smaller range now than before -- but when seeing who 
+      // could have had ID as a neighbour, we still need to use the old
+      // range for seeing how far back we search (but new separation between
+      // points). [cf CCN28-42]
+      left_end--; right_end--;
+    }
+
+    // and then for each left-end point: establish if the removed
+    // point was its neighbour [in which case a new neighbour must be
+    // found], otherwise see if the right-end point is a closer neighbour
+    do {
+      Point * left_point = left_end->point;
+
+      //cout << "    visited " << setw(3)<<_ID(left_point)<<" (its neighbour was "<<	setw(3)<< _ID(left_point->neighbour)<<")"<<endl;
+
+      if (left_point->neighbour == point_to_remove) {
+	// we'll deal with it later...
+	_add_label(left_point, _review_neighbour);
+      } else {
+	// check to see if right point has become its closest neighbour
+	double dist2 = left_point->distance2(*right_end->point);
+	if (dist2 < left_point->neighbour_dist2) {
+	  left_point->neighbour = right_end->point;
+	  left_point->neighbour_dist2 = dist2;
+	  // NB: (LESSER) REVIEW NEEDED HERE TOO...
+	  _add_label(left_point, _review_heap_entry);
+	}
+      }
+      ++right_end;
+    } while (++left_end != orig_right_end);
+  } // ishift...
+
+}
+
+
+//----------------------------------------------------------------------
+void ClosestPair2D::_deal_with_points_to_review() {
+
+  // the range in which we carry out searches for new neighbours on
+  // the search tree
+  unsigned int CP_range = min(_cp_search_range, size()-1);
+
+  // now deal with the points that are "under review" in some way
+  // (have lost their neighbour, or need their heap entry updating)
+  while(_points_under_review.size() > 0) {
+    // get the point to be considered
+    Point * this_point = _points_under_review.back();
+    // remove it from the list
+    _points_under_review.pop_back();  
+    
+    if (this_point->review_flag & _remove_heap_entry) {
+      // make sure no other flags are on (it wouldn't be consistent?)
+      assert(!(this_point->review_flag ^ _remove_heap_entry));
+      _heap->remove(_ID(this_point));
+    } 
+    // check to see if the _review_neighbour flag is on
+    else {
+      if (this_point->review_flag & _review_neighbour) {
+	this_point->neighbour_dist2 = numeric_limits<double>::max();
+	// among all three shifts
+	for (unsigned int ishift = 0; ishift < _nshift; ishift++) {
+	  circulator other = this_point->circ[ishift];
+	  // among points within CP_range
+	  for (unsigned i=0; i < CP_range; i++) {
+	    ++other;
+	    double dist2 = this_point->distance2(*other->point);
+	    if (dist2 < this_point->neighbour_dist2) {
+	      this_point->neighbour_dist2 = dist2;
+	      this_point->neighbour       = other->point;
+	    }
+	  }
+	}
+      }
+
+      // for any non-zero review flag we'll have to update the heap
+      _heap->update(_ID(this_point), this_point->neighbour_dist2);
+    }
+
+    // "delabel" the point
+    this_point->review_flag = 0; 
+
+  }
+
+}
+
+//----------------------------------------------------------------------
+unsigned int ClosestPair2D::insert(const Coord2D & new_coord) {
+
+  // get hold of a point
+  assert(_available_points.size() > 0);
+  Point * new_point = _available_points.top();
+  _available_points.pop();
+
+  // set the point's coordinate
+  new_point->coord = new_coord;
+  
+  // now find it's neighbour in the search tree
+  _insert_into_search_tree(new_point);
+
+  // sort out other points that may have been affected by this, 
+  // and/or for which the heap needs to be updated
+  _deal_with_points_to_review();
+
+  // 
+  return _ID(new_point);
+}
+
+//----------------------------------------------------------------------
+unsigned int ClosestPair2D::replace(unsigned int ID1, unsigned int ID2, 
+				    const Coord2D & position) {
+  
+  // deletion from tree...
+  Point * point_to_remove = & (_points[ID1]);
+  _remove_from_search_tree(point_to_remove);
+
+  point_to_remove = & (_points[ID2]);
+  _remove_from_search_tree(point_to_remove);
+
+  // insertion into tree
+  // get hold of a point
+  Point * new_point = _available_points.top();
+  _available_points.pop();
+
+  // set the point's coordinate
+  new_point->coord = position;
+  
+  // now find it's neighbour in the search tree
+  _insert_into_search_tree(new_point);
+
+  // the above statement labels certain points as needing "review" --
+  // deal with them...
+  _deal_with_points_to_review();
+
+  //
+  return _ID(new_point);
+
+}
+
+
+//----------------------------------------------------------------------
+void ClosestPair2D::replace_many(
+                  const std::vector<unsigned int> & IDs_to_remove,
+		  const std::vector<Coord2D> & new_positions,
+		  std::vector<unsigned int> & new_IDs) {
+
+  // deletion from tree...
+  for (unsigned int i = 0; i < IDs_to_remove.size(); i++) {
+    _remove_from_search_tree(& (_points[IDs_to_remove[i]]));
+  }
+
+  // insertion into tree
+  new_IDs.resize(0);
+  for (unsigned int i = 0; i < new_positions.size(); i++) {
+    Point * new_point = _available_points.top();
+    _available_points.pop();
+    // set the point's coordinate
+    new_point->coord = new_positions[i];
+    // now find it's neighbour in the search tree
+    _insert_into_search_tree(new_point);
+    // record the ID
+    new_IDs.push_back(_ID(new_point));
+  }
+
+  // the above statement labels certain points as needing "review" --
+  // deal with them...
+  _deal_with_points_to_review();
+
+}
+
+
+//----------------------------------------------------------------------
+void ClosestPair2D::_insert_into_search_tree(Point * new_point) {
+
+  // this point will have to have it's heap entry reviewed...
+  _set_label(new_point, _review_heap_entry);
+
+  // set the current distance to "infinity"
+  new_point->neighbour_dist2 = numeric_limits<double>::max();
+  
+  // establish how far we will be searching;
+  unsigned int CP_range = min(_cp_search_range, size()-1);
+
+  for (unsigned ishift = 0; ishift < _nshift; ishift++) {
+    // create the shuffle
+    Shuffle new_shuffle;
+    _point2shuffle(*new_point, new_shuffle, _shifts[ishift]);
+    
+    // insert it into the tree
+    circulator new_circ = _trees[ishift]->insert(new_shuffle);
+    new_point->circ[ishift] = new_circ;
+
+    // now get hold of the right and left edges of the region we will be
+    // looking at (cf CCN28-43)
+    circulator right_edge = new_circ; right_edge++;
+    circulator left_edge  = new_circ;
+    for (unsigned int i = 0; i < CP_range; i++) {left_edge--;}
+
+    // now 
+    do {
+      Point * left_point  = left_edge->point;
+      Point * right_point = right_edge->point;
+
+      // see if the new point is closer to the left-edge than the latter's
+      // current neighbour
+      double new_dist2 = left_point->distance2(*new_point);
+      if (new_dist2 < left_point->neighbour_dist2) {
+	left_point->neighbour_dist2 = new_dist2;
+	left_point->neighbour       = new_point;
+	_add_label(left_point, _review_heap_entry);
+      }
+
+      // see if the right-point is closer to the new point than it's current
+      // neighbour
+      new_dist2 = new_point->distance2(*right_point);
+      if (new_dist2 < new_point->neighbour_dist2) {
+	new_point->neighbour_dist2 = new_dist2;
+	new_point->neighbour = right_point;
+      }
+
+      // if the right-edge point was the left-edge's neighbour, then
+      // then it's just gone off-radar and the left-point will need to
+      // have its neighbour recalculated [actually, this is overdoing
+      // it a little, since right point may be an less "distant"
+      // (circulator distance) in one of the other shifts -- but not
+      // sure how to deal with this...]
+      if (left_point->neighbour == right_point) {
+	_add_label(left_point, _review_neighbour);
+      }
+
+      // shift the left and right edges until left edge hits new_circ
+      right_edge++;
+    } while (++left_edge != new_circ);
+  }
+}
+
+FASTJET_END_NAMESPACE
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence.cc	(revision 5)
@@ -0,0 +1,1522 @@
+//STARTHEADER
+// $Id: ClusterSequence.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/Error.hh"
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/ClusterSequenceStructure.hh"
+#include "fastjet/version.hh" // stores the current version number
+#include<iostream>
+#include<sstream>
+#include<fstream>
+#include<cmath>
+#include<cstdlib>
+#include<cassert>
+#include<string>
+#include<set>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+// here's where we put the main page for fastjet (as explained in the
+// Doxygen FAQ)
+// We put it inside the fastjet namespace to have the links without
+// having to specify (fastjet::)
+//......................................................................
+/** \mainpage FastJet code documentation
+ *
+ * These pages provide automatically generated documentation for the 
+ * FastJet package.
+ * 
+ * \section useful_classes The most useful classes
+ *
+ * Many of the facilities of FastJet can be accessed through the three
+ * following classes:
+ *
+ * - PseudoJet: the basic class for holding the 4-momentum of a
+ *   particle or a jet.
+ *
+ * - JetDefinition: the combination of a #JetAlgorithm and its
+ *   associated parameters. Can also be initialised with a \ref plugins "plugin".  
+ *
+ * - ClusterSequence: constructed with a vector of input (PseudoJet)
+ *   particles and a JetDefinition, it computes and stores the
+ *   information on how the input particles are clustered into jets.
+ *
+ * \section advanced_classes Selected more advanced classes
+ *
+ * - ClusterSequenceArea: with the help of an AreaDefinition, provides
+ *   jets that also contain information about their area.
+ *
+ * \section Tools Selected additional tools
+ *
+ * - JetMedianBackgroundEstimator: with the help of a Selector, a JetDefinition and
+ *   an AreaDefinition, allows one to estimate the background noise density in an event; for a simpler, quicker, effective alternative, use GridMedianBackgroundEstimator
+ *
+ * - Transformer: class from which are derived various tools for
+ *   manipulating jets and accessing their substructure. Examples are
+ *   Subtractor, Filter, Pruner and various taggers (e.g. JHTopTagger
+ *   and MassDropTagger).
+ *
+ * \section further_info Further information
+ *
+ * - Selected classes ordered by topics can be found under the <a
+ * href="modules.html">modules</a> tab.
+ *
+ * - The complete list of classes is available under the  <a
+ * href="annotated.html">classes</a> tab.
+ * 
+ * - For non-class material (<a href="namespacefastjet.html#enum-members">enums</a>,
+ * <a href="namespacefastjet.html#typedef-members">typedefs</a>, 
+ * <a href="namespacefastjet.html#func-members">functions</a>), see the 
+ * #fastjet documentation
+ * 
+ * - For further information and normal documentation, see the main <a
+ * href="http://fastjet.fr/">FastJet</a> page.
+ *
+ * \section examples Examples
+ *   See our \subpage Examples page
+ */
+
+// define the doxygen groups
+/// \defgroup basic_classes    Fundamental FastJet classes
+/// \defgroup area_classes     Area-related classes
+/// \defgroup sec_area_classes Secondary area-related classes
+/// \defgroup plugins          Plugins for non-native jet definitions
+/// \defgroup selectors        Selectors
+/// \defgroup tools            FastJet tools
+/// \{ \defgroup tools_generic     Generic tools
+///    \defgroup tools_background  Background subtraction
+///    \defgroup tools_taggers     Taggers
+/// \}
+/// \defgroup extra_info       Access to extra information
+/// \defgroup error_handling   Error handling
+/// \defgroup advanced_usage   Advanced usage
+/// \if internal_doc
+/// \defgroup internal
+/// \endif
+
+//----------------------------------------------------------------------
+
+
+using namespace std;
+
+
+// The following variable can be modified from within user code
+// so as to redirect banners to an ostream other than cout.
+//
+// Please note that if you distribute 3rd party code
+// that links with FastJet, that 3rd party code is NOT
+// allowed to turn off the printing of FastJet banners
+// by default. This requirement reflects the spirit of
+// clause 2c of the GNU Public License (v2), under which
+// FastJet and its plugins are distributed.
+std::ostream * ClusterSequence::_fastjet_banner_ostr = &cout;
+
+
+// destructor that guarantees proper bookkeeping for the CS Structure
+ClusterSequence::~ClusterSequence () {
+  // set the pointer in the wrapper to this object to NULL to say that
+  // we're going out of scope
+  if (_structure_shared_ptr()){
+    ClusterSequenceStructure* csi = dynamic_cast<ClusterSequenceStructure*>(_structure_shared_ptr()); 
+    // normally the csi is purely internal so it really should not be
+    // NULL i.e assert should be OK
+    // (we assert rather than throw an error, since failure here is a
+    // sign of major internal problems)
+    assert(csi != NULL);
+    csi->set_associated_cs(NULL);
+
+    // if the user had given the CS responsibility to delete itself,
+    // but then deletes the CS themselves, the following lines of
+    // code will ensure that the structure_shared_ptr will have
+    // a proper object count (so that jets associated with the CS will
+    // throw the correct error if the user tries to access their
+    // constituents).
+    if (_deletes_self_when_unused) {
+      _structure_shared_ptr.set_count(_structure_shared_ptr.use_count() 
+				        + _structure_use_count_after_construction);
+    }
+  }
+}
+
+//-----------
+void ClusterSequence::signal_imminent_self_deletion() const {
+  // normally if the destructor is called when
+  // _deletes_self_when_unused is true, it assumes that it's been
+  // called by the user (and it therefore resets the shared pointer
+  // count to the true count).
+  //
+  // for self deletion (called from the destructor of the CSstructure,
+  // the shared_ptr to which has just had its pointer -> 0) you do
+  // _not_ want to reset the pointer count (otherwise you will end up
+  // with a double delete on the shared pointer once you start
+  // deleting the internal structure of the CS).
+  //
+  // the following modification ensures that the count reset will not
+  // take place in the destructor
+  assert(_deletes_self_when_unused);
+  _deletes_self_when_unused = false;
+}
+
+//DEP //----------------------------------------------------------------------
+//DEP void ClusterSequence::_initialise_and_run (
+//DEP 				  const double & R,
+//DEP 				  const Strategy & strategy,
+//DEP 				  const bool & writeout_combinations) {
+//DEP 
+//DEP   JetDefinition jet_def(_default_jet_algorithm, R, strategy);
+//DEP   _initialise_and_run(jet_def, writeout_combinations);
+//DEP }
+
+
+//----------------------------------------------------------------------
+void ClusterSequence::_initialise_and_run (
+				  const JetDefinition & jet_def_in,
+				  const bool & writeout_combinations) {
+
+  // transfer all relevant info into internal variables
+  _decant_options(jet_def_in, writeout_combinations);
+
+  // now run
+  _initialise_and_run_no_decant();
+}
+
+//----------------------------------------------------------------------
+void ClusterSequence::_initialise_and_run_no_decant () {
+
+  // set up the history entries for the initial particles (those
+  // currently in _jets)
+  _fill_initial_history();
+
+  // don't run anything if the event is empty
+  if (n_particles() == 0) return;
+
+  // ----- deal with special cases: plugins & e+e- ------
+  if (_jet_algorithm == plugin_algorithm) {
+    // allows plugin_xyz() functions to modify cluster sequence
+    _plugin_activated = true;
+    // let the plugin do its work here
+    _jet_def.plugin()->run_clustering( (*this) );
+    _plugin_activated = false;
+    _update_structure_use_count();
+    return;
+  } else if (_jet_algorithm == ee_kt_algorithm ||
+	     _jet_algorithm == ee_genkt_algorithm) {
+    // ignore requested strategy
+    _strategy = N2Plain;
+    if (_jet_algorithm == ee_kt_algorithm) {
+      // make sure that R is large enough so that "beam" recomb only
+      // occurs when a single particle is left
+      // Normally, this should be automatically set to 4 from JetDefinition
+      assert(_Rparam > 2.0); 
+      // this is used to renormalise the dij to get a "standard" form
+      // and our convention in e+e- will be different from that
+      // in long.inv case; NB: _invR2 name should be changed -> _renorm_dij?
+      _invR2 = 1.0;
+    } else {
+      // as of 2009-01-09, choose R to be an angular distance, in
+      // radians.  Since the algorithm uses 2(1-cos(theta)) as its
+      // squared angular measure, make sure that the _R2 is defined
+      // in a similar way.
+      if (_Rparam > pi) {
+	// choose a value that ensures that back-to-back particles will
+	// always recombine 
+	//_R2 = 4.0000000000001;
+	_R2 = 2 * ( 3.0 + cos(_Rparam) );
+      } else {
+	_R2    = 2 * ( 1.0 - cos(_Rparam) );
+      }
+      _invR2 = 1.0/_R2;
+    }
+    _simple_N2_cluster_EEBriefJet();
+    return;
+  } else if (_jet_algorithm == undefined_jet_algorithm) {
+    throw Error("A ClusterSequence cannot be created with an uninitialised JetDefinition");
+  }
+
+
+  // automatically redefine the strategy according to N if that is
+  // what the user requested -- transition points (and especially
+  // their R-dependence) are based on empirical observations for a
+  // R=0.4, 0.7 and 1.0, running on toth (3.4GHz, Pentium IV D [dual
+  // core] with 2MB of cache).
+  //-------------
+  // 2011-11-15: lowered N2Plain -> N2Tiled switchover based on some
+  //             new tests on an Intel Core 2 Duo T9400 @ 2.53 GHz
+  //             with 6MB cache; tests performed with lines such as
+  //             ./fastjet_timing_plugins -kt -nhardest 30 -repeat 50000 -strategy -3 -R 0.5 -nev 1  <  ../../data/Pythia-PtMin1000-LHC-1000ev.dat
+  if (_strategy == Best) {
+    int N = _jets.size();
+    //if (N <= 55*max(0.5,min(1.0,_Rparam))) {// old empirical scaling with R
+    //----------------------
+    // 2011-11-15: new empirical scaling with R; NB: low-R N2Tiled
+    // could be significantly improved at low N by limiting the
+    // minimum size of tiles when R is small
+    if (min(1.0,max(0.1,_Rparam)*3.3)*N <= 30) {
+      _strategy = N2Plain;
+    } else if (N > 6200/pow(_Rparam,2.0) && _jet_def.jet_algorithm() == cambridge_algorithm) {
+      _strategy = NlnNCam;
+#ifndef DROP_CGAL
+    } else if ((N > 16000/pow(_Rparam,1.15) && _jet_def.jet_algorithm() != antikt_algorithm)
+	       || N > 35000/pow(_Rparam,1.15)) {
+      _strategy = NlnN;
+#endif  // DROP_CGAL
+    } else if (N <= 450) {
+      _strategy = N2Tiled;
+    } else {                   
+      _strategy = N2MinHeapTiled;
+    }
+  }
+
+  // R >= 2pi is not supported by all clustering strategies owing to
+  // periodicity issues (a particle might cluster with itself). When
+  // R>=2pi, we therefore automatically switch to a strategy that is
+  // known to work.
+  if (_Rparam >= twopi) {
+    if (   _strategy == NlnN
+	|| _strategy == NlnN3pi
+	|| _strategy == NlnNCam
+	|| _strategy == NlnNCam2pi2R
+	|| _strategy == NlnNCam4pi) {
+#ifdef DROP_CGAL
+      _strategy = N2MinHeapTiled;
+#else
+      _strategy = NlnN4pi;
+#endif    
+    }
+    if (_jet_def.strategy() != Best && _strategy != _jet_def.strategy()) {
+      ostringstream oss;
+      oss << "Cluster strategy " << strategy_string(_jet_def.strategy())
+	  << " automatically changed to " << strategy_string()
+	  << " because the former is not supported for R = " << _Rparam
+	  << " >= 2pi";
+      _changed_strategy_warning.warn(oss.str());
+    }
+  }
+
+
+  // run the code containing the selected strategy
+  // 
+  // We order the strategies stqrting from the ones used by the Best
+  // strategy in the order of increasing N, then the remaining ones
+  // again in the order of increasing N.
+  if (_strategy == N2Plain) {
+    // BriefJet provides standard long.invariant kt alg.
+    this->_simple_N2_cluster_BriefJet();
+  } else if (_strategy == N2Tiled) {
+    this->_faster_tiled_N2_cluster();
+  } else if (_strategy == N2MinHeapTiled) {
+    this->_minheap_faster_tiled_N2_cluster();
+  } else if (_strategy == NlnN) {
+    this->_delaunay_cluster();
+  } else if (_strategy == NlnNCam) {
+    this->_CP2DChan_cluster_2piMultD();
+  } else if (_strategy == NlnN3pi || _strategy == NlnN4pi ) {
+    this->_delaunay_cluster();
+  } else if (_strategy ==  N3Dumb ) {
+    this->_really_dumb_cluster();
+  } else if (_strategy == N2PoorTiled) {
+    this->_tiled_N2_cluster();
+  } else if (_strategy == NlnNCam4pi) {
+    this->_CP2DChan_cluster();
+  } else if (_strategy == NlnNCam2pi2R) {
+    this->_CP2DChan_cluster_2pi2R();
+  } else {
+    ostringstream err;
+    err << "Unrecognised value for strategy: "<<_strategy;
+    throw Error(err.str());
+  }
+
+}
+
+
+// these needs to be defined outside the class definition.
+bool ClusterSequence::_first_time = true;
+int ClusterSequence::_n_exclusive_warnings = 0;
+
+
+//----------------------------------------------------------------------
+// the version string
+string fastjet_version_string() {
+  return "FastJet version "+string(fastjet_version);
+}
+
+
+//----------------------------------------------------------------------
+// prints a banner on the first call
+void ClusterSequence::print_banner() {
+
+  if (!_first_time) {return;}
+  _first_time = false;
+
+  // make sure the user has not set the banner stream to NULL
+  ostream * ostr = _fastjet_banner_ostr;
+  if (!ostr) return;  
+
+  (*ostr) << "#--------------------------------------------------------------------------\n";
+  (*ostr) << "#                         FastJet release " << fastjet_version << endl;
+  (*ostr) << "#                 M. Cacciari, G.P. Salam and G. Soyez                  \n"; 
+  (*ostr) << "#     A software package for jet finding and analysis at colliders      \n";
+  (*ostr) << "#                           http://fastjet.fr                           \n"; 
+  (*ostr) << "#                                                                       \n";
+  (*ostr) << "# Please cite EPJC72(2012)1896 [arXiv:1111.6097] if you use this package\n";
+  (*ostr) << "# for scientific work and optionally PLB641(2006)57 [hep-ph/0512210].   \n";
+  (*ostr) << "#								      	   \n";
+  (*ostr) << "# FastJet is provided without warranty under the terms of the GNU GPLv2.\n";
+  (*ostr) << "# It uses T. Chan's closest pair algorithm, S. Fortune's Voronoi code";
+#ifndef DROP_CGAL
+  (*ostr) << ",\n# CGAL ";
+#else
+  (*ostr) << "\n# ";
+#endif  // DROP_CGAL
+  (*ostr) << "and 3rd party plugin jet algorithms. See COPYING file for details.\n";
+  (*ostr) << "#--------------------------------------------------------------------------\n";
+  // make sure we really have the output done.
+  ostr->flush();
+}
+
+//----------------------------------------------------------------------
+// transfer all relevant info into internal variables
+void ClusterSequence::_decant_options(const JetDefinition & jet_def_in,
+                                      const bool & writeout_combinations) {
+  // make a local copy of the jet definition (for future use)
+  _jet_def = jet_def_in;
+  _writeout_combinations = writeout_combinations;
+  // initialised the wrapper to the current CS
+  _structure_shared_ptr.reset(new ClusterSequenceStructure(this));
+
+  _decant_options_partial();
+}
+
+//----------------------------------------------------------------------
+// transfer all relevant info into internal variables
+void ClusterSequence::_decant_options_partial() {
+  // let the user know what's going on
+  print_banner();
+  
+  _jet_algorithm = _jet_def.jet_algorithm();
+  _Rparam = _jet_def.R();  _R2 = _Rparam*_Rparam; _invR2 = 1.0/_R2;
+  _strategy = _jet_def.strategy();
+
+  // disallow interference from the plugin
+  _plugin_activated = false;
+
+  // initialised the wrapper to the current CS
+  //_structure_shared_ptr.reset(new ClusterSequenceStructure(this));
+  _update_structure_use_count(); // make sure it's correct already here
+}
+
+
+//----------------------------------------------------------------------
+// initialise the history in a standard way
+void ClusterSequence::_fill_initial_history () {
+
+  //if (_jets.size() == 0) {throw Error("Cannot run jet-finder on empty event");}
+
+  // reserve sufficient space for everything
+  _jets.reserve(_jets.size()*2);
+  _history.reserve(_jets.size()*2);
+
+  _Qtot = 0;
+
+  for (int i = 0; i < static_cast<int>(_jets.size()) ; i++) {
+    history_element element;
+    element.parent1 = InexistentParent;
+    element.parent2 = InexistentParent;
+    element.child   = Invalid;
+    element.jetp_index = i;
+    element.dij     = 0.0;
+    element.max_dij_so_far = 0.0;
+
+    _history.push_back(element);
+    
+    // do any momentum preprocessing needed by the recombination scheme
+    _jet_def.recombiner()->preprocess(_jets[i]);
+
+    // get cross-referencing right from PseudoJets
+    _jets[i].set_cluster_hist_index(i);
+    _set_structure_shared_ptr(_jets[i]);
+
+    // determine the total energy in the event
+    _Qtot += _jets[i].E();
+  }
+  _initial_n = _jets.size();
+  _deletes_self_when_unused = false;
+}
+
+
+//----------------------------------------------------------------------
+// Return the component corresponding to the specified index.
+// taken from CLHEP
+string ClusterSequence::strategy_string (Strategy strategy_in)  const {
+  string strategy;
+  switch(strategy_in) {
+  case NlnN:
+    strategy = "NlnN"; break;
+  case NlnN3pi:
+    strategy = "NlnN3pi"; break;
+  case NlnN4pi:
+    strategy = "NlnN4pi"; break;
+  case N2Plain:
+    strategy = "N2Plain"; break;
+  case N2Tiled:
+    strategy = "N2Tiled"; break;
+  case N2MinHeapTiled:
+    strategy = "N2MinHeapTiled"; break;
+  case N2PoorTiled:
+    strategy = "N2PoorTiled"; break;
+  case N3Dumb:
+    strategy = "N3Dumb"; break;
+  case NlnNCam4pi:
+    strategy = "NlnNCam4pi"; break;
+  case NlnNCam2pi2R:
+    strategy = "NlnNCam2pi2R"; break;
+  case NlnNCam:
+    strategy = "NlnNCam"; break; // 2piMultD
+  case plugin_strategy:
+    strategy = "plugin strategy"; break;
+  default:
+    strategy = "Unrecognized";
+  }
+  return strategy;
+}  
+
+
+double ClusterSequence::jet_scale_for_algorithm(
+				  const PseudoJet & jet) const {
+  if (_jet_algorithm == kt_algorithm)             {return jet.kt2();}
+  else if (_jet_algorithm == cambridge_algorithm) {return 1.0;}
+  else if (_jet_algorithm == antikt_algorithm) {
+    double kt2=jet.kt2();
+    return kt2 > 1e-300 ? 1.0/kt2 : 1e300;
+  } else if (_jet_algorithm == genkt_algorithm) {
+    double kt2 = jet.kt2();
+    double p   = jet_def().extra_param();
+    if (p <= 0 && kt2 < 1e-300) kt2 = 1e-300; // dodgy safety check
+    return pow(kt2, p);
+  } else if (_jet_algorithm == cambridge_for_passive_algorithm) {
+    double kt2 = jet.kt2();
+    double lim = _jet_def.extra_param();
+    if (kt2 < lim*lim && kt2 != 0.0) {
+      return 1.0/kt2;
+    } else {return 1.0;}
+  } else {throw Error("Unrecognised jet algorithm");}
+}
+
+
+// //----------------------------------------------------------------------
+// /// transfer the sequence contained in other_seq into our own;
+// /// any plugin "extras" contained in the from_seq will be lost
+// /// from there.
+// void ClusterSequence::transfer_from_sequence(ClusterSequence & from_seq) {
+// 
+//   if (will_delete_self_when_unused()) 
+//     throw(Error("cannot use CS::transfer_from_sequence after a call to delete_self_when_unused()"));
+// 
+//   // the metadata
+//   _jet_def                 = from_seq._jet_def                ;
+//   _writeout_combinations   = from_seq._writeout_combinations  ;
+//   _initial_n               = from_seq._initial_n              ;
+//   _Rparam                  = from_seq._Rparam                 ;
+//   _R2                      = from_seq._R2                     ;
+//   _invR2                   = from_seq._invR2                  ;
+//   _strategy                = from_seq._strategy               ;
+//   _jet_algorithm           = from_seq._jet_algorithm          ;
+//   _plugin_activated        = from_seq._plugin_activated       ;
+// 
+//   // the data
+//   _jets     = from_seq._jets;
+//   _history  = from_seq._history;
+//   // the following transfers ownership of the extras from the from_seq
+//   _extras   = from_seq._extras;
+// 
+//   // transfer of ownership
+//   if (_structure_shared_ptr()) {
+//     // anything that is currently associated with the cluster sequence
+//     // should be told that its cluster sequence no longer exists
+//     ClusterSequenceStructure* csi = dynamic_cast<ClusterSequenceStructure*>(_structure_shared_ptr()); 
+//     assert(csi != NULL);
+//     csi->set_associated_cs(NULL);
+//   }
+//   // create a new _structure_shared_ptr to reflect the fact that
+//   // this CS is essentially a new one
+//   _structure_shared_ptr.reset(new ClusterSequenceStructure(this));
+//   _update_structure_use_count();
+//   
+//   for (vector<PseudoJet>::iterator jit = _jets.begin(); jit != _jets.end(); jit++)
+//     _set_structure_shared_ptr(*jit);
+// }
+
+
+//----------------------------------------------------------------------
+// transfer the sequence contained in other_seq into our own;
+// any plugin "extras" contained in the from_seq will be lost
+// from there.
+//
+// It also sets the ClusterSequence pointers of the PseudoJets in
+// the history to point to this ClusterSequence
+//
+// The second argument is an action that will be applied on every
+// jets in the resulting ClusterSequence
+void ClusterSequence::transfer_from_sequence(const ClusterSequence & from_seq,
+					     const FunctionOfPseudoJet<PseudoJet> * action_on_jets){
+
+  if (will_delete_self_when_unused()) 
+    throw(Error("cannot use CS::transfer_from_sequence after a call to delete_self_when_unused()"));
+
+  // the metadata
+  _jet_def                 = from_seq._jet_def                ;
+  _writeout_combinations   = from_seq._writeout_combinations  ;
+  _initial_n               = from_seq._initial_n              ;
+  _Rparam                  = from_seq._Rparam                 ;
+  _R2                      = from_seq._R2                     ;
+  _invR2                   = from_seq._invR2                  ;
+  _strategy                = from_seq._strategy               ;
+  _jet_algorithm           = from_seq._jet_algorithm          ;
+  _plugin_activated        = from_seq._plugin_activated       ;
+
+  // the data
+
+  // apply the transformation on the jets if needed
+  if (action_on_jets)
+    _jets     = (*action_on_jets)(from_seq._jets);
+  else
+    _jets     = from_seq._jets;
+  _history  = from_seq._history;
+  // the following shares ownership of the extras with the from_seq;
+  // no transformations will be applied to the extras
+  _extras   = from_seq._extras;
+
+  // clean up existing structure
+  if (_structure_shared_ptr()) {
+    // If there are jets associated with an old version of the CS and
+    // a new one, keeping track of when to delete the CS becomes more
+    // complex; so we don't allow this situation to occur.
+    if (_deletes_self_when_unused) throw Error("transfer_from_sequence cannot be used for a cluster sequence that deletes self when unused");
+    
+    // anything that is currently associated with the cluster sequence
+    // should be told that its cluster sequence no longer exists
+    ClusterSequenceStructure* csi = dynamic_cast<ClusterSequenceStructure*>(_structure_shared_ptr()); 
+    assert(csi != NULL);
+    csi->set_associated_cs(NULL);
+  }
+  // create a new _structure_shared_ptr to reflect the fact that
+  // this CS is essentially a new one
+  _structure_shared_ptr.reset(new ClusterSequenceStructure(this));
+  _update_structure_use_count();
+  
+  for (unsigned int i=0; i<_jets.size(); i++){
+    // we reset the cluster history index in case action_on_jets
+    // messed up with it
+    _jets[i].set_cluster_hist_index(from_seq._jets[i].cluster_hist_index());
+
+    // reset the structure pointer
+    _set_structure_shared_ptr(_jets[i]);
+  }
+}
+
+
+//----------------------------------------------------------------------
+// record an ij recombination and reset the _jets[newjet_k] momentum and
+// user index to be those of newjet
+void ClusterSequence::plugin_record_ij_recombination(
+	   int jet_i, int jet_j, double dij, 
+	   const PseudoJet & newjet, int & newjet_k) {
+
+  plugin_record_ij_recombination(jet_i, jet_j, dij, newjet_k);
+
+  // now transfer newjet into place
+  int tmp_index = _jets[newjet_k].cluster_hist_index();
+  _jets[newjet_k] = newjet;
+  _jets[newjet_k].set_cluster_hist_index(tmp_index);
+  _set_structure_shared_ptr(_jets[newjet_k]);
+}
+
+
+//----------------------------------------------------------------------
+// return all inclusive jets with pt > ptmin
+vector<PseudoJet> ClusterSequence::inclusive_jets (const double & ptmin) const{
+  double dcut = ptmin*ptmin;
+  int i = _history.size() - 1; // last jet
+  vector<PseudoJet> jets_local;
+  if (_jet_algorithm == kt_algorithm) {
+    while (i >= 0) {
+      // with our specific definition of dij and diB (i.e. R appears only in 
+      // dij), then dij==diB is the same as the jet.perp2() and we can exploit
+      // this in selecting the jets...
+      if (_history[i].max_dij_so_far < dcut) {break;}
+      if (_history[i].parent2 == BeamJet && _history[i].dij >= dcut) {
+	// for beam jets
+	int parent1 = _history[i].parent1;
+	jets_local.push_back(_jets[_history[parent1].jetp_index]);}
+      i--;
+    }
+  } else if (_jet_algorithm == cambridge_algorithm) {
+    while (i >= 0) {
+      // inclusive jets are all at end of clustering sequence in the
+      // Cambridge algorithm -- so if we find a non-exclusive jet, then
+      // we can exit
+      if (_history[i].parent2 != BeamJet) {break;}
+      int parent1 = _history[i].parent1;
+      const PseudoJet & jet = _jets[_history[parent1].jetp_index];
+      if (jet.perp2() >= dcut) {jets_local.push_back(jet);}
+      i--;
+    }
+  } else if (_jet_algorithm == plugin_algorithm 
+             || _jet_algorithm == ee_kt_algorithm
+             || _jet_algorithm == antikt_algorithm
+             || _jet_algorithm == genkt_algorithm
+             || _jet_algorithm == ee_genkt_algorithm
+             || _jet_algorithm == cambridge_for_passive_algorithm) {
+    // for inclusive jets with a plugin algorithm, we make no
+    // assumptions about anything (relation of dij to momenta,
+    // ordering of the dij, etc.)
+    while (i >= 0) {
+      if (_history[i].parent2 == BeamJet) {
+	int parent1 = _history[i].parent1;
+	const PseudoJet & jet = _jets[_history[parent1].jetp_index];
+	if (jet.perp2() >= dcut) {jets_local.push_back(jet);}
+      }
+      i--;
+    }
+  } else {throw Error("cs::inclusive_jets(...): Unrecognized jet algorithm");}
+  return jets_local;
+}
+
+
+//----------------------------------------------------------------------
+// return the number of exclusive jets that would have been obtained
+// running the algorithm in exclusive mode with the given dcut
+int ClusterSequence::n_exclusive_jets (const double & dcut) const {
+
+  // first locate the point where clustering would have stopped (i.e. the
+  // first time max_dij_so_far > dcut)
+  int i = _history.size() - 1; // last jet
+  while (i >= 0) {
+    if (_history[i].max_dij_so_far <= dcut) {break;}
+    i--;
+  }
+  int stop_point = i + 1;
+  // relation between stop_point, njets assumes one extra jet disappears
+  // at each clustering.
+  int njets = 2*_initial_n - stop_point;
+  return njets;
+}
+
+//----------------------------------------------------------------------
+// return all exclusive jets that would have been obtained running
+// the algorithm in exclusive mode with the given dcut
+vector<PseudoJet> ClusterSequence::exclusive_jets (const double & dcut) const {
+  int njets = n_exclusive_jets(dcut);
+  return exclusive_jets(njets);
+}
+
+
+//----------------------------------------------------------------------
+// return the jets obtained by clustering the event to n jets.
+// Throw an error if there are fewer than n particles.
+vector<PseudoJet> ClusterSequence::exclusive_jets (const int & njets) const {
+
+  // make sure the user does not ask for more than jets than there
+  // were particles in the first place.
+  if (njets > _initial_n) {
+    ostringstream err;
+    err << "Requested " << njets << " exclusive jets, but there were only " 
+	<< _initial_n << " particles in the event";
+    throw Error(err.str());
+  }
+
+  return exclusive_jets_up_to(njets);
+}
+
+//----------------------------------------------------------------------
+// return the jets obtained by clustering the event to n jets.
+// If there are fewer than n particles, simply return all particles
+vector<PseudoJet> ClusterSequence::exclusive_jets_up_to (const int & njets) const {
+
+  // provide a warning when extracting exclusive jets for algorithms 
+  // that does not support it explicitly.
+  // Native algorithm that support it are: kt, ee_kt, cambridge, 
+  //   genkt and ee_genkt (both with p>=0)
+  // For plugins, we check Plugin::exclusive_sequence_meaningful()
+  if (( _jet_def.jet_algorithm() != kt_algorithm) &&
+      ( _jet_def.jet_algorithm() != cambridge_algorithm) &&
+      ( _jet_def.jet_algorithm() != ee_kt_algorithm) &&
+      (((_jet_def.jet_algorithm() != genkt_algorithm) && 
+	(_jet_def.jet_algorithm() != ee_genkt_algorithm)) || 
+       (_jet_def.extra_param() <0)) &&
+      ((_jet_def.jet_algorithm() != plugin_algorithm) ||
+       (!_jet_def.plugin()->exclusive_sequence_meaningful())) &&
+      (_n_exclusive_warnings < 5)) {
+    _n_exclusive_warnings++;
+    cerr << "FastJet WARNING: dcut and exclusive jets for jet-finders other than kt should be interpreted with care." << endl;
+  }
+
+
+  // calculate the point where we have to stop the clustering.
+  // relation between stop_point, njets assumes one extra jet disappears
+  // at each clustering.
+  int stop_point = 2*_initial_n - njets;
+  // make sure it's safe when more jets are requested than there are particles
+  if (stop_point < _initial_n) stop_point = _initial_n;
+
+  // some sanity checking to make sure that e+e- does not give us
+  // surprises (should we ever implement e+e-)...
+  if (2*_initial_n != static_cast<int>(_history.size())) {
+    ostringstream err;
+    err << "2*_initial_n != _history.size() -- this endangers internal assumptions!\n";
+    throw Error(err.str());
+    //assert(false);
+  }
+
+  // now go forwards and reconstitute the jets that we have --
+  // basically for any history element, see if the parent jets to
+  // which it refers were created before the stopping point -- if they
+  // were then add them to the list, otherwise they are subsequent
+  // recombinations of the jets that we are looking for.
+  vector<PseudoJet> jets_local;
+  for (unsigned int i = stop_point; i < _history.size(); i++) {
+    int parent1 = _history[i].parent1;
+    if (parent1 < stop_point) {
+      jets_local.push_back(_jets[_history[parent1].jetp_index]);
+    }
+    int parent2 = _history[i].parent2;
+    if (parent2 < stop_point && parent2 > 0) {
+      jets_local.push_back(_jets[_history[parent2].jetp_index]);
+    }
+    
+  }
+
+  // sanity check...
+  if (int(jets_local.size()) != min(_initial_n, njets)) {
+    ostringstream err;
+    err << "ClusterSequence::exclusive_jets: size of returned vector ("
+	 <<jets_local.size()<<") does not coincide with requested number of jets ("
+	 <<njets<<")";
+    throw Error(err.str());
+  }
+
+  return jets_local;
+}
+
+//----------------------------------------------------------------------
+/// return the dmin corresponding to the recombination that went from
+/// n+1 to n jets
+double ClusterSequence::exclusive_dmerge (const int & njets) const {
+  assert(njets >= 0);
+  if (njets >= _initial_n) {return 0.0;}
+  return _history[2*_initial_n-njets-1].dij;
+}
+
+
+//----------------------------------------------------------------------
+/// return the maximum of the dmin encountered during all recombinations 
+/// up to the one that led to an n-jet final state; identical to
+/// exclusive_dmerge, except in cases where the dmin do not increase
+/// monotonically.
+double ClusterSequence::exclusive_dmerge_max (const int & njets) const {
+  assert(njets >= 0);
+  if (njets >= _initial_n) {return 0.0;}
+  return _history[2*_initial_n-njets-1].max_dij_so_far;
+}
+
+
+//----------------------------------------------------------------------
+/// return a vector of all subjets of the current jet (in the sense
+/// of the exclusive algorithm) that would be obtained when running
+/// the algorithm with the given dcut.
+std::vector<PseudoJet> ClusterSequence::exclusive_subjets 
+   (const PseudoJet & jet, const double & dcut) const {
+
+  set<const history_element*> subhist;
+
+  // get the set of history elements that correspond to subjets at
+  // scale dcut
+  get_subhist_set(subhist, jet, dcut, 0);
+
+  // now transfer this into a sequence of jets
+  vector<PseudoJet> subjets;
+  subjets.reserve(subhist.size());
+  for (set<const history_element*>::iterator elem = subhist.begin(); 
+       elem != subhist.end(); elem++) {
+    subjets.push_back(_jets[(*elem)->jetp_index]);
+  }
+  return subjets;
+}
+
+//----------------------------------------------------------------------
+/// return the size of exclusive_subjets(...); still n ln n with same
+/// coefficient, but marginally more efficient than manually taking
+/// exclusive_subjets.size()
+int ClusterSequence::n_exclusive_subjets(const PseudoJet & jet, 
+                        const double & dcut) const {
+  set<const history_element*> subhist;
+  // get the set of history elements that correspond to subjets at
+  // scale dcut
+  get_subhist_set(subhist, jet, dcut, 0);
+  return subhist.size();
+}
+
+//----------------------------------------------------------------------
+/// return the list of subjets obtained by unclustering the supplied
+/// jet down to nsub subjets. Throws an error if there are fewer than
+/// nsub particles in the jet.
+std::vector<PseudoJet> ClusterSequence::exclusive_subjets
+   (const PseudoJet & jet, int nsub) const {
+  vector<PseudoJet> subjets = exclusive_subjets_up_to(jet, nsub);
+  if (int(subjets.size()) < nsub) {
+    ostringstream err;
+    err << "Requested " << nsub << " exclusive subjets, but there were only " 
+	<< subjets.size() << " particles in the jet";
+    throw Error(err.str());
+  }
+  return subjets;
+
+}
+
+//----------------------------------------------------------------------
+/// return the list of subjets obtained by unclustering the supplied
+/// jet down to nsub subjets (or all constituents if there are fewer
+/// than nsub).
+std::vector<PseudoJet> ClusterSequence::exclusive_subjets_up_to
+   (const PseudoJet & jet, int nsub) const {
+
+  set<const history_element*> subhist;
+
+  // prepare the vector into which we'll put the result
+  vector<PseudoJet> subjets;
+  if (nsub <  0) throw Error("Requested a negative number of subjets. This is nonsensical.");
+  if (nsub == 0) return subjets;
+
+  // get the set of history elements that correspond to subjets at
+  // scale dcut
+  get_subhist_set(subhist, jet, -1.0, nsub);
+
+  // now transfer this into a sequence of jets
+  subjets.reserve(subhist.size());
+  for (set<const history_element*>::iterator elem = subhist.begin(); 
+       elem != subhist.end(); elem++) {
+    subjets.push_back(_jets[(*elem)->jetp_index]);
+  }
+  return subjets;
+}
+
+
+//----------------------------------------------------------------------
+/// return the dij that was present in the merging nsub+1 -> nsub 
+/// subjets inside this jet.
+/// 
+/// If the jet has nsub or fewer constituents, it will return 0.
+double ClusterSequence::exclusive_subdmerge(const PseudoJet & jet, int nsub) const {
+  set<const history_element*> subhist;
+
+  // get the set of history elements that correspond to subjets at
+  // scale dcut
+  get_subhist_set(subhist, jet, -1.0, nsub);
+  
+  set<const history_element*>::iterator highest = subhist.end();
+  highest--;
+  /// will be zero if nconst <= nsub, since highest will be an original 
+  /// particle have zero dij
+  return (*highest)->dij;
+}
+
+
+//----------------------------------------------------------------------
+/// return the maximum dij that occurred in the whole event at the
+/// stage that the nsub+1 -> nsub merge of subjets occurred inside 
+/// this jet.
+///
+/// If the jet has nsub or fewer constituents, it will return 0.
+double ClusterSequence::exclusive_subdmerge_max(const PseudoJet & jet, int nsub) const {
+
+  set<const history_element*> subhist;
+
+  // get the set of history elements that correspond to subjets at
+  // scale dcut
+  get_subhist_set(subhist, jet, -1.0, nsub);
+  
+  set<const history_element*>::iterator highest = subhist.end();
+  highest--;
+  /// will be zero if nconst <= nsub, since highest will be an original 
+  /// particle have zero dij
+  return (*highest)->max_dij_so_far;
+}
+
+
+
+//----------------------------------------------------------------------
+/// return a set of pointers to history entries corresponding to the
+/// subjets of this jet; one stops going working down through the
+/// subjets either when 
+///   - there is no further to go
+///   - one has found maxjet entries
+///   - max_dij_so_far <= dcut
+void ClusterSequence::get_subhist_set(set<const history_element*> & subhist,
+                                     const  PseudoJet & jet, 
+                                     double dcut, int maxjet) const {
+  assert(contains(jet));
+  
+  subhist.clear();
+  subhist.insert(&(_history[jet.cluster_hist_index()]));
+
+  // establish the set of jets that are relevant
+  int njet = 1;
+  while (true) {
+    // first find out if we need to probe deeper into jet.
+    // Get history element closest to end of sequence
+    set<const history_element*>::iterator highest = subhist.end();
+    assert (highest != subhist.begin()); 
+    highest--;
+    const history_element* elem = *highest;
+    // make sure we haven't got too many jets
+    if (njet == maxjet) break;
+    // make sure it has parents
+    if (elem->parent1 < 0)            break;
+    // make sure that we still resolve it at scale dcut
+    if (elem->max_dij_so_far <= dcut) break;
+
+    // then do so: replace "highest" with its two parents
+    subhist.erase(highest);
+    subhist.insert(&(_history[elem->parent1]));
+    subhist.insert(&(_history[elem->parent2]));
+    njet++;
+  }
+}
+
+//----------------------------------------------------------------------
+// work through the object's history until
+bool ClusterSequence::object_in_jet(const PseudoJet & object, 
+                                    const PseudoJet & jet) const {
+
+  // make sure the object conceivably belongs to this clustering
+  // sequence
+  assert(contains(object) && contains(jet));
+
+  const PseudoJet * this_object = &object;
+  const PseudoJet * childp;
+  while(true) {
+    if (this_object->cluster_hist_index() == jet.cluster_hist_index()) {
+      return true;
+    } else if (has_child(*this_object, childp)) {
+      this_object = childp;
+    } else {
+      return false;
+    }
+  }
+}
+
+//----------------------------------------------------------------------
+/// if the jet has parents in the clustering, it returns true
+/// and sets parent1 and parent2 equal to them.
+///
+/// if it has no parents it returns false and sets parent1 and
+/// parent2 to zero
+bool ClusterSequence::has_parents(const PseudoJet & jet, PseudoJet & parent1, 
+                              PseudoJet & parent2) const {
+
+  const history_element & hist = _history[jet.cluster_hist_index()];
+
+  // make sure we do not run into any unexpected situations --
+  // i.e. both parents valid, or neither
+  assert ((hist.parent1 >= 0 && hist.parent2 >= 0) || 
+          (hist.parent1 < 0 && hist.parent2 < 0));
+
+  if (hist.parent1 < 0) {
+    parent1 = PseudoJet(0.0,0.0,0.0,0.0);
+    parent2 = parent1;
+    return false;
+  } else {
+    parent1 = _jets[_history[hist.parent1].jetp_index];
+    parent2 = _jets[_history[hist.parent2].jetp_index];
+    // order the parents in decreasing pt
+    if (parent1.perp2() < parent2.perp2()) std::swap(parent1,parent2);
+    return true;
+  }
+}
+
+//----------------------------------------------------------------------
+/// if the jet has a child then return true and give the child jet
+/// otherwise return false and set the child to zero
+bool ClusterSequence::has_child(const PseudoJet & jet, PseudoJet & child) const {
+
+  //const history_element & hist = _history[jet.cluster_hist_index()];
+  //
+  //if (hist.child >= 0) {
+  //  child = _jets[_history[hist.child].jetp_index];
+  //  return true;
+  //} else {
+  //  child = PseudoJet(0.0,0.0,0.0,0.0);
+  //  return false;
+  //}
+  const PseudoJet * childp;
+  bool res = has_child(jet, childp);
+  if (res) {
+    child = *childp;
+    return true;
+  } else {
+    child = PseudoJet(0.0,0.0,0.0,0.0);
+    return false;
+  }
+}
+
+bool ClusterSequence::has_child(const PseudoJet & jet, const PseudoJet * & childp) const {
+
+  const history_element & hist = _history[jet.cluster_hist_index()];
+
+  // check that this jet has a child and that the child corresponds to
+  // a true jet [RETHINK-IF-CHANGE-NUMBERING: what is the right
+  // behaviour if the child is the same jet but made inclusive...?]
+  if (hist.child >= 0 && _history[hist.child].jetp_index >= 0) {
+    childp = &(_jets[_history[hist.child].jetp_index]);
+    return true;
+  } else {
+    childp = NULL;
+    return false;
+  }
+}
+
+
+//----------------------------------------------------------------------
+/// if this jet has a child (and so a partner) return true
+/// and give the partner, otherwise return false and set the
+/// partner to zero
+bool ClusterSequence::has_partner(const PseudoJet & jet, 
+                              PseudoJet & partner) const {
+
+  const history_element & hist = _history[jet.cluster_hist_index()];
+
+  // make sure we have a child and that the child does not correspond
+  // to a clustering with the beam (or some other invalid quantity)
+  if (hist.child >= 0 && _history[hist.child].parent2 >= 0) {
+    const history_element & child_hist = _history[hist.child];
+    if (child_hist.parent1 == jet.cluster_hist_index()) {
+      // partner will be child's parent2 -- for iB clustering
+      // parent2 will not be valid
+      partner = _jets[_history[child_hist.parent2].jetp_index];
+    } else {
+      // partner will be child's parent1
+      partner = _jets[_history[child_hist.parent1].jetp_index];
+    }
+    return true;
+  } else {
+    partner = PseudoJet(0.0,0.0,0.0,0.0);
+    return false;
+  }
+}
+
+
+//----------------------------------------------------------------------
+// return a vector of the particles that make up a jet
+vector<PseudoJet> ClusterSequence::constituents (const PseudoJet & jet) const {
+  vector<PseudoJet> subjets;
+  add_constituents(jet, subjets);
+  return subjets;
+}
+
+//----------------------------------------------------------------------
+/// output the supplied vector of jets in a format that can be read
+/// by an appropriate root script; the format is:
+/// jet-n jet-px jet-py jet-pz jet-E 
+///   particle-n particle-rap particle-phi particle-pt
+///   particle-n particle-rap particle-phi particle-pt
+///   ...
+/// #END
+/// ... [i.e. above repeated]
+void ClusterSequence::print_jets_for_root(const std::vector<PseudoJet> & jets_in, 
+                                          ostream & ostr) const {
+  for (unsigned i = 0; i < jets_in.size(); i++) {
+    ostr << i  << " "
+         << jets_in[i].px() << " "
+         << jets_in[i].py() << " "
+         << jets_in[i].pz() << " "
+         << jets_in[i].E() << endl;
+    vector<PseudoJet> cst = constituents(jets_in[i]);
+    for (unsigned j = 0; j < cst.size() ; j++) {
+      ostr << " " << j << " "
+           << cst[j].rap() << " "
+           << cst[j].phi() << " "
+           << cst[j].perp() << endl;
+    }
+    ostr << "#END" << endl;
+  }
+}
+
+void ClusterSequence::print_jets_for_root(const std::vector<PseudoJet> & jets_in, 
+					  const std::string & filename,
+					  const std::string & comment ) const {
+  std::ofstream ostr(filename.c_str());
+  if (comment != "") ostr << "# " << comment << endl;
+  print_jets_for_root(jets_in, ostr);
+}
+
+
+// Not yet. Perhaps in a future release
+// //----------------------------------------------------------------------
+// // print out all inclusive jets with pt > ptmin
+// void ClusterSequence::print_jets (const double & ptmin) const{
+//     vector<PseudoJet> jets = sorted_by_pt(inclusive_jets(ptmin));
+// 
+//     for (size_t j = 0; j < jets.size(); j++) {
+//        printf("%5u %7.3f %7.3f %9.3f\n",
+//        j,jets[j].rap(),jets[j].phi(),jets[j].perp());
+//     }
+// }
+
+//----------------------------------------------------------------------
+/// returns a vector of size n_particles() which indicates, for 
+/// each of the initial particles (in the order in which they were
+/// supplied), which of the supplied jets it belongs to; if it does
+/// not belong to any of the supplied jets, the index is set to -1;
+vector<int> ClusterSequence::particle_jet_indices(
+                        const vector<PseudoJet> & jets_in) const {
+
+  vector<int> indices(n_particles());
+
+  // first label all particles as not belonging to any jets
+  for (unsigned ipart = 0; ipart < n_particles(); ipart++) 
+    indices[ipart] = -1;
+
+  // then for each of the jets relabel its consituents as belonging to
+  // that jet
+  for (unsigned ijet = 0; ijet < jets_in.size(); ijet++) {
+
+    vector<PseudoJet> jet_constituents(constituents(jets_in[ijet]));
+
+    for (unsigned ip = 0; ip < jet_constituents.size(); ip++) {
+      // a safe (if slightly redundant) way of getting the particle
+      // index (for initial particles it is actually safe to assume
+      // ipart=iclust).
+      unsigned iclust = jet_constituents[ip].cluster_hist_index();
+      unsigned ipart = history()[iclust].jetp_index;
+      indices[ipart] = ijet;
+    }
+  }
+
+  return indices;
+}
+
+
+//----------------------------------------------------------------------
+// recursive routine that adds on constituents of jet to the subjet_vector
+void ClusterSequence::add_constituents (
+           const PseudoJet & jet, vector<PseudoJet> & subjet_vector) const {
+  // find out position in cluster history
+  int i = jet.cluster_hist_index();
+  int parent1 = _history[i].parent1;
+  int parent2 = _history[i].parent2;
+
+  if (parent1 == InexistentParent) {
+    // It is an original particle (labelled by its parent having value
+    // InexistentParent), therefore add it on to the subjet vector
+    // Note: we add the initial particle and not simply 'jet' so that
+    //       calling add_constituents with a subtracted jet containing
+    //       only one particle will work.
+    subjet_vector.push_back(_jets[i]);
+    return;
+  } 
+
+  // add parent 1
+  add_constituents(_jets[_history[parent1].jetp_index], subjet_vector);
+
+  // see if parent2 is a real jet; if it is then add its constituents
+  if (parent2 != BeamJet) {
+    add_constituents(_jets[_history[parent2].jetp_index], subjet_vector);
+  }
+}
+
+
+
+//----------------------------------------------------------------------
+// initialise the history in a standard way
+void ClusterSequence::_add_step_to_history (
+	       const int & step_number, const int & parent1, 
+	       const int & parent2, const int & jetp_index,
+	       const double & dij) {
+
+  history_element element;
+  element.parent1 = parent1;
+  element.parent2 = parent2;
+  element.jetp_index = jetp_index;
+  element.child = Invalid;
+  element.dij   = dij;
+  element.max_dij_so_far = max(dij,_history[_history.size()-1].max_dij_so_far);
+  _history.push_back(element);
+
+  int local_step = _history.size()-1;
+  assert(local_step == step_number);
+
+  assert(parent1 >= 0);
+  _history[parent1].child = local_step;
+  if (parent2 >= 0) {_history[parent2].child = local_step;}
+
+  // get cross-referencing right from PseudoJets
+  if (jetp_index != Invalid) {
+    assert(jetp_index >= 0);
+    //cout << _jets.size() <<" "<<jetp_index<<"\n";
+    _jets[jetp_index].set_cluster_hist_index(local_step);
+    _set_structure_shared_ptr(_jets[jetp_index]);
+  }
+
+  if (_writeout_combinations) {
+    cout << local_step << ": " 
+	 << parent1 << " with " << parent2
+	 << "; y = "<< dij<<endl;
+  }
+
+}
+
+
+
+
+//======================================================================
+// Return an order in which to read the history such that _history[order[i]] 
+// will always correspond to the same set of consituent particles if 
+// two branching histories are equivalent in terms of the particles
+// contained in any given pseudojet.
+vector<int> ClusterSequence::unique_history_order() const {
+
+  // first construct an array that will tell us the lowest constituent
+  // of a given jet -- this will always be one of the original
+  // particles, whose order is well defined and so will help us to
+  // follow the tree in a unique manner.
+  valarray<int> lowest_constituent(_history.size());
+  int hist_n = _history.size();
+  lowest_constituent = hist_n; // give it a large number
+  for (int i = 0; i < hist_n; i++) {
+    // sets things up for the initial partons
+    lowest_constituent[i] = min(lowest_constituent[i],i); 
+    // propagates them through to the children of this parton
+    if (_history[i].child > 0) lowest_constituent[_history[i].child] 
+      = min(lowest_constituent[_history[i].child],lowest_constituent[i]);
+  }
+
+  // establish an array for what we have and have not extracted so far
+  valarray<bool> extracted(_history.size()); extracted = false;
+  vector<int> unique_tree;
+  unique_tree.reserve(_history.size());
+
+  // now work our way through the tree
+  for (unsigned i = 0; i < n_particles(); i++) {
+    if (!extracted[i]) {
+      unique_tree.push_back(i);
+      extracted[i] = true;
+      _extract_tree_children(i, extracted, lowest_constituent, unique_tree);
+    }
+  }
+
+  return unique_tree;
+}
+
+//======================================================================
+// helper for unique_history_order
+void ClusterSequence::_extract_tree_children(
+       int position, 
+       valarray<bool> & extracted, 
+       const valarray<int> & lowest_constituent,
+       vector<int> & unique_tree) const {
+  if (!extracted[position]) {
+    // that means we may have unidentified parents around, so go and
+    // collect them (extracted[position]) will then be made true)
+    _extract_tree_parents(position,extracted,lowest_constituent,unique_tree);
+  } 
+  
+  // now look after the children...
+  int child = _history[position].child;
+  if (child  >= 0) _extract_tree_children(child,extracted,lowest_constituent,unique_tree);
+}
+
+
+//======================================================================
+// return the list of unclustered particles
+vector<PseudoJet> ClusterSequence::unclustered_particles() const {
+  vector<PseudoJet> unclustered;
+  for (unsigned i = 0; i < n_particles() ; i++) {
+    if (_history[i].child == Invalid) 
+      unclustered.push_back(_jets[_history[i].jetp_index]);
+  }
+  return unclustered;
+}
+
+//======================================================================
+/// Return the list of pseudojets in the ClusterSequence that do not
+/// have children (and are not among the inclusive jets). They may
+/// result from a clustering step or may be one of the pseudojets
+/// returned by unclustered_particles().
+vector<PseudoJet> ClusterSequence::childless_pseudojets() const {
+  vector<PseudoJet> unclustered;
+  for (unsigned i = 0; i < _history.size() ; i++) {
+    if ((_history[i].child == Invalid) && (_history[i].parent2 != BeamJet))
+      unclustered.push_back(_jets[_history[i].jetp_index]);
+  }
+  return unclustered;
+}
+
+
+
+//----------------------------------------------------------------------
+// returns true if the cluster sequence contains this jet (i.e. jet's
+// structure is this cluster sequence's and the cluster history index
+// is in a consistent range)
+bool ClusterSequence::contains(const PseudoJet & jet) const {
+  return jet.cluster_hist_index() >= 0 
+    &&   jet.cluster_hist_index() < int(_history.size())
+    &&   jet.has_valid_cluster_sequence()
+    &&   jet.associated_cluster_sequence() == this;
+}
+
+
+
+//======================================================================
+// helper for unique_history_order
+void ClusterSequence::_extract_tree_parents(
+       int position, 
+       valarray<bool> & extracted, 
+       const valarray<int> & lowest_constituent,
+       vector<int> & unique_tree) const {
+
+  if (!extracted[position]) {
+    int parent1 = _history[position].parent1;
+    int parent2 = _history[position].parent2;
+    // where relevant order parents so that we will first treat the
+    // one containing the smaller "lowest_constituent"
+    if (parent1 >= 0 && parent2 >= 0) {
+      if (lowest_constituent[parent1] > lowest_constituent[parent2]) 
+	std::swap(parent1, parent2);
+    }
+    // then actually run through the parents to extract the constituents...
+    if (parent1 >= 0 && !extracted[parent1]) 
+      _extract_tree_parents(parent1,extracted,lowest_constituent,unique_tree);
+    if (parent2 >= 0 && !extracted[parent2]) 
+      _extract_tree_parents(parent2,extracted,lowest_constituent,unique_tree);
+    // finally declare this position to be accounted for and push it
+    // onto our list.
+    unique_tree.push_back(position);
+    extracted[position] = true;
+  }
+}
+
+
+//======================================================================
+/// carries out the bookkeeping associated with the step of recombining
+/// jet_i and jet_j (assuming a distance dij) and returns the index
+/// of the recombined jet, newjet_k.
+void ClusterSequence::_do_ij_recombination_step(
+                               const int & jet_i, const int & jet_j, 
+			       const double & dij, 
+			       int & newjet_k) {
+
+  // Create the new jet by recombining the first two.
+  //
+  // For efficiency reasons, use a ctr that initialises only the
+  // shared pointers, since the rest of the info will anyway be dealt
+  // with by the recombiner.
+  PseudoJet newjet(false); 
+  _jet_def.recombiner()->recombine(_jets[jet_i], _jets[jet_j], newjet);
+  _jets.push_back(newjet);
+  // original version...
+  //_jets.push_back(_jets[jet_i] + _jets[jet_j]);
+
+  // get its index
+  newjet_k = _jets.size()-1;
+
+  // get history index
+  int newstep_k = _history.size();
+  // and provide jet with the info
+  _jets[newjet_k].set_cluster_hist_index(newstep_k);
+
+  // finally sort out the history 
+  int hist_i = _jets[jet_i].cluster_hist_index();
+  int hist_j = _jets[jet_j].cluster_hist_index();
+
+  _add_step_to_history(newstep_k, min(hist_i, hist_j), max(hist_i,hist_j),
+		       newjet_k, dij);
+
+}
+
+
+//======================================================================
+/// carries out the bookkeeping associated with the step of recombining
+/// jet_i with the beam
+void ClusterSequence::_do_iB_recombination_step(
+				  const int & jet_i, const double & diB) {
+  // get history index
+  int newstep_k = _history.size();
+
+  // recombine the jet with the beam
+  _add_step_to_history(newstep_k,_jets[jet_i].cluster_hist_index(),BeamJet,
+		       Invalid, diB);
+
+}
+
+
+// make sure the static member _changed_strategy_warning is defined. 
+LimitedWarning ClusterSequence::_changed_strategy_warning;
+
+
+//----------------------------------------------------------------------
+void ClusterSequence::_set_structure_shared_ptr(PseudoJet & j) {
+  j.set_structure_shared_ptr(_structure_shared_ptr);
+  // record the use count of the structure shared point to help
+  // in case we want to ask the CS to handle its own memory
+  _update_structure_use_count();
+}
+
+
+//----------------------------------------------------------------------
+void ClusterSequence::_update_structure_use_count() {
+  // record the use count of the structure shared point to help
+  // in case we want to ask the CS to handle its own memory
+  _structure_use_count_after_construction = _structure_shared_ptr.use_count();
+}
+
+//----------------------------------------------------------------------
+/// by calling this routine you tell the ClusterSequence to delete
+/// itself when all the Pseudojets associated with it have gone out
+/// of scope. 
+void ClusterSequence::delete_self_when_unused() {
+  // the trick we use to handle this is to modify the use count; 
+  // that way the structure will be deleted when there are no external
+  // objects left associated the CS and the structure's destructor will then
+  // look after deleting the cluster sequence
+  
+  // first make sure that there is at least one other object
+  // associated with the CS
+  int new_count = _structure_shared_ptr.use_count() - _structure_use_count_after_construction;
+  if (new_count <= 0) {
+    throw Error("delete_self_when_unused may only be called if at least one object outside the CS (e.g. a jet) is already associated with the CS");
+  }
+
+  _structure_shared_ptr.set_count(new_count);
+  _deletes_self_when_unused = true;
+}
+
+
+FASTJET_END_NAMESPACE
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence.hh	(revision 5)
@@ -0,0 +1,1055 @@
+//STARTHEADER
+// $Id: ClusterSequence.hh 2806 2011-12-01 17:21:00Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_CLUSTERSEQUENCE_HH__
+#define __FASTJET_CLUSTERSEQUENCE_HH__
+
+#include<vector>
+#include<map>
+#include "fastjet/internal/DynamicNearestNeighbours.hh"
+#include "fastjet/PseudoJet.hh"
+#include<memory>
+#include<cassert>
+#include<iostream>
+#include<string>
+#include<set>
+#include<cmath> // needed to get double std::abs(double)
+#include "fastjet/Error.hh"
+#include "fastjet/JetDefinition.hh"
+#include "fastjet/SharedPtr.hh"
+#include "fastjet/LimitedWarning.hh"
+#include "fastjet/FunctionOfPseudoJet.hh"
+#include "fastjet/ClusterSequenceStructure.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+
+// forward declaration
+class ClusterSequenceStructure;
+
+/// @ingroup basic_classes
+/// \class ClusterSequence
+/// deals with clustering
+class ClusterSequence {
+
+
+ public: 
+
+  /// default constructor
+  ClusterSequence () : _deletes_self_when_unused(false) {}
+
+//   /// create a clustersequence starting from the supplied set
+//   /// of pseudojets and clustering them with the long-invariant
+//   /// kt algorithm (E-scheme recombination) with the supplied
+//   /// value for R.
+//   ///
+//   /// If strategy=DumbN3 a very stupid N^3 algorithm is used for the
+//   /// clustering; otherwise strategy = NlnN* uses cylinders algorithms
+//   /// with some number of pi coverage. If writeout_combinations=true a
+//   /// summary of the recombination sequence is written out
+//   template<class L> ClusterSequence (const std::vector<L> & pseudojets, 
+// 		   const double & R = 1.0,
+// 		   const Strategy & strategy = Best,
+// 		   const bool & writeout_combinations = false);
+
+
+  /// create a clustersequence starting from the supplied set
+  /// of pseudojets and clustering them with jet definition specified
+  /// by jet_def (which also specifies the clustering strategy)
+  template<class L> ClusterSequence (
+			          const std::vector<L> & pseudojets,
+				  const JetDefinition & jet_def,
+				  const bool & writeout_combinations = false);
+  
+  /// copy constructor for a ClusterSequence
+  ClusterSequence (const ClusterSequence & cs) : _deletes_self_when_unused(false) {
+    transfer_from_sequence(cs);
+  }
+
+  // virtual ClusterSequence destructor, in case any derived class
+  // thinks of needing a destructor at some point
+  virtual ~ClusterSequence (); //{}
+
+  // NB: in the routines that follow, for extracting lists of jets, a
+  //     list structure might be more efficient, if sometimes a little
+  //     more awkward to use (at least for old fortran hands).
+
+  /// return a vector of all jets (in the sense of the inclusive
+  /// algorithm) with pt >= ptmin. Time taken should be of the order
+  /// of the number of jets returned.
+  std::vector<PseudoJet> inclusive_jets (const double & ptmin = 0.0) const;
+
+  /// return the number of jets (in the sense of the exclusive
+  /// algorithm) that would be obtained when running the algorithm
+  /// with the given dcut.
+  int n_exclusive_jets (const double & dcut) const;
+
+  /// return a vector of all jets (in the sense of the exclusive
+  /// algorithm) that would be obtained when running the algorithm
+  /// with the given dcut.
+  std::vector<PseudoJet> exclusive_jets (const double & dcut) const;
+
+  /// return a vector of all jets when the event is clustered (in the
+  /// exclusive sense) to exactly njets. 
+  ///
+  /// If there are fewer than njets particles in the ClusterSequence
+  /// an error is thrown
+  std::vector<PseudoJet> exclusive_jets (const int & njets) const;
+
+  /// return a vector of all jets when the event is clustered (in the
+  /// exclusive sense) to exactly njets. 
+  ///
+  /// If there are fewer than njets particles in the ClusterSequence
+  /// the function just returns however many particles there were.
+  std::vector<PseudoJet> exclusive_jets_up_to (const int & njets) const;
+
+  /// return the dmin corresponding to the recombination that went
+  /// from n+1 to n jets (sometimes known as d_{n n+1}). If the number
+  /// of particles in the event is <= njets, the function returns 0.
+  double exclusive_dmerge (const int & njets) const;
+
+  /// return the maximum of the dmin encountered during all recombinations 
+  /// up to the one that led to an n-jet final state; identical to
+  /// exclusive_dmerge, except in cases where the dmin do not increase
+  /// monotonically.
+  double exclusive_dmerge_max (const int & njets) const;
+
+  /// return the ymin corresponding to the recombination that went from
+  /// n+1 to n jets (sometimes known as y_{n n+1}).
+  double exclusive_ymerge (int njets) const {return exclusive_dmerge(njets) / Q2();}
+
+  /// same as exclusive_dmerge_max, but normalised to squared total energy
+  double exclusive_ymerge_max (int njets) const {return exclusive_dmerge_max(njets)/Q2();}
+
+  /// the number of exclusive jets at the given ycut
+  int n_exclusive_jets_ycut (double ycut) const {return n_exclusive_jets(ycut*Q2());}
+
+  /// the exclusive jets obtained at the given ycut
+  std::vector<PseudoJet> exclusive_jets_ycut (double ycut) const {
+    int njets = n_exclusive_jets_ycut(ycut);
+    return exclusive_jets(njets);
+  }
+
+
+  //int n_exclusive_jets (const PseudoJet & jet, const double & dcut) const;
+
+  /// return a vector of all subjets of the current jet (in the sense
+  /// of the exclusive algorithm) that would be obtained when running
+  /// the algorithm with the given dcut. 
+  ///
+  /// Time taken is O(m ln m), where m is the number of subjets that
+  /// are found. If m gets to be of order of the total number of
+  /// constituents in the jet, this could be substantially slower than
+  /// just getting that list of constituents.
+  std::vector<PseudoJet> exclusive_subjets (const PseudoJet & jet, 
+                                            const double & dcut) const;
+
+  /// return the size of exclusive_subjets(...); still n ln n with same
+  /// coefficient, but marginally more efficient than manually taking
+  /// exclusive_subjets.size()
+  int n_exclusive_subjets(const PseudoJet & jet, 
+                          const double & dcut) const;
+
+  /// return the list of subjets obtained by unclustering the supplied
+  /// jet down to nsub subjets. Throws an error if there are fewer than
+  /// nsub particles in the jet.
+  ///
+  /// This requires nsub ln nsub time
+  std::vector<PseudoJet> exclusive_subjets (const PseudoJet & jet, 
+                                            int nsub) const;
+
+  /// return the list of subjets obtained by unclustering the supplied
+  /// jet down to nsub subjets (or all constituents if there are fewer
+  /// than nsub).
+  ///
+  /// This requires nsub ln nsub time
+  std::vector<PseudoJet> exclusive_subjets_up_to (const PseudoJet & jet, 
+						  int nsub) const;
+
+  /// return the dij that was present in the merging nsub+1 -> nsub 
+  /// subjets inside this jet.
+  ///
+  /// Returns 0 if there were nsub or fewer constituents in the jet.
+  double exclusive_subdmerge(const PseudoJet & jet, int nsub) const;
+
+  /// return the maximum dij that occurred in the whole event at the
+  /// stage that the nsub+1 -> nsub merge of subjets occurred inside 
+  /// this jet.
+  ///
+  /// Returns 0 if there were nsub or fewer constituents in the jet.
+  double exclusive_subdmerge_max(const PseudoJet & jet, int nsub) const;
+
+  //std::vector<PseudoJet> exclusive_jets (const PseudoJet & jet, 
+  //                                       const int & njets) const;
+  //double exclusive_dmerge (const PseudoJet & jet, const int & njets) const;
+
+  /// returns the sum of all energies in the event (relevant mainly for e+e-)
+  double Q() const {return _Qtot;}
+  /// return Q()^2
+  double Q2() const {return _Qtot*_Qtot;}
+
+  /// returns true iff the object is included in the jet. 
+  ///
+  /// NB: this is only sensible if the object is already registered
+  /// within the cluster sequence, so you cannot use it with an input
+  /// particle to the CS (since the particle won't have the history
+  /// index set properly).
+  ///
+  /// For nice clustering structures it should run in O(ln(N)) time
+  /// but in worst cases (certain cone plugins) it can take O(n) time,
+  /// where n is the number of particles in the jet.
+  bool object_in_jet(const PseudoJet & object, const PseudoJet & jet) const;
+
+  /// if the jet has parents in the clustering, it returns true
+  /// and sets parent1 and parent2 equal to them.
+  ///
+  /// if it has no parents it returns false and sets parent1 and
+  /// parent2 to zero
+  bool has_parents(const PseudoJet & jet, PseudoJet & parent1, 
+               PseudoJet & parent2) const;
+
+  /// if the jet has a child then return true and give the child jet
+  /// otherwise return false and set the child to zero
+  bool has_child(const PseudoJet & jet, PseudoJet & child) const;
+
+  /// Version of has_child that sets a pointer to the child if the child
+  /// exists;
+  bool has_child(const PseudoJet & jet, const PseudoJet * & childp) const;
+
+  /// if this jet has a child (and so a partner) return true
+  /// and give the partner, otherwise return false and set the
+  /// partner to zero
+  bool has_partner(const PseudoJet & jet, PseudoJet & partner) const;
+
+  
+  /// return a vector of the particles that make up jet
+  std::vector<PseudoJet> constituents (const PseudoJet & jet) const;
+
+
+  /// output the supplied vector of jets in a format that can be read
+  /// by an appropriate root script; the format is:
+  /// jet-n jet-px jet-py jet-pz jet-E 
+  ///   particle-n particle-rap particle-phi particle-pt
+  ///   particle-n particle-rap particle-phi particle-pt
+  ///   ...
+  /// #END
+  /// ... [i.e. above repeated]
+  void print_jets_for_root(const std::vector<PseudoJet> & jets, 
+                           std::ostream & ostr = std::cout) const;
+
+  /// print jets for root to the file labelled filename, with an
+  /// optional comment at the beginning
+  void print_jets_for_root(const std::vector<PseudoJet> & jets, 
+                           const std::string & filename,
+			   const std::string & comment = "") const;
+
+// Not yet. Perhaps in a future release.
+//   /// print out all inclusive jets with pt > ptmin
+//   virtual void print_jets (const double & ptmin=0.0) const;
+
+  /// add on to subjet_vector the constituents of jet (for internal use mainly)
+  void add_constituents (const PseudoJet & jet, 
+			 std::vector<PseudoJet> & subjet_vector) const;
+
+  /// return the enum value of the strategy used to cluster the event
+  inline Strategy strategy_used () const {return _strategy;}
+
+  /// return the name of the strategy used to cluster the event
+  std::string strategy_string () const {return strategy_string(_strategy);}
+
+  /// return the name of the strategy associated with the enum strategy_in
+  std::string strategy_string (Strategy strategy_in) const;
+
+
+  /// return a reference to the jet definition
+  const JetDefinition & jet_def() const {return _jet_def;}
+
+  /// by calling this routine you tell the ClusterSequence to delete
+  /// itself when all the Pseudojets associated with it have gone out
+  /// of scope. 
+  ///
+  /// At the time you call this, there must be at least one jet or
+  /// other object outside the CS that is associated with the CS
+  /// (e.g. the result of inclusive_jets()).
+  ///
+  /// NB: after having made this call, the user is still allowed to
+  /// delete the CS or let it go out of scope. Jets associated with it
+  /// will then simply not be able to access their substructure after
+  /// that point.
+  void delete_self_when_unused();
+
+  /// return true if the object has been told to delete itself
+  /// when unused
+  bool will_delete_self_when_unused() const {return _deletes_self_when_unused;}
+
+  /// tell the ClusterSequence it's about to be self deleted (internal use only)
+  void signal_imminent_self_deletion() const;
+
+  /// returns the scale associated with a jet as required for this
+  /// clustering algorithm (kt^2 for the kt-algorithm, 1 for the 
+  /// Cambridge algorithm). [May become virtual at some point]
+  double jet_scale_for_algorithm(const PseudoJet & jet) const;
+
+  ///
+
+  //----- next follow functions designed specifically for plugins, which
+  //      may only be called when plugin_activated() returns true
+
+  /// record the fact that there has been a recombination between
+  /// jets()[jet_i] and jets()[jet_k], with the specified dij, and
+  /// return the index (newjet_k) allocated to the new jet, whose
+  /// momentum is assumed to be the 4-vector sum of that of jet_i and
+  /// jet_j
+  void plugin_record_ij_recombination(int jet_i, int jet_j, double dij, 
+				      int & newjet_k) {
+    assert(plugin_activated());
+    _do_ij_recombination_step(jet_i, jet_j, dij, newjet_k);
+  }
+
+  /// as for the simpler variant of plugin_record_ij_recombination,
+  /// except that the new jet is attributed the momentum and
+  /// user_index of newjet
+  void plugin_record_ij_recombination(int jet_i, int jet_j, double dij, 
+				      const PseudoJet & newjet, 
+				      int & newjet_k);
+
+  /// record the fact that there has been a recombination between
+  /// jets()[jet_i] and the beam, with the specified diB; when looking
+  /// for inclusive jets, any iB recombination will returned to the user 
+  /// as a jet.
+  void plugin_record_iB_recombination(int jet_i, double diB) {
+    assert(plugin_activated());
+    _do_iB_recombination_step(jet_i, diB);
+  }
+
+  /// @ingroup extra_info
+  /// \class Extras
+  /// base class to store extra information that plugins may provide
+  /// 
+  /// a class intended to serve as a base in case a plugin needs to
+  /// associate extra information with a ClusterSequence (see
+  /// SISConePlugin.* for an example).
+  class Extras {
+  public:
+    virtual ~Extras() {}
+    virtual std::string description() const {return "This is a dummy extras class that contains no extra information! Derive from it if you want to use it to provide extra information from a plugin jet finder";}
+  };
+
+  /// the plugin can associate some extra information with the
+  /// ClusterSequence object by calling this function
+  inline void plugin_associate_extras(std::auto_ptr<Extras> extras_in) {
+    //_extras = extras_in;
+    _extras.reset(extras_in.release());
+  }
+
+  /// returns true when the plugin is allowed to run the show.
+  inline bool plugin_activated() const {return _plugin_activated;}
+
+  /// returns a pointer to the extras object (may be null)
+  const Extras * extras() const {return _extras.get();}
+
+  /// allows a plugin to run a templated clustering (nearest-neighbour heuristic)
+  ///
+  /// This has N^2 behaviour on "good" distance, but a worst case behaviour
+  /// of N^3 (and many algs trigger the worst case behaviour)
+  ///
+  /// 
+  /// For more details on how this works, see GenBriefJet below
+  template<class GBJ> void plugin_simple_N2_cluster () {
+    assert(plugin_activated());
+    _simple_N2_cluster<GBJ>();
+  }
+
+
+public:
+//DEP   /// set the default (static) jet finder across all current and future
+//DEP   /// ClusterSequence objects -- deprecated and obsolescent (i.e. may be
+//DEP   /// suppressed in a future release).
+//DEP   static void set_jet_algorithm (JetAlgorithm jet_algorithm) {_default_jet_algorithm = jet_algorithm;}
+//DEP   /// same as above for backward compatibility
+//DEP   static void set_jet_finder (JetAlgorithm jet_algorithm)    {_default_jet_algorithm = jet_algorithm;}
+
+
+  /// \ingroup extra_info
+  /// \struct history_element
+  /// a single element in the clustering history
+  /// 
+  /// (see vector _history below).
+  struct history_element{
+    int parent1; /// index in _history where first parent of this jet
+                 /// was created (InexistentParent if this jet is an
+                 /// original particle)
+
+    int parent2; /// index in _history where second parent of this jet
+                 /// was created (InexistentParent if this jet is an
+                 /// original particle); BeamJet if this history entry
+                 /// just labels the fact that the jet has recombined
+                 /// with the beam)
+
+    int child;   /// index in _history where the current jet is
+		 /// recombined with another jet to form its child. It
+		 /// is Invalid if this jet does not further
+		 /// recombine.
+
+    int jetp_index; /// index in the _jets vector where we will find the
+                 /// PseudoJet object corresponding to this jet
+                 /// (i.e. the jet created at this entry of the
+                 /// history). NB: if this element of the history
+                 /// corresponds to a beam recombination, then
+                 /// jetp_index=Invalid.
+
+    double dij;  /// the distance corresponding to the recombination
+		 /// at this stage of the clustering.
+
+    double max_dij_so_far; /// the largest recombination distance seen
+			   /// so far in the clustering history.
+  };
+
+  enum JetType {Invalid=-3, InexistentParent = -2, BeamJet = -1};
+
+  /// allow the user to access the internally stored _jets() array,
+  /// which contains both the initial particles and the various
+  /// intermediate and final stages of recombination.
+  ///
+  /// The first n_particles() entries are the original particles,
+  /// in the order in which they were supplied to the ClusterSequence
+  /// constructor. It can be useful to access them for example when
+  /// examining whether a given input object is part of a specific
+  /// jet, via the objects_in_jet(...) member function (which only takes
+  /// PseudoJets that are registered in the ClusterSequence).
+  ///
+  /// One of the other (internal uses) is related to the fact
+  /// because we don't seem to be able to access protected elements of
+  /// the class for an object that is not "this" (at least in case where
+  /// "this" is of a slightly different kind from the object, both
+  /// derived from ClusterSequence).
+  const std::vector<PseudoJet> & jets()    const;
+
+  /// allow the user to access the raw internal history.
+  ///
+  /// This is present (as for jets()) in part so that protected
+  /// derived classes can access this information about other
+  /// ClusterSequences.
+  ///
+  /// A user who wishes to follow the details of the ClusterSequence
+  /// can also make use of this information (and should consult the
+  /// history_element documentation for more information), but should
+  /// be aware that these internal structures may evolve in future
+  /// FastJet versions.
+  const std::vector<history_element> & history() const;
+
+  /// returns the number of particles that were provided to the
+  /// clustering algorithm (helps the user find their way around the
+  /// history and jets objects if they weren't paying attention
+  /// beforehand).
+  unsigned int n_particles() const;
+
+  /// returns a vector of size n_particles() which indicates, for 
+  /// each of the initial particles (in the order in which they were
+  /// supplied), which of the supplied jets it belongs to; if it does
+  /// not belong to any of the supplied jets, the index is set to -1;
+  std::vector<int> particle_jet_indices(const std::vector<PseudoJet> &) const;
+
+  /// routine that returns an order in which to read the history
+  /// such that clusterings that lead to identical jet compositions
+  /// but different histories (because of degeneracies in the
+  /// clustering order) will have matching constituents for each
+  /// matching entry in the unique_history_order.
+  ///
+  /// The order has the property that an entry's parents will always
+  /// appear prior to that entry itself. 
+  ///
+  /// Roughly speaking the order is such that we first provide all
+  /// steps that lead to the final jet containing particle 1; then we
+  /// have the steps that lead to reconstruction of the jet containing
+  /// the next-lowest-numbered unclustered particle, etc...
+  /// [see GPS CCN28-12 for more info -- of course a full explanation
+  /// here would be better...]
+  std::vector<int> unique_history_order() const;
+
+  /// return the set of particles that have not been clustered. For 
+  /// kt and cam/aachen algorithms this should always be null, but for
+  /// cone type algorithms it can be non-null;
+  std::vector<PseudoJet> unclustered_particles() const;
+
+  /// Return the list of pseudojets in the ClusterSequence that do not
+  /// have children (and are not among the inclusive jets). They may
+  /// result from a clustering step or may be one of the pseudojets
+  /// returned by unclustered_particles().
+  std::vector<PseudoJet> childless_pseudojets() const;
+
+  /// returns true if the object (jet or particle) is contained by (ie
+  /// belongs to) this cluster sequence.
+  ///
+  /// Tests performed: if thejet's interface is this cluster sequence
+  /// and its cluster history index is in a consistent range.
+  bool contains(const PseudoJet & object) const;
+
+  /// transfer the sequence contained in other_seq into our own;
+  /// any plugin "extras" contained in the from_seq will be lost
+  /// from there.
+  ///
+  /// It also sets the ClusterSequence pointers of the PseudoJets in
+  /// the history to point to this ClusterSequence
+  ///
+  /// When specified, the second argument is an action that will be
+  /// applied on every jets in the resulting ClusterSequence
+  void transfer_from_sequence(const ClusterSequence & from_seq,
+			      const FunctionOfPseudoJet<PseudoJet> * action_on_jets = 0);
+
+  /// retrieve a shared pointer to the wrapper to this ClusterSequence
+  ///
+  /// this may turn useful if you want to track when this
+  /// ClusterSequence goes out of scope
+  const SharedPtr<PseudoJetStructureBase> & structure_shared_ptr() const{
+    return _structure_shared_ptr;
+  }
+
+  /// the structure type associated with a jet belonging to a ClusterSequence
+  typedef ClusterSequenceStructure StructureType;
+
+  /// This is the function that is automatically called during
+  /// clustering to print the FastJet banner. Only the first call to
+  /// this function will result in the printout of the banner. Users
+  /// may wish to call this function themselves, during the
+  /// initialization phase of their program, in order to ensure that
+  /// the banner appears before other output. This call will not
+  /// affect 3rd-party banners, e.g. those from plugins.
+  static void print_banner();
+
+  /// \cond internal_doc
+  //  [this line must be left as is to hide the doxygen comment]
+  /// A call to this function modifies the stream used to print
+  /// banners (by default cout). If a null pointer is passed, banner
+  /// printout is suppressed. This affects all banners, including
+  /// those from plugins.
+  ///
+  /// Please note that if you distribute 3rd party code
+  /// that links with FastJet, that 3rd party code must not
+  /// use this call turn off the printing of FastJet banners
+  /// by default. This requirement reflects the spirit of
+  /// clause 2c of the GNU Public License (v2), under which
+  /// FastJet and its plugins are distributed.
+  static void set_fastjet_banner_stream(std::ostream * ostr) {_fastjet_banner_ostr = ostr;}
+  //  [this line must be left as is to hide the doxygen comment]
+  /// \endcond
+
+  /// returns a pointer to the stream to be used to print banners
+  /// (cout by default). This function is used by plugins to determine
+  /// where to direct their banners. Plugins should properly handle
+  /// the case where the pointer is null.
+  static std::ostream * fastjet_banner_stream() {return _fastjet_banner_ostr;}
+
+private:
+  /// \cond internal_doc
+
+  /// contains the actual stream to use for banners 
+  static std::ostream * _fastjet_banner_ostr;
+
+  /// \endcond
+
+protected:
+//DEP  static JetAlgorithm _default_jet_algorithm;
+  JetDefinition _jet_def;
+
+  /// transfer the vector<L> of input jets into our own vector<PseudoJet>
+  /// _jets (with some reserved space for future growth).
+  template<class L> void _transfer_input_jets(
+                                     const std::vector<L> & pseudojets);
+
+  /// This is what is called to do all the initialisation and
+  /// then run the clustering (may be called by various constructors).
+  /// It assumes _jets contains the momenta to be clustered.
+  void _initialise_and_run (const JetDefinition & jet_def,
+			    const bool & writeout_combinations);
+
+  //// this performs the initialisation, minus the option-decanting
+  //// stage; for low multiplicity, initialising a few things in the
+  //// constructor, calling the decant_options_partial() and then this
+  //// is faster than going through _initialise_and_run.
+  void _initialise_and_run_no_decant();
+
+//DEP   /// This is an alternative routine for initialising and running the
+//DEP   /// clustering, provided for legacy purposes. The jet finder is that
+//DEP   /// specified in the static member _default_jet_algorithm.
+//DEP   void _initialise_and_run (const double & R,
+//DEP 			    const Strategy & strategy,
+//DEP 			    const bool & writeout_combinations);
+
+  /// fills in the various member variables with "decanted" options from
+  /// the jet_definition and writeout_combinations variables
+  void _decant_options(const JetDefinition & jet_def,
+                       const bool & writeout_combinations);
+
+  /// assuming that the jet definition, writeout_combinations and
+  /// _structure_shared_ptr have been set (e.g. in an initialiser list
+  /// in the constructor), it handles the remaining decanting of
+  /// options.
+  void _decant_options_partial();
+
+  /// fill out the history (and jet cross refs) related to the initial
+  /// set of jets (assumed already to have been "transferred"),
+  /// without any clustering
+  void _fill_initial_history();
+
+  /// carry out the recombination between the jets numbered jet_i and
+  /// jet_j, at distance scale dij; return the index newjet_k of the
+  /// result of the recombination of i and j.
+  void _do_ij_recombination_step(const int & jet_i, const int & jet_j, 
+				 const double & dij, int & newjet_k);
+
+  /// carry out an recombination step in which _jets[jet_i] merges with
+  /// the beam, 
+  void _do_iB_recombination_step(const int & jet_i, const double & diB);
+
+  /// every time a jet is added internally during clustering, this
+  /// should be called to set the jet's structure shared ptr to point
+  /// to the CS (and the count of internally associated objects is
+  /// also updated). This should not be called outside construction of
+  /// a CS object.
+  void _set_structure_shared_ptr(PseudoJet & j);
+
+  /// make sure that the CS's internal tally of the use count matches
+  /// that of the _structure_shared_ptr
+  void _update_structure_use_count();
+  
+
+  /// This contains the physical PseudoJets; for each PseudoJet one
+  /// can find the corresponding position in the _history by looking
+  /// at _jets[i].cluster_hist_index().
+  std::vector<PseudoJet> _jets;
+
+
+  /// this vector will contain the branching history; for each stage,
+  /// _history[i].jetp_index indicates where to look in the _jets
+  /// vector to get the physical PseudoJet.
+  std::vector<history_element> _history;
+
+  /// set subhist to be a set pointers to history entries corresponding to the
+  /// subjets of this jet; one stops going working down through the
+  /// subjets either when 
+  ///   - there is no further to go
+  ///   - one has found maxjet entries
+  ///   - max_dij_so_far <= dcut
+  /// By setting maxjet=0 one can use just dcut; by setting dcut<0
+  /// one can use jet maxjet
+  void get_subhist_set(std::set<const history_element*> & subhist,
+                       const  PseudoJet & jet, double dcut, int maxjet) const;
+
+  bool _writeout_combinations;
+  int  _initial_n;
+  double _Rparam, _R2, _invR2;
+  double _Qtot;
+  Strategy    _strategy;
+  JetAlgorithm  _jet_algorithm;
+
+  SharedPtr<PseudoJetStructureBase> _structure_shared_ptr; //< will actually be of type ClusterSequenceStructure
+  int _structure_use_count_after_construction; //< info of use when CS handles its own memory
+  /// if true then the CS will delete itself when the last external
+  /// object referring to it disappears. It is mutable so as to ensure
+  /// that signal_imminent_self_deletion() [const] can make relevant
+  /// changes.
+  mutable bool _deletes_self_when_unused;
+
+ private:
+
+  bool _plugin_activated;
+  //std::auto_ptr<Extras> _extras; // things the plugin might want to add
+  SharedPtr<Extras> _extras; // things the plugin might want to add
+
+  void _really_dumb_cluster ();
+  void _delaunay_cluster ();
+  //void _simple_N2_cluster ();
+  template<class BJ> void _simple_N2_cluster ();
+  void _tiled_N2_cluster ();
+  void _faster_tiled_N2_cluster ();
+
+  //
+  void _minheap_faster_tiled_N2_cluster();
+
+  // things needed specifically for Cambridge with Chan's 2D closest
+  // pairs method
+  void _CP2DChan_cluster();
+  void _CP2DChan_cluster_2pi2R ();
+  void _CP2DChan_cluster_2piMultD ();
+  void _CP2DChan_limited_cluster(double D);
+  void _do_Cambridge_inclusive_jets();
+
+  // NSqrtN method for C/A
+  void _fast_NsqrtN_cluster();
+
+  void _add_step_to_history(const int & step_number, const int & parent1, 
+			       const int & parent2, const int & jetp_index,
+			       const double & dij);
+
+  /// internal routine associated with the construction of the unique
+  /// history order (following children in the tree)
+  void _extract_tree_children(int pos, std::valarray<bool> &, 
+		const std::valarray<int> &, std::vector<int> &) const;
+
+  /// internal routine associated with the construction of the unique
+  /// history order (following parents in the tree)
+  void _extract_tree_parents (int pos, std::valarray<bool> &, 
+                const std::valarray<int> &,  std::vector<int> &) const;
+
+
+  // these will be useful shorthands in the Voronoi-based code
+  typedef std::pair<int,int> TwoVertices;
+  typedef std::pair<double,TwoVertices> DijEntry;
+  typedef std::multimap<double,TwoVertices> DistMap;
+
+  /// currently used only in the Voronoi based code
+  void _add_ktdistance_to_map(const int & ii, 
+			      DistMap & DijMap,
+  			      const DynamicNearestNeighbours * DNN);
+
+
+  /// will be set by default to be true for the first run
+  static bool _first_time;
+
+  /// record the number of warnings provided about the exclusive
+  /// algorithm -- so that we don't print it out more than a few
+  /// times.
+  static int _n_exclusive_warnings;
+
+  /// the limited warning member for notification of user that 
+  /// their requested strategy has been overridden (usually because
+  /// they have R>2pi and not all strategies work then)
+  static LimitedWarning _changed_strategy_warning;
+
+  //----------------------------------------------------------------------
+  /// the fundamental structure which contains the minimal info about
+  /// a jet, as needed for our plain N^2 algorithm -- the idea is to
+  /// put all info that will be accessed N^2 times into an array of
+  /// BriefJets...
+  struct BriefJet {
+    double     eta, phi, kt2, NN_dist;
+    BriefJet * NN;
+    int        _jets_index;
+  };
+
+
+  /// structure analogous to BriefJet, but with the extra information
+  /// needed for dealing with tiles
+  class TiledJet {
+  public:
+    double     eta, phi, kt2, NN_dist;
+    TiledJet * NN, *previous, * next; 
+    int        _jets_index, tile_index, diJ_posn;
+    // routines that are useful in the minheap version of tiled
+    // clustering ("misuse" the otherwise unused diJ_posn, so as
+    // to indicate whether jets need to have their minheap entries
+    // updated).
+    inline void label_minheap_update_needed() {diJ_posn = 1;}
+    inline void label_minheap_update_done()   {diJ_posn = 0;}
+    inline bool minheap_update_needed() const {return diJ_posn==1;}
+  };
+
+  //-- some of the functions that follow are templates and will work
+  //as well for briefjet and tiled jets
+
+  /// set the kinematic and labelling info for jeta so that it corresponds
+  /// to _jets[_jets_index]
+  template <class J> void _bj_set_jetinfo( J * const jet, 
+						 const int _jets_index) const;
+
+  /// "remove" this jet, which implies updating links of neighbours and
+  /// perhaps modifying the tile structure
+  void _bj_remove_from_tiles( TiledJet * const jet) const;
+
+  /// return the distance between two BriefJet objects
+  template <class J> double _bj_dist(const J * const jeta, 
+			const J * const jetb) const;
+
+  // return the diJ (multiplied by _R2) for this jet assuming its NN
+  // info is correct
+  template <class J> double _bj_diJ(const J * const jeta) const;
+
+  /// for testing purposes only: if in the range head--tail-1 there is a
+  /// a jet which corresponds to hist_index in the history, then
+  /// return a pointer to that jet; otherwise return tail.
+  template <class J> inline J * _bj_of_hindex(
+                          const int hist_index, 
+			  J * const head, J * const tail) 
+    const {
+    J * res;
+    for(res = head; res<tail; res++) {
+      if (_jets[res->_jets_index].cluster_hist_index() == hist_index) {break;}
+    }
+    return res;
+  }
+
+
+  //-- remaining functions are different in various cases, so we
+  //   will use templates but are not sure if they're useful...
+
+  /// updates (only towards smaller distances) the NN for jeta without checking
+  /// whether in the process jeta itself might be a new NN of one of
+  /// the jets being scanned -- span the range head to tail-1 with
+  /// assumption that jeta is not contained in that range
+  template <class J> void _bj_set_NN_nocross(J * const jeta, 
+            J * const head, const J * const tail) const;
+
+  /// reset the NN for jeta and DO check whether in the process jeta
+  /// itself might be a new NN of one of the jets being scanned --
+  /// span the range head to tail-1 with assumption that jeta is not
+  /// contained in that range
+  template <class J> void _bj_set_NN_crosscheck(J * const jeta, 
+            J * const head, const J * const tail) const;
+  
+
+
+  /// number of neighbours that a tile will have (rectangular geometry
+  /// gives 9 neighbours).
+  static const int n_tile_neighbours = 9;
+  //----------------------------------------------------------------------
+  /// The fundamental structures to be used for the tiled N^2 algorithm
+  /// (see CCN27-44 for some discussion of pattern of tiling)
+  struct Tile {
+    /// pointers to neighbouring tiles, including self
+    Tile *   begin_tiles[n_tile_neighbours]; 
+    /// neighbouring tiles, excluding self
+    Tile **  surrounding_tiles; 
+    /// half of neighbouring tiles, no self
+    Tile **  RH_tiles;  
+    /// just beyond end of tiles
+    Tile **  end_tiles; 
+    /// start of list of BriefJets contained in this tile
+    TiledJet * head;    
+    /// sometimes useful to be able to tag a tile
+    bool     tagged;    
+  };
+  std::vector<Tile> _tiles;
+  double _tiles_eta_min, _tiles_eta_max;
+  double _tile_size_eta, _tile_size_phi;
+  int    _n_tiles_phi,_tiles_ieta_min,_tiles_ieta_max;
+
+  // reasonably robust return of tile index given ieta and iphi, in particular
+  // it works even if iphi is negative
+  inline int _tile_index (int ieta, int iphi) const {
+    // note that (-1)%n = -1 so that we have to add _n_tiles_phi
+    // before performing modulo operation
+    return (ieta-_tiles_ieta_min)*_n_tiles_phi
+                  + (iphi+_n_tiles_phi) % _n_tiles_phi;
+  }
+
+  // routines for tiled case, including some overloads of the plain
+  // BriefJet cases
+  int  _tile_index(const double & eta, const double & phi) const;
+  void _tj_set_jetinfo ( TiledJet * const jet, const int _jets_index);
+  void  _bj_remove_from_tiles(TiledJet * const jet);
+  void _initialise_tiles();
+  void _print_tiles(TiledJet * briefjets ) const;
+  void _add_neighbours_to_tile_union(const int tile_index, 
+		 std::vector<int> & tile_union, int & n_near_tiles) const;
+  void _add_untagged_neighbours_to_tile_union(const int tile_index, 
+		 std::vector<int> & tile_union, int & n_near_tiles);
+
+
+  //----------------------------------------------------------------------
+  /// fundamental structure for e+e- clustering
+  struct EEBriefJet {
+    double NN_dist;  // obligatorily present
+    double kt2;      // obligatorily present == E^2 in general
+    EEBriefJet * NN; // must be present too
+    int    _jets_index; // must also be present!
+    //...........................................................
+    double nx, ny, nz;  // our internal storage for fast distance calcs
+  };
+
+  /// to help instantiation (fj 2.4.0; did not quite work on gcc 33 and os x 10.3?)
+  //void _dummy_N2_cluster_instantiation();
+
+
+  /// to avoid issues with template instantiation (OS X 10.3, gcc 3.3)
+  void _simple_N2_cluster_BriefJet();
+  /// to avoid issues with template instantiation (OS X 10.3, gcc 3.3)
+  void _simple_N2_cluster_EEBriefJet();
+};
+
+
+//**********************************************************************
+//**************    START   OF   INLINE   MATERIAL    ******************
+//**********************************************************************
+
+
+//----------------------------------------------------------------------
+// Transfer the initial jets into our internal structure
+template<class L> void ClusterSequence::_transfer_input_jets(
+                                       const std::vector<L> & pseudojets) {
+
+  // this will ensure that we can point to jets without difficulties
+  // arising.
+  _jets.reserve(pseudojets.size()*2);
+
+  // insert initial jets this way so that any type L that can be
+  // converted to a pseudojet will work fine (basically PseudoJet
+  // and any type that has [] subscript access to the momentum
+  // components, such as CLHEP HepLorentzVector).
+  for (unsigned int i = 0; i < pseudojets.size(); i++) {
+    _jets.push_back(pseudojets[i]);}
+  
+}
+
+// //----------------------------------------------------------------------
+// // initialise from some generic type... Has to be made available
+// // here in order for it the template aspect of it to work...
+// template<class L> ClusterSequence::ClusterSequence (
+// 			          const std::vector<L> & pseudojets,
+// 				  const double & R,
+// 				  const Strategy & strategy,
+// 				  const bool & writeout_combinations) {
+// 
+//   // transfer the initial jets (type L) into our own array
+//   _transfer_input_jets(pseudojets);
+// 
+//   // run the clustering
+//   _initialise_and_run(R,strategy,writeout_combinations);
+// }
+
+
+//----------------------------------------------------------------------
+/// constructor of a jet-clustering sequence from a vector of
+/// four-momenta, with the jet definition specified by jet_def
+template<class L> ClusterSequence::ClusterSequence (
+			          const std::vector<L> & pseudojets,
+				  const JetDefinition & jet_def_in,
+				  const bool & writeout_combinations) :
+  _jet_def(jet_def_in), _writeout_combinations(writeout_combinations),
+  _structure_shared_ptr(new ClusterSequenceStructure(this))
+{
+
+  // transfer the initial jets (type L) into our own array
+  _transfer_input_jets(pseudojets);
+
+  // transfer the remaining options
+  _decant_options_partial();
+
+  // run the clustering
+  _initialise_and_run_no_decant();
+}
+
+
+inline const std::vector<PseudoJet> & ClusterSequence::jets () const {
+  return _jets;
+}
+
+inline const std::vector<ClusterSequence::history_element> & ClusterSequence::history () const {
+  return _history;
+}
+
+inline unsigned int ClusterSequence::n_particles() const {return _initial_n;}
+
+
+
+//----------------------------------------------------------------------
+template <class J> inline void ClusterSequence::_bj_set_jetinfo(
+                            J * const jetA, const int _jets_index) const {
+    jetA->eta  = _jets[_jets_index].rap();
+    jetA->phi  = _jets[_jets_index].phi_02pi();
+    jetA->kt2  = jet_scale_for_algorithm(_jets[_jets_index]);
+    jetA->_jets_index = _jets_index;
+    // initialise NN info as well
+    jetA->NN_dist = _R2;
+    jetA->NN      = NULL;
+}
+
+
+
+
+//----------------------------------------------------------------------
+template <class J> inline double ClusterSequence::_bj_dist(
+                const J * const jetA, const J * const jetB) const {
+  double dphi = std::abs(jetA->phi - jetB->phi);
+  double deta = (jetA->eta - jetB->eta);
+  if (dphi > pi) {dphi = twopi - dphi;}
+  return dphi*dphi + deta*deta;
+}
+
+//----------------------------------------------------------------------
+template <class J> inline double ClusterSequence::_bj_diJ(const J * const jet) const {
+  double kt2 = jet->kt2;
+  if (jet->NN != NULL) {if (jet->NN->kt2 < kt2) {kt2 = jet->NN->kt2;}}
+  return jet->NN_dist * kt2;
+}
+
+
+//----------------------------------------------------------------------
+// set the NN for jet without checking whether in the process you might
+// have discovered a new nearest neighbour for another jet
+template <class J> inline void ClusterSequence::_bj_set_NN_nocross(
+                 J * const jet, J * const head, const J * const tail) const {
+  double NN_dist = _R2;
+  J * NN  = NULL;
+  if (head < jet) {
+    for (J * jetB = head; jetB != jet; jetB++) {
+      double dist = _bj_dist(jet,jetB);
+      if (dist < NN_dist) {
+	NN_dist = dist;
+	NN = jetB;
+      }
+    }
+  }
+  if (tail > jet) {
+    for (J * jetB = jet+1; jetB != tail; jetB++) {
+      double dist = _bj_dist(jet,jetB);
+      if (dist < NN_dist) {
+	NN_dist = dist;
+	NN = jetB;
+      }
+    }
+  }
+  jet->NN = NN;
+  jet->NN_dist = NN_dist;
+}
+
+
+//----------------------------------------------------------------------
+template <class J> inline void ClusterSequence::_bj_set_NN_crosscheck(J * const jet, 
+		    J * const head, const J * const tail) const {
+  double NN_dist = _R2;
+  J * NN  = NULL;
+  for (J * jetB = head; jetB != tail; jetB++) {
+    double dist = _bj_dist(jet,jetB);
+    if (dist < NN_dist) {
+      NN_dist = dist;
+      NN = jetB;
+    }
+    if (dist < jetB->NN_dist) {
+      jetB->NN_dist = dist;
+      jetB->NN = jet;
+    }
+  }
+  jet->NN = NN;
+  jet->NN_dist = NN_dist;
+}
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_CLUSTERSEQUENCE_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence1GhostPassiveArea.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence1GhostPassiveArea.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence1GhostPassiveArea.cc	(revision 5)
@@ -0,0 +1,100 @@
+//STARTHEADER
+// $Id: ClusterSequence1GhostPassiveArea.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/ClusterSequence1GhostPassiveArea.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+
+using namespace std;
+
+//----------------------------------------------------------------------
+/// global routine for initialising and running a general passive area
+void ClusterSequence1GhostPassiveArea::_initialise_and_run_1GPA (
+		const JetDefinition & jet_def_in,
+		const GhostedAreaSpec & area_spec,
+		const bool & writeout_combinations) {
+
+  bool continue_running;
+  _initialise_AA(jet_def_in, area_spec, writeout_combinations, continue_running);
+  if (continue_running) {
+    _run_1GPA(area_spec);
+    _postprocess_AA(area_spec);
+  }
+}
+
+
+//----------------------------------------------------------------------
+/// routine for running a passive area one ghost at a time.
+void ClusterSequence1GhostPassiveArea::_run_1GPA (const GhostedAreaSpec & area_spec) {
+    // record the input jets as they are currently
+  vector<PseudoJet> input_jets(_jets);
+
+  // code for testing the unique tree
+  vector<int> unique_tree;
+
+  // initialise our temporary average area^2
+  valarray<double> lcl_average_area2(0.0, _average_area.size());
+  valarray<double> last_average_area(0.0, _average_area.size());
+
+  // run the clustering multiple times so as to get areas of all the jets
+  for (int irepeat = 0; irepeat < area_spec.repeat(); irepeat++) {
+
+    // first establish list of all ghosts
+    vector<PseudoJet> all_ghosts;
+    area_spec.add_ghosts(all_ghosts);
+
+    // then run many subsets of ghosts (actually each subset contains just one ghost)
+    for (unsigned ig = 0; ig < all_ghosts.size(); ig++) {
+      vector<PseudoJet> some_ghosts;
+      some_ghosts.push_back(all_ghosts[ig]);
+      ClusterSequenceActiveAreaExplicitGhosts clust_seq(input_jets, jet_def(), 
+                                                       some_ghosts, area_spec.actual_ghost_area());
+
+      if (irepeat == 0 && ig == 0) {
+        // take the non-ghost part of the history and put into our own
+        // history.
+        _transfer_ghost_free_history(clust_seq);
+        // get the "unique" order that will be used for transferring all areas. 
+        unique_tree = unique_history_order();
+      }
+      
+      // transfer areas from clust_seq into our object
+      _transfer_areas(unique_tree, clust_seq);
+    }
+    // keep track of fluctuations in area
+    lcl_average_area2 += (_average_area - last_average_area)*
+                         (_average_area - last_average_area);
+    last_average_area = _average_area;
+  }
+  _average_area2 = lcl_average_area2;
+}
+
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence1GhostPassiveArea.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence1GhostPassiveArea.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence1GhostPassiveArea.hh	(revision 5)
@@ -0,0 +1,107 @@
+//STARTHEADER
+// $Id: ClusterSequence1GhostPassiveArea.hh 2687 2011-11-14 11:17:51Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLUSTERSEQUENCE1GHOSTPASSIVEAREA_HH__
+#define __FASTJET_CLUSTERSEQUENCE1GHOSTPASSIVEAREA_HH__
+
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/ClusterSequenceAreaBase.hh"
+#include "fastjet/ClusterSequenceActiveArea.hh"
+#include<iostream>
+#include<vector>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//using namespace std;
+
+/// @ingroup sec_area_classes
+/// \class ClusterSequence1GhostPassiveArea
+/// Like ClusterSequence with computation of the passive jet area by
+/// adding a single ghost
+///
+/// Class that behaves essentially like ClusterSequence except
+/// that it also provides access to the area of a jet (which
+/// will be a random quantity... Figure out what to do about seeds 
+/// later...)
+///
+/// This class should not be used directly. Rather use
+/// ClusterSequenceArea
+class ClusterSequence1GhostPassiveArea : public ClusterSequenceActiveArea {
+public:
+
+  ClusterSequence1GhostPassiveArea() {}
+
+  /// constructor based on JetDefinition and 1GhostPassiveAreaSpec
+  template<class L> ClusterSequence1GhostPassiveArea
+         (const std::vector<L> & pseudojets, 
+	  const JetDefinition & jet_def_in,
+	  const GhostedAreaSpec & area_spec,
+	  const bool & writeout_combinations = false) ;
+
+  /// return an estimate for the number of empty jets -- one uses the
+  /// AreaBase one rather than the ActiveArea one (which for which we
+  /// do not have the information).
+  virtual double n_empty_jets(const Selector & selector) const {
+    return ClusterSequenceAreaBase::n_empty_jets(selector);
+  }
+
+protected:
+  /// does the initialisation and running specific to the passive
+  /// areas class
+  void _initialise_and_run_1GPA (const JetDefinition & jet_def_in,
+                               const GhostedAreaSpec & area_spec,
+                               const bool & writeout_combinations = false);
+
+private:
+
+  void _run_1GPA(const GhostedAreaSpec & area_spec);
+};
+
+
+
+
+template<class L> ClusterSequence1GhostPassiveArea::ClusterSequence1GhostPassiveArea 
+(const std::vector<L> & pseudojets, 
+ const JetDefinition & jet_def_in,
+ const GhostedAreaSpec & area_spec,
+ const bool & writeout_combinations) {
+
+  // transfer the initial jets (type L) into our own array
+  _transfer_input_jets(pseudojets);
+
+  // run the clustering for passive areas
+  _initialise_and_run_1GPA(jet_def_in, area_spec, writeout_combinations);
+
+}
+
+
+  
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_CLUSTERSEQUENCE1GHOSTPASSIVEAREA_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceActiveArea.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceActiveArea.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceActiveArea.cc	(revision 5)
@@ -0,0 +1,785 @@
+//STARTHEADER
+// $Id: ClusterSequenceActiveArea.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/ClusterSequenceActiveArea.hh"
+#include "fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh"
+#include<iostream>
+#include<vector>
+#include<sstream>
+#include<algorithm>
+#include<cmath>
+#include<valarray>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+
+using namespace std;
+
+
+//int ClusterSequenceActiveArea::_n_seed_warnings = 0;
+//const int _max_seed_warnings = 10;
+
+//----------------------------------------------------------------------
+/// global routine for running active area
+void ClusterSequenceActiveArea::_initialise_and_run_AA (
+		const JetDefinition & jet_def_in,
+		const GhostedAreaSpec & ghost_spec,
+		const bool & writeout_combinations) {
+
+  bool continue_running;
+  _initialise_AA(jet_def_in,  ghost_spec, writeout_combinations, continue_running);
+  if (continue_running) {
+    _run_AA(ghost_spec);
+    _postprocess_AA(ghost_spec);
+  }
+}
+
+//----------------------------------------------------------------------
+void ClusterSequenceActiveArea::_resize_and_zero_AA () {
+  // initialize our local area information
+  _average_area.resize(2*_jets.size());  _average_area  = 0.0;
+  _average_area2.resize(2*_jets.size()); _average_area2 = 0.0;
+  _average_area_4vector.resize(2*_jets.size()); 
+  _average_area_4vector = PseudoJet(0.0,0.0,0.0,0.0);
+  _non_jet_area = 0.0; _non_jet_area2 = 0.0; _non_jet_number=0.0;
+}
+
+//---------------------------------a-------------------------------------
+void ClusterSequenceActiveArea::_initialise_AA (
+		const JetDefinition & jet_def_in,
+		const GhostedAreaSpec & ghost_spec,
+		const bool & writeout_combinations,
+                bool & continue_running) 
+{
+
+  // store this for future use
+  _ghost_spec_repeat = ghost_spec.repeat();
+
+  // make sure placeholders are there & zeroed
+  _resize_and_zero_AA();
+     
+  // for future reference...
+  _maxrap_for_area = ghost_spec.ghost_maxrap();
+  _safe_rap_for_area = _maxrap_for_area - jet_def_in.R();
+
+  // Make sure we'll have at least one repetition -- then we can
+  // deduce the unghosted clustering sequence from one of the ghosted
+  // sequences. If we do not have any repetitions, then get the
+  // unghosted sequence from the plain unghosted clustering.
+  //
+  // NB: all decanting and filling of initial history will then
+  // be carried out by base-class routine
+  if (ghost_spec.repeat() <= 0) {
+    _initialise_and_run(jet_def_in, writeout_combinations);
+    continue_running = false;
+    return;
+  }
+
+  // transfer all relevant info into internal variables
+  _decant_options(jet_def_in, writeout_combinations);
+
+  // set up the history entries for the initial particles (those
+  // currently in _jets)
+  _fill_initial_history();
+
+  // by default it does not...
+  _has_dangerous_particles = false;
+  
+  continue_running = true;
+}
+
+
+//----------------------------------------------------------------------
+void ClusterSequenceActiveArea::_run_AA (const GhostedAreaSpec & ghost_spec) {
+  // record the input jets as they are currently
+  vector<PseudoJet> input_jets(_jets);
+
+  // code for testing the unique tree
+  vector<int> unique_tree;
+
+  // run the clustering multiple times so as to get areas of all the jets
+  for (int irepeat = 0; irepeat < ghost_spec.repeat(); irepeat++) {
+
+    ClusterSequenceActiveAreaExplicitGhosts clust_seq(input_jets, 
+                                                      jet_def(), ghost_spec);
+
+    _has_dangerous_particles |= clust_seq.has_dangerous_particles();
+    if (irepeat == 0) {
+      // take the non-ghost part of the history and put into our own
+      // history.
+      _transfer_ghost_free_history(clust_seq);
+      // get the "unique" order that will be used for transferring all areas. 
+      unique_tree = unique_history_order();
+    }
+
+    // transfer areas from clust_seq into our object
+    _transfer_areas(unique_tree, clust_seq);
+  }
+}
+  
+
+//----------------------------------------------------------------------
+/// run the postprocessing for the active area (and derived classes)
+void ClusterSequenceActiveArea::_postprocess_AA (const GhostedAreaSpec & ghost_spec) {
+  _average_area  /= ghost_spec.repeat();
+  _average_area2 /= ghost_spec.repeat();
+  if (ghost_spec.repeat() > 1) {
+    // the VC compiler complains if one puts everything on a single line.
+    // An alternative solution would be to use -1.0 (+single line)
+    const double tmp = ghost_spec.repeat()-1;
+    _average_area2 = sqrt(abs(_average_area2 - _average_area*_average_area)/tmp);
+  } else {
+    _average_area2 = 0.0;
+  }
+
+  _non_jet_area  /= ghost_spec.repeat();
+  _non_jet_area2 /= ghost_spec.repeat();
+  _non_jet_area2  = sqrt(abs(_non_jet_area2 - _non_jet_area*_non_jet_area)/
+			 ghost_spec.repeat());
+  _non_jet_number /= ghost_spec.repeat();
+
+  // following bizarre way of writing things is related to 
+  // poverty of operations on PseudoJet objects (as well as some confusion
+  // in one or two places)
+  for (unsigned i = 0; i < _average_area_4vector.size(); i++) {
+    _average_area_4vector[i] = (1.0/ghost_spec.repeat()) * _average_area_4vector[i];
+  }
+  //cerr << "Non-jet area = " << _non_jet_area << " +- " << _non_jet_area2<<endl;
+}
+
+
+// //----------------------------------------------------------------------
+// void ClusterSequenceActiveArea::_initialise_and_run_AA (
+// 		const JetDefinition & jet_def,
+// 		const GhostedAreaSpec & ghost_spec,
+// 		const bool & writeout_combinations) 
+// {
+// 
+//   // store this for future use
+//   _ghost_spec_repeat = ghost_spec.repeat();
+// 
+//   // initialize our local area information
+//   _average_area.resize(2*_jets.size());  _average_area  = 0.0;
+//   _average_area2.resize(2*_jets.size()); _average_area2 = 0.0;
+//   _average_area_4vector.resize(2*_jets.size()); 
+//   _average_area_4vector = PseudoJet(0.0,0.0,0.0,0.0);
+//   _non_jet_area = 0.0; _non_jet_area2 = 0.0; _non_jet_number=0.0;
+//      
+//   // for future reference...
+//   _maxrap_for_area = ghost_spec.ghost_maxrap();
+//   _safe_rap_for_area = _maxrap_for_area - jet_def.R();
+// 
+//   // Make sure we'll have at least one repetition -- then we can
+//   // deduce the unghosted clustering sequence from one of the ghosted
+//   // sequences. If we do not have any repetitions, then get the
+//   // unghosted sequence from the plain unghosted clustering.
+//   //
+//   // NB: all decanting and filling of initial history will then
+//   // be carried out by base-class routine
+//   if (ghost_spec.repeat() <= 0) {
+//     _initialise_and_run(jet_def, writeout_combinations);
+//     return;
+//   }
+// 
+//   // transfer all relevant info into internal variables
+//   _decant_options(jet_def, writeout_combinations);
+// 
+//   // set up the history entries for the initial particles (those
+//   // currently in _jets)
+//   _fill_initial_history();
+// 
+//   // record the input jets as they are currently
+//   vector<PseudoJet> input_jets(_jets);
+// 
+//   // code for testing the unique tree
+//   vector<int> unique_tree;
+// 
+//   
+//   
+// 
+//   // run the clustering multiple times so as to get areas of all the jets
+//   for (int irepeat = 0; irepeat < ghost_spec.repeat(); irepeat++) {
+// 
+//     ClusterSequenceActiveAreaExplicitGhosts clust_seq(input_jets, 
+//                                                       jet_def, ghost_spec);
+// 
+//     if (irepeat == 0) {
+//       // take the non-ghost part of the history and put into our own
+//       // history.
+//       _transfer_ghost_free_history(clust_seq);
+//       // get the "unique" order that will be used for transferring all areas. 
+//       unique_tree = unique_history_order();
+//     }
+// 
+//     // transfer areas from clust_seq into our object
+//     _transfer_areas(unique_tree, clust_seq);
+//   }
+//   
+//   _average_area  /= ghost_spec.repeat();
+//   _average_area2 /= ghost_spec.repeat();
+//   if (ghost_spec.repeat() > 1) {
+//     _average_area2 = sqrt(abs(_average_area2 - _average_area*_average_area)/
+//                           (ghost_spec.repeat()-1));
+//   } else {
+//     _average_area2 = 0.0;
+//   }
+// 
+//   _non_jet_area  /= ghost_spec.repeat();
+//   _non_jet_area2 /= ghost_spec.repeat();
+//   _non_jet_area2  = sqrt(abs(_non_jet_area2 - _non_jet_area*_non_jet_area)/
+// 			 ghost_spec.repeat());
+//   _non_jet_number /= ghost_spec.repeat();
+// 
+//   // following bizarre way of writing things is related to 
+//   // poverty of operations on PseudoJet objects (as well as some confusion
+//   // in one or two places)
+//   for (unsigned i = 0; i < _average_area_4vector.size(); i++) {
+//     _average_area_4vector[i] = (1.0/ghost_spec.repeat()) * _average_area_4vector[i];
+//   }
+//   //cerr << "Non-jet area = " << _non_jet_area << " +- " << _non_jet_area2<<endl;
+// 
+//   
+// }
+// 
+
+
+//----------------------------------------------------------------------
+double ClusterSequenceActiveArea::pt_per_unit_area(
+		       mean_pt_strategies strat, double range) const {
+  
+  vector<PseudoJet> incl_jets = inclusive_jets();
+  vector<double> pt_over_areas;
+
+  for (unsigned i = 0; i < incl_jets.size(); i++) {
+    if (abs(incl_jets[i].rap()) < _safe_rap_for_area) {
+      double this_area;
+      if ( strat == median_4vector ) {
+          this_area = area_4vector(incl_jets[i]).perp();
+      } else {
+          this_area = area(incl_jets[i]);
+      }
+      pt_over_areas.push_back(incl_jets[i].perp()/this_area);
+    }
+  }
+  
+  // there is nothing inside our region, so answer will always be zero
+  if (pt_over_areas.size() == 0) {return 0.0;}
+  
+  // get median (pt/area) [this is the "old" median definition. It considers
+  // only the "real" jets in calculating the median, i.e. excluding the
+  // only-ghost ones]
+  sort(pt_over_areas.begin(), pt_over_areas.end());
+  double non_ghost_median_ratio = pt_over_areas[pt_over_areas.size()/2];
+
+  // new median definition that takes into account non-jet area (i.e.
+  // jets composed only of ghosts), and for fractional median position 
+  // interpolates between the corresponding entries in the pt_over_areas array
+  double nj_median_pos = (pt_over_areas.size()-1 - _non_jet_number)/2.0;
+  double nj_median_ratio;
+  if (nj_median_pos >= 0 && pt_over_areas.size() > 1) {
+    int int_nj_median = int(nj_median_pos);
+    nj_median_ratio = 
+      pt_over_areas[int_nj_median] * (int_nj_median+1-nj_median_pos)
+      + pt_over_areas[int_nj_median+1] * (nj_median_pos - int_nj_median);
+  } else {
+    nj_median_ratio = 0.0;
+  }
+
+
+  // get various forms of mean (pt/area)
+  double pt_sum = 0.0, pt_sum_with_cut = 0.0;
+  double area_sum = _non_jet_area, area_sum_with_cut = _non_jet_area;
+  double ratio_sum = 0.0; 
+  double ratio_n = _non_jet_number;
+  for (unsigned i = 0; i < incl_jets.size(); i++) {
+    if (abs(incl_jets[i].rap()) < _safe_rap_for_area) {
+      double this_area;
+      if ( strat == median_4vector ) {
+          this_area = area_4vector(incl_jets[i]).perp();
+      } else {
+          this_area = area(incl_jets[i]);
+      }
+      pt_sum   += incl_jets[i].perp();
+      area_sum += this_area;
+      double ratio = incl_jets[i].perp()/this_area;
+      if (ratio < range*nj_median_ratio) {
+	pt_sum_with_cut   += incl_jets[i].perp();
+	area_sum_with_cut += this_area;
+	ratio_sum += ratio; ratio_n++;
+      }
+    }
+  }
+  
+  if (strat == play) {
+    double trunc_sum = 0, trunc_sumsqr = 0;
+    vector<double> means(pt_over_areas.size()), sd(pt_over_areas.size());
+    for (unsigned i = 0; i < pt_over_areas.size() ; i++ ) {
+      double ratio = pt_over_areas[i];
+      trunc_sum += ratio;
+      trunc_sumsqr += ratio*ratio;
+      means[i] = trunc_sum / (i+1);
+      sd[i]    = sqrt(abs(means[i]*means[i]  - trunc_sumsqr/(i+1)));
+      cerr << "i, means, sd: " <<i<<", "<< means[i] <<", "<<sd[i]<<", "<<
+	sd[i]/sqrt(i+1.0)<<endl;
+    }
+    cout << "-----------------------------------"<<endl;
+    for (unsigned i = 0; i <= pt_over_areas.size()/2 ; i++ ) {
+      cout << "Median "<< i <<" = " << pt_over_areas[i]<<endl;
+    }
+    cout << "Number of non-jets: "<<_non_jet_number<<endl;
+    cout << "Area of non-jets: "<<_non_jet_area<<endl;
+    cout << "Default median position: " << (pt_over_areas.size()-1)/2.0<<endl;
+    cout << "NJ median position: " << nj_median_pos <<endl;
+    cout << "NJ median value: " << nj_median_ratio <<endl;
+    return 0.0;
+  }
+
+  switch(strat) {
+  case median:
+  case median_4vector:
+    return nj_median_ratio;
+  case non_ghost_median:
+    return non_ghost_median_ratio; 
+  case pttot_over_areatot:
+    return pt_sum / area_sum;
+  case pttot_over_areatot_cut:
+    return pt_sum_with_cut / area_sum_with_cut;
+  case mean_ratio_cut:
+    return ratio_sum/ratio_n;
+  default:
+    return nj_median_ratio;
+  }
+
+}
+
+
+// The following functionality is now provided by the base class
+// //----------------------------------------------------------------------
+// // fit a parabola to pt/area as a function of rapidity, using the
+// // formulae of CCN28-36 (which actually fits f = a+b*x^2)
+// void ClusterSequenceActiveArea::parabolic_pt_per_unit_area(
+//        double & a, double & b, double raprange, double exclude_above,
+//        bool use_area_4vector) const {
+//   
+//   double this_raprange;
+//   if (raprange <= 0) {this_raprange = _safe_rap_for_area;}
+//   else {this_raprange = raprange;}
+// 
+//   int n=0;
+//   int n_excluded = 0;
+//   double mean_f=0, mean_x2=0, mean_x4=0, mean_fx2=0; 
+// 
+//   vector<PseudoJet> incl_jets = inclusive_jets();
+// 
+//   for (unsigned i = 0; i < incl_jets.size(); i++) {
+//     if (abs(incl_jets[i].rap()) < this_raprange) {
+//       double this_area;
+//       if ( use_area_4vector ) {
+//           this_area = area_4vector(incl_jets[i]).perp();     
+//       } else {
+//           this_area = area(incl_jets[i]);
+//       }
+//       double f = incl_jets[i].perp()/this_area;
+//       if (exclude_above <= 0.0 || f < exclude_above) {
+// 	double x = incl_jets[i].rap(); double x2 = x*x;
+// 	mean_f   += f;
+// 	mean_x2  += x2;
+// 	mean_x4  += x2*x2;
+// 	mean_fx2 += f*x2;
+// 	n++;
+//       } else {
+// 	n_excluded++;
+//       }
+//     }
+//   }
+// 
+//   if (n <= 1) {
+//     // meaningful results require at least two jets inside the
+//     // area -- mind you if there are empty jets we should be in 
+//     // any case doing something special...
+//     a = 0.0;
+//     b = 0.0;
+//   } else {
+//     mean_f   /= n;
+//     mean_x2  /= n;
+//     mean_x4  /= n;
+//     mean_fx2 /= n;
+//     
+//     b = (mean_f*mean_x2 - mean_fx2)/(mean_x2*mean_x2 - mean_x4);
+//     a = mean_f - b*mean_x2;
+//   }
+//   //cerr << "n_excluded = "<< n_excluded << endl;
+// }
+
+
+//----------------------------------------------------------------------
+double ClusterSequenceActiveArea::empty_area(const Selector & selector) const {
+  // make sure that the selector applies jet by jet
+  if (! selector.applies_jet_by_jet()){
+    throw Error("ClusterSequenceActiveArea: empty area can only be computed from selectors applying jet by jet");
+  }
+
+  double empty = 0.0;
+  // first deal with ghost jets
+  for (unsigned  i = 0; i < _ghost_jets.size(); i++) {
+    if (selector.pass(_ghost_jets[i])) {
+      empty += _ghost_jets[i].area;
+    }
+  }
+  // then deal with unclustered ghosts
+  for (unsigned  i = 0; i < _unclustered_ghosts.size(); i++) {
+    if (selector.pass(_unclustered_ghosts[i])) {
+      empty += _unclustered_ghosts[i].area;
+    }
+  }
+  empty /= _ghost_spec_repeat;
+  return empty;
+}
+
+//----------------------------------------------------------------------
+double ClusterSequenceActiveArea::n_empty_jets(const Selector & selector) const {
+  _check_selector_good_for_median(selector);
+
+  double inrange = 0;
+  for (unsigned  i = 0; i < _ghost_jets.size(); i++) {
+    if (selector.pass(_ghost_jets[i])) inrange++;
+  }
+  inrange /= _ghost_spec_repeat;
+  return inrange;
+}
+
+//----------------------------------------------------------------------
+/// transfer the history (and jet-momenta) from clust_seq to our
+/// own internal structure while removing ghosts
+void ClusterSequenceActiveArea::_transfer_ghost_free_history(
+             const ClusterSequenceActiveAreaExplicitGhosts & ghosted_seq) {
+  
+  const vector<history_element> & gs_history  = ghosted_seq.history();
+  vector<int> gs2self_hist_map(gs_history.size());
+
+  // first transfer info about strategy used (which isn't necessarily
+  // always the one that got asked for...)
+  _strategy = ghosted_seq.strategy_used();
+
+  // work our way through to first non-trivial combination
+  unsigned igs = 0;
+  unsigned iself = 0;
+  while (igs < gs_history.size() && gs_history[igs].parent1 == InexistentParent) {
+    // record correspondence 
+    if (!ghosted_seq.is_pure_ghost(igs)) {
+      gs2self_hist_map[igs] = iself++; 
+    } else {
+      gs2self_hist_map[igs] = Invalid; 
+    }
+    igs++;
+  };
+
+  // make sure the count of non-ghost initial jets is equal to
+  // what we already have in terms of initial jets
+  assert(iself == _history.size());
+
+  // if there was no clustering in this event (e.g. SISCone passive
+  // area with zero input particles, or with a pt cut on stable cones
+  // that kills all jets), then don't bother with the rest (which
+  // would crash!)
+  if (igs == gs_history.size()) return;
+  
+  // now actually transfer things
+  do  {
+    // if we are a pure ghost, then go on to next round
+    if (ghosted_seq.is_pure_ghost(igs)) {
+      gs2self_hist_map[igs] = Invalid;
+      continue;
+    }
+
+    const history_element & gs_hist_el = gs_history[igs];
+
+    bool parent1_is_ghost = ghosted_seq.is_pure_ghost(gs_hist_el.parent1);
+    bool parent2_is_ghost = ghosted_seq.is_pure_ghost(gs_hist_el.parent2);
+
+    // if exactly one parent is a ghost then maintain info about the
+    // non-ghost correspondence for this jet, and then go on to next
+    // recombination in the ghosted sequence
+    if (parent1_is_ghost && !parent2_is_ghost && gs_hist_el.parent2 >= 0) {
+      gs2self_hist_map[igs] = gs2self_hist_map[gs_hist_el.parent2];
+      continue;
+    }
+    if (!parent1_is_ghost && parent2_is_ghost) {
+      gs2self_hist_map[igs] = gs2self_hist_map[gs_hist_el.parent1];
+      continue;
+    }
+
+    // no parents are ghosts...
+    if (gs_hist_el.parent2 >= 0) {
+      // recombination of two non-ghosts
+      gs2self_hist_map[igs] = _history.size();
+      // record the recombination in our own sequence
+      int newjet_k; // dummy var -- not used
+      int jet_i = _history[gs2self_hist_map[gs_hist_el.parent1]].jetp_index;
+      int jet_j = _history[gs2self_hist_map[gs_hist_el.parent2]].jetp_index;
+      //cerr << "recombining "<< jet_i << " and "<< jet_j << endl;
+      _do_ij_recombination_step(jet_i, jet_j, gs_hist_el.dij, newjet_k);
+    } else {
+      // we have a non-ghost that has become a beam-jet
+      assert(gs_history[igs].parent2 == BeamJet);
+      // record position
+      gs2self_hist_map[igs] = _history.size();
+      // record the recombination in our own sequence
+      _do_iB_recombination_step(
+             _history[gs2self_hist_map[gs_hist_el.parent1]].jetp_index,
+             gs_hist_el.dij);
+    }
+  } while (++igs < gs_history.size());
+
+}
+
+//----------------------------------------------------------------------
+void ClusterSequenceActiveArea::_transfer_areas(
+	    const vector<int> & unique_hist_order,
+    	    const ClusterSequenceActiveAreaExplicitGhosts & ghosted_seq  ) {
+
+  const vector<history_element> & gs_history  = ghosted_seq.history();
+  const vector<PseudoJet>       & gs_jets     = ghosted_seq.jets();
+  vector<int>    gs_unique_hist_order = ghosted_seq.unique_history_order();
+
+  const double tolerance = 1e-11; // to decide when two jets are the same
+
+  int j = -1;
+  int hist_index = -1;
+  
+  valarray<double> our_areas(_history.size());
+  our_areas = 0.0;
+
+  valarray<PseudoJet> our_area_4vectors(_history.size());
+  our_area_4vectors = PseudoJet(0.0,0.0,0.0,0.0);
+
+  for (unsigned i = 0; i < gs_history.size(); i++) {
+    // only consider composite particles
+    unsigned gs_hist_index = gs_unique_hist_order[i];
+    if (gs_hist_index < ghosted_seq.n_particles()) continue;
+    const history_element & gs_hist = gs_history[gs_unique_hist_order[i]];
+    int parent1 = gs_hist.parent1;
+    int parent2 = gs_hist.parent2;
+
+    if (parent2 == BeamJet) {
+      // need to look at parent to get the actual jet
+      const PseudoJet & jet = 
+  	  gs_jets[gs_history[parent1].jetp_index];
+      double area_local = ghosted_seq.area(jet);
+      PseudoJet ext_area = ghosted_seq.area_4vector(jet);
+
+      if (ghosted_seq.is_pure_ghost(parent1)) {
+        // record the existence of the pure ghost jet for future use
+        _ghost_jets.push_back(GhostJet(jet,area_local));
+	if (abs(jet.rap()) < _safe_rap_for_area) {
+	  _non_jet_area  += area_local;
+	  _non_jet_area2 += area_local*area_local;
+	  _non_jet_number += 1;
+	}
+      } else {
+
+	// get next "combined-particle" index in our own history
+	// making sure we don't go beyond its bounds (if we do
+	// then we're in big trouble anyway...)
+	while (++j < int(_history.size())) {
+	  hist_index = unique_hist_order[j];
+	  if (hist_index >= _initial_n) break;}
+
+        // sanity checking -- do not overrun
+        if (j >= int(_history.size())) throw Error("ClusterSequenceActiveArea: overran reference array in diB matching");
+
+        // sanity check -- make sure we are taking about the same 
+        // jet in reference and new sequences
+        int refjet_index = _history[_history[hist_index].parent1].jetp_index;
+        assert(refjet_index >= 0 && refjet_index < int(_jets.size()));
+	const PseudoJet & refjet = _jets[refjet_index];
+
+      //cerr << "Inclusive" << endl;
+      //cerr << gs_history[parent1].jetp_index << " " << gs_jets.size() << endl;
+      //cerr << _history[_history[hist_index].parent1].jetp_index << " " << _jets.size() << endl;
+
+        // If pt disagrees check E; if they both disagree there's a
+        // problem here... NB: a massive particle with zero pt may
+        // have its pt changed when a ghost is added -- this is why we
+        // also require the energy to be wrong before complaining
+        _throw_unless_jets_have_same_perp_or_E(jet, refjet, tolerance,
+                                               ghosted_seq);
+
+	// set the area at this clustering stage
+	our_areas[hist_index]  = area_local; 
+	our_area_4vectors[hist_index]  = ext_area; 
+
+	// update the parent as well -- that way its area is the area
+	// immediately before clustering (i.e. resolve an ambiguity in
+	// the Cambridge case and ensure in the kt case that the original
+	// particles get a correct area)
+	our_areas[_history[hist_index].parent1] = area_local;
+	our_area_4vectors[_history[hist_index].parent1] = ext_area;
+	
+      }
+    }
+    else if (!ghosted_seq.is_pure_ghost(parent1) && 
+	     !ghosted_seq.is_pure_ghost(parent2)) {
+
+      // get next "combined-particle" index in our own history
+      while (++j < int(_history.size())) {
+	hist_index = unique_hist_order[j];
+	if (hist_index >= _initial_n) break;}
+      
+      // sanity checking -- do not overrun
+      if (j >= int(_history.size())) throw Error("ClusterSequenceActiveArea: overran reference array in dij matching");
+
+      // make sure that our reference history entry is also for
+      // an exclusive (dij) clustering (otherwise the comparison jet
+      // will not exist)
+      if (_history[hist_index].parent2 == BeamJet) throw Error("ClusterSequenceActiveArea: could not match clustering sequences (encountered dij matched with diB)");
+
+      //cerr << "Exclusive: hist_index,hist_size: " << hist_index << " " << _history.size()<< endl;
+      //cerr << gs_hist.jetp_index << " " << gs_jets.size() << endl;
+      //cerr << _history[hist_index].jetp_index << " " << _jets.size() << endl;
+
+      const PseudoJet & jet = gs_jets[gs_hist.jetp_index];
+      const PseudoJet & refjet = _jets[_history[hist_index].jetp_index];
+
+      // run sanity check 
+      _throw_unless_jets_have_same_perp_or_E(jet, refjet, tolerance,
+                                             ghosted_seq);
+
+      // update area and our local index (maybe redundant since later
+      // the descendants will reupdate it?)
+      double area_local  = ghosted_seq.area(jet);
+      our_areas[hist_index]  += area_local; 
+
+      PseudoJet ext_area = ghosted_seq.area_4vector(jet);
+
+      // GPS TMP debugging (jetclu) -----------------------
+      //ext_area = PseudoJet(1e-100,1e-100,1e-100,4e-100);
+      //our_area_4vectors[hist_index] = ext_area;
+      //cout << "aa " 
+      //     << our_area_4vectors[hist_index].px() << " "
+      //     << our_area_4vectors[hist_index].py() << " "
+      //     << our_area_4vectors[hist_index].pz() << " "
+      //     << our_area_4vectors[hist_index].E() << endl;
+      //cout << "bb " 
+      //     << ext_area.px() << " "
+      //     << ext_area.py() << " "
+      //     << ext_area.pz() << " "
+      //     << ext_area.E() << endl;
+      //---------------------------------------------------
+
+      _jet_def.recombiner()->plus_equal(our_area_4vectors[hist_index], ext_area);
+
+      // now update areas of parents (so that they becomes areas
+      // immediately before clustering occurred). This is of use
+      // because it allows us to set the areas of the original hard
+      // particles in the kt algorithm; for the Cambridge case it
+      // means a jet's area will be the area just before it clusters
+      // with another hard jet.
+      const PseudoJet & jet1 = gs_jets[gs_history[parent1].jetp_index];
+      int our_parent1 = _history[hist_index].parent1;
+      our_areas[our_parent1] = ghosted_seq.area(jet1);
+      our_area_4vectors[our_parent1] = ghosted_seq.area_4vector(jet1);
+
+      const PseudoJet & jet2 = gs_jets[gs_history[parent2].jetp_index];
+      int our_parent2 = _history[hist_index].parent2;
+      our_areas[our_parent2] = ghosted_seq.area(jet2);
+      our_area_4vectors[our_parent2] = ghosted_seq.area_4vector(jet2);
+    }
+
+  }
+
+  // now add unclustered ghosts to the relevant list so that we can
+  // calculate empty area later.
+  vector<PseudoJet> unclust = ghosted_seq.unclustered_particles();
+  for (unsigned iu = 0; iu < unclust.size();  iu++) {
+    if (ghosted_seq.is_pure_ghost(unclust[iu])) {
+      double area_local = ghosted_seq.area(unclust[iu]);
+      _unclustered_ghosts.push_back(GhostJet(unclust[iu],area_local));
+    }
+  }
+
+  /*
+   * WARNING:
+   *   _average_area has explicitly been sized initially to 2*jets().size()
+   *   which can be bigger than our_areas (of size _history.size()
+   *   if there are some unclustered particles. 
+   *   So we must take care about boundaries
+   */
+
+  for (unsigned int area_index = 0; area_index<our_areas.size(); area_index++){
+    _average_area[area_index]  += our_areas[area_index]; 
+    _average_area2[area_index] += our_areas[area_index]*our_areas[area_index]; 
+  }
+
+  //_average_area_4vector += our_area_4vectors;
+  // Use the proper recombination scheme when averaging the area_4vectors
+  // over multiple ghost runs (i.e. the repeat stage);
+  for (unsigned i = 0; i < our_area_4vectors.size(); i++) {
+    _jet_def.recombiner()->plus_equal(_average_area_4vector[i],
+                                       our_area_4vectors[i]);
+  }
+}
+
+
+/// check if two jets have the same momentum to within the
+/// tolerance (and if pt's are not the same we're forgiving and
+/// look to see if the energy is the same)
+void ClusterSequenceActiveArea::_throw_unless_jets_have_same_perp_or_E(
+                                const PseudoJet & jet, 
+                                const PseudoJet & refjet, 
+                                double tolerance,
+          const ClusterSequenceActiveAreaExplicitGhosts & jets_ghosted_seq
+) const {
+
+  if (abs(jet.perp2()-refjet.perp2()) > 
+      tolerance*max(jet.perp2(),refjet.perp2())
+      && abs(jet.E()-refjet.E()) > tolerance*max(jet.E(),refjet.E())) {
+    ostringstream ostr;
+    ostr << "Could not match clustering sequence for an inclusive/exclusive jet when reconstructing areas. See FAQ for possible explanations." << endl;
+    ostr << "  Ref-Jet: "
+         << refjet.px() << " " 
+         << refjet.py() << " " 
+         << refjet.pz() << " " 
+         << refjet.E() << endl;
+    ostr << "  New-Jet: "
+         << jet.px() << " " 
+         << jet.py() << " " 
+         << jet.pz() << " " 
+         << jet.E() << endl;
+    if (jets_ghosted_seq.has_dangerous_particles()) {
+      ostr << "  NB: some particles have pt too low wrt ghosts -- this may be the cause" << endl;}
+    //ostr << jet.perp() << " " << refjet.perp() << " "
+    //     << jet.perp() - refjet.perp() << endl;
+    throw Error(ostr.str());
+  }
+}
+
+FASTJET_END_NAMESPACE
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceActiveArea.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceActiveArea.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceActiveArea.hh	(revision 5)
@@ -0,0 +1,228 @@
+//STARTHEADER
+// $Id: ClusterSequenceActiveArea.hh 2687 2011-11-14 11:17:51Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLUSTERSEQUENCEACTIVEAREA_HH__
+#define __FASTJET_CLUSTERSEQUENCEACTIVEAREA_HH__
+
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/ClusterSequenceAreaBase.hh"
+#include "fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh"
+#include<iostream>
+#include<vector>
+
+//------------ backwards compatibility with version 2.1 -------------
+// for backwards compatibility make ActiveAreaSpec name available
+//#include "fastjet/ActiveAreaSpec.hh"
+//#include "fastjet/ClusterSequenceWithArea.hh"
+//--------------------------------------------------------------------
+
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//using namespace std;
+
+/// @ingroup sec_area_classes
+/// \class ClusterSequenceActiveArea
+/// Like ClusterSequence with computation of the active jet area
+///
+/// Class that behaves essentially like ClusterSequence except
+/// that it also provides access to the area of a jet (which
+/// will be a random quantity... Figure out what to do about seeds 
+/// later...)
+///
+/// This class should not be used directly. Rather use
+/// ClusterSequenceArea with the appropriate AreaDefinition
+class ClusterSequenceActiveArea : public ClusterSequenceAreaBase {
+public:
+
+  /// default constructor
+  ClusterSequenceActiveArea() {}
+
+  /// constructor based on JetDefinition and GhostedAreaSpec
+  template<class L> ClusterSequenceActiveArea
+         (const std::vector<L> & pseudojets, 
+	  const JetDefinition & jet_def_in,
+	  const GhostedAreaSpec & ghost_spec,
+	  const bool & writeout_combinations = false) ;
+
+  virtual double area (const PseudoJet & jet) const {
+                             return _average_area[jet.cluster_hist_index()];};
+  virtual double area_error (const PseudoJet & jet) const {
+                             return _average_area2[jet.cluster_hist_index()];};
+
+  virtual PseudoJet area_4vector (const PseudoJet & jet) const {
+                    return _average_area_4vector[jet.cluster_hist_index()];};
+
+  /// enum providing a variety of tentative strategies for estimating
+  /// the background (e.g. non-jet) activity in a highly populated event; the
+  /// one that has been most extensively tested is median.
+  enum mean_pt_strategies{median=0, non_ghost_median, pttot_over_areatot, 
+			  pttot_over_areatot_cut, mean_ratio_cut, play,
+			  median_4vector};
+
+  /// return the transverse momentum per unit area according to one
+  /// of the above strategies; for some strategies (those with "cut"
+  /// in their name) the parameter "range" allows one to exclude a
+  /// subset of the jets for the background estimation, those that
+  /// have pt/area > median(pt/area)*range.
+  ///
+  /// NB: This call is OBSOLETE; use media_pt_per_unit_area from the
+  //      ClusterSequenceAreaBase class instead
+  double pt_per_unit_area(mean_pt_strategies strat=median, 
+                          double range=2.0 ) const;
+
+  // following code removed -- now dealt with by AreaBase class (and
+  // this definition here conflicts with it).
+//   /// fits a form pt_per_unit_area(y) = a + b*y^2 in the range
+//   /// abs(y)<raprange (for negative raprange, it defaults to
+//   /// _safe_rap_for_area).
+//   void parabolic_pt_per_unit_area(double & a,double & b, double raprange=-1.0,
+// 				  double exclude_above=-1.0, 
+// 				  bool use_area_4vector=false ) const;
+// 
+  /// rewrite the empty area from the parent class, so as to use
+  /// all info at our disposal
+  /// return the total area, corresponding to a given Selector, that
+  /// consists of ghost jets or unclustered ghosts
+  ///
+  /// The selector passed as an argument needs to apply jet by jet.
+  virtual double empty_area(const Selector & selector) const;
+
+  /// return the true number of empty jets (replaces
+  /// ClusterSequenceAreaBase::n_empty_jets(...))
+  virtual double n_empty_jets(const Selector & selector) const;
+
+protected:
+  void _resize_and_zero_AA ();
+  void _initialise_AA(const JetDefinition & jet_def,
+                      const GhostedAreaSpec & ghost_spec,
+                      const bool & writeout_combinations,
+                      bool & continue_running);
+
+  void _run_AA(const GhostedAreaSpec & ghost_spec);
+
+  void _postprocess_AA(const GhostedAreaSpec & ghost_spec);
+
+  /// does the initialisation and running specific to the active
+  /// areas class
+  void _initialise_and_run_AA (const JetDefinition & jet_def,
+                               const GhostedAreaSpec & ghost_spec,
+                               const bool & writeout_combinations = false);
+
+  /// transfer the history (and jet-momenta) from clust_seq to our
+  /// own internal structure while removing ghosts
+  void _transfer_ghost_free_history(
+           const ClusterSequenceActiveAreaExplicitGhosts & clust_seq);
+
+
+  /// transfer areas from the ClusterSequenceActiveAreaExplicitGhosts
+  /// object into our internal area bookkeeping...
+  void _transfer_areas(const std::vector<int> & unique_hist_order, 
+                       const ClusterSequenceActiveAreaExplicitGhosts & );
+
+  /// child classes benefit from having these at their disposal
+  std::valarray<double> _average_area, _average_area2;
+  std::valarray<PseudoJet> _average_area_4vector;
+
+  /// returns true if there are any particles whose transverse momentum
+  /// if so low that there's a risk of the ghosts having modified the
+  /// clustering sequence
+  bool has_dangerous_particles() const {return _has_dangerous_particles;}
+
+private:
+
+
+  double           _non_jet_area, _non_jet_area2, _non_jet_number;
+
+  double _maxrap_for_area; // max rap where we put ghosts
+  double _safe_rap_for_area; // max rap where we trust jet areas
+
+  bool   _has_dangerous_particles; 
+
+
+  /// routine for extracting the tree in an order that will be independent
+  /// of any degeneracies in the recombination sequence that don't
+  /// affect the composition of the final jets
+  void _extract_tree(std::vector<int> &) const;
+  /// do the part of the extraction associated with pos, working
+  /// through its children and their parents
+  void _extract_tree_children(int pos, std::valarray<bool> &, const std::valarray<int> &, std::vector<int> &) const;
+  /// do the part of the extraction associated with the parents of pos.
+  void _extract_tree_parents (int pos, std::valarray<bool> &, const std::valarray<int> &,  std::vector<int> &) const;
+
+  /// check if two jets have the same momentum to within the
+  /// tolerance (and if pt's are not the same we're forgiving and
+  /// look to see if the energy is the same)
+  void _throw_unless_jets_have_same_perp_or_E(const PseudoJet & jet, 
+                                              const PseudoJet & refjet, 
+                                              double tolerance,
+             const ClusterSequenceActiveAreaExplicitGhosts & jets_ghosted_seq
+                                              ) const;
+
+  /// since we are playing nasty games with seeds, we should warn
+  /// the user a few times
+  //static int _n_seed_warnings;
+  //const static int _max_seed_warnings = 10;
+
+  // record the number of repeats
+  int _ghost_spec_repeat;
+
+  /// a class for our internal storage of ghost jets
+  class GhostJet : public PseudoJet {
+  public:
+    GhostJet(const PseudoJet & j, double a) : PseudoJet(j), area(a){}
+    double area;
+  };
+
+  std::vector<GhostJet> _ghost_jets;
+  std::vector<GhostJet> _unclustered_ghosts;
+};
+
+
+
+
+template<class L> ClusterSequenceActiveArea::ClusterSequenceActiveArea 
+(const std::vector<L> & pseudojets, 
+ const JetDefinition & jet_def_in,
+ const GhostedAreaSpec & ghost_spec,
+ const bool & writeout_combinations) {
+
+  // transfer the initial jets (type L) into our own array
+  _transfer_input_jets(pseudojets);
+
+  // run the clustering for active areas
+  _initialise_and_run_AA(jet_def_in, ghost_spec, writeout_combinations);
+
+}
+
+
+  
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_CLUSTERSEQUENCEACTIVEAREA_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceActiveAreaExplicitGhosts.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceActiveAreaExplicitGhosts.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceActiveAreaExplicitGhosts.cc	(revision 5)
@@ -0,0 +1,202 @@
+//STARTHEADER
+// $Id: ClusterSequenceActiveAreaExplicitGhosts.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh"
+#include<limits>
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+// save some typing
+typedef ClusterSequenceActiveAreaExplicitGhosts ClustSeqActAreaEG;
+
+
+LimitedWarning ClustSeqActAreaEG::_warnings;
+
+//----------------------------------------------------------------------
+///
+void ClustSeqActAreaEG::_add_ghosts (
+			 const GhostedAreaSpec & ghost_spec) {
+
+  // add the ghosts to the jets
+  ghost_spec.add_ghosts(_jets);
+
+  // now add labelling...
+  for (unsigned i = _initial_hard_n; i < _jets.size(); i++) {
+    //_jets[i].set_user_index(1);
+    _is_pure_ghost.push_back(true);
+  }
+
+  // and record some info from the ghost_spec
+  _ghost_area = ghost_spec.actual_ghost_area();
+  _n_ghosts   = ghost_spec.n_ghosts();
+}
+
+
+//----------------------------------------------------------------------
+// return the area of a jet
+double ClustSeqActAreaEG::area (const PseudoJet & jet) const {
+  return _areas[jet.cluster_hist_index()];
+}
+
+
+//----------------------------------------------------------------------
+// return the total area
+double ClustSeqActAreaEG::total_area () const {
+  return _n_ghosts * _ghost_area;
+}
+
+
+//----------------------------------------------------------------------
+// return the extended area of a jet
+PseudoJet ClustSeqActAreaEG::area_4vector (const PseudoJet & jet) const {
+  return _area_4vectors[jet.cluster_hist_index()];
+}
+
+//----------------------------------------------------------------------
+bool ClustSeqActAreaEG::is_pure_ghost(const PseudoJet & jet) const 
+{
+  return _is_pure_ghost[jet.cluster_hist_index()];
+}
+
+//----------------------------------------------------------------------
+bool ClustSeqActAreaEG::is_pure_ghost(int hist_ix) const 
+{
+  return hist_ix >= 0 ? _is_pure_ghost[hist_ix] : false;
+}
+
+//----------------------------------------------------------------------
+double ClustSeqActAreaEG::empty_area(const Selector & selector) const {
+  // make sure that the selector applies jet by jet
+  if (! selector.applies_jet_by_jet()){
+    throw Error("ClusterSequenceActiveAreaExplicitGhosts: empty area can only be computed from selectors applying jet by jet");
+  }
+
+  vector<PseudoJet> unclust = unclustered_particles();
+  double area_local = 0.0;
+  for (unsigned iu = 0; iu < unclust.size();  iu++) {
+    if (is_pure_ghost(unclust[iu]) && selector.pass(unclust[iu])) {
+      area_local += _ghost_area;
+    }
+  }
+  return area_local;
+}
+
+//======================================================================
+// sort out the areas
+void ClustSeqActAreaEG::_post_process() {
+
+  // first check for danger signals.
+  // Establish largest ghost transverse momentum
+  _max_ghost_perp2 = 0.0;
+  for (int i = 0; i < _initial_n; i++) {
+    if (_is_pure_ghost[i] && _jets[i].perp2() > _max_ghost_perp2) 
+      _max_ghost_perp2 = _jets[i].perp2();
+  }
+
+  // now find out if any of the particles are close to danger
+  double danger_ratio = numeric_limits<double>::epsilon();
+  danger_ratio = danger_ratio * danger_ratio;
+  _has_dangerous_particles = false;
+  for (int i = 0; i < _initial_n; i++) {
+    if (!_is_pure_ghost[i] && 
+        danger_ratio * _jets[i].perp2() <=  _max_ghost_perp2) {
+      _has_dangerous_particles = true;
+      break;
+    }
+  }
+
+  if (_has_dangerous_particles) _warnings.warn("ClusterSequenceActiveAreaExplicitGhosts: \n  ghosts not sufficiently soft wrt some of the input particles\n  a common cause is (unphysical?) input particles with pt=0 but finite rapidity");
+
+  // sort out sizes
+  _areas.resize(_history.size());
+  _area_4vectors.resize(_history.size());
+  _is_pure_ghost.resize(_history.size());
+  
+//   copy(_jets.begin(), _jets.begin()+_initial_n, _area_4vectors.begin());
+//   for (int i = 0; i < _initial_n; i++) {
+//     if (_is_pure_ghost[i]) {
+//       _areas[i] = _ghost_area;
+//       // normalise pt to be _ghost_area (NB we make use of fact that
+//       // for initial particles, jet and clust_hist index are the same).
+//       _area_4vectors[i] *= (_ghost_area/_jets[i].perp());
+//     } else {
+//       _areas[i] = 0;
+//       _area_4vectors[i].reset(0,0,0,0);
+//     }
+//   }
+  
+  // First set up areas for the initial particles (ghost=_ghost_area,
+  // real particles = 0); recall that _initial_n here is the number of
+  // particles including ghosts
+  for (int i = 0; i < _initial_n; i++) {
+    if (_is_pure_ghost[i]) {
+      _areas[i] = _ghost_area;
+      // normalise pt to be _ghost_area (NB we make use of fact that
+      // for initial particles, jet and clust_hist index are the same).
+      //_area_4vectors[i] = (_ghost_area/_jets[i].perp()) * _jets[i];
+      
+      // NB: we use reset_momentum here, to ensure that the area 4
+      // vectors do not acquire any structure (the structure would not
+      // be meaningful for an area, and it messes up the use count (->
+      // memory leaks if the user call delete_self_when_unused).
+      _area_4vectors[i].reset_momentum(_jets[i]);
+      _area_4vectors[i] *= (_ghost_area/_jets[i].perp());
+    } else {
+      _areas[i] = 0;
+      _area_4vectors[i] = PseudoJet(0.0,0.0,0.0,0.0);
+    }
+  }
+  
+  // next follow the branching through and set up the areas 
+  // and ghost-nature at each step of the clustering (rather than
+  // each jet).
+  for (unsigned i = _initial_n; i < _history.size(); i++) {
+    if (_history[i].parent2 == BeamJet) {
+      _is_pure_ghost[i]  = _is_pure_ghost[_history[i].parent1];
+      _areas[i]          = _areas[_history[i].parent1];
+      _area_4vectors[i] = _area_4vectors[_history[i].parent1];
+    } else {
+      _is_pure_ghost[i]  = _is_pure_ghost[_history[i].parent1] && 
+	                   _is_pure_ghost[_history[i].parent2]   ;
+      _areas[i]          = _areas[_history[i].parent1] + 
+	                   _areas[_history[i].parent2]  ;			   
+      _jet_def.recombiner()->recombine(_area_4vectors[_history[i].parent1], 
+	                   _area_4vectors[_history[i].parent2],
+			   _area_4vectors[i]);	
+//      _area_4vectors[i] = _area_4vectors[_history[i].parent1] + 
+//                          _area_4vectors[_history[i].parent2]  ;
+    }
+
+  }
+  
+}
+
+FASTJET_END_NAMESPACE
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh	(revision 5)
@@ -0,0 +1,251 @@
+//STARTHEADER
+// $Id: ClusterSequenceActiveAreaExplicitGhosts.hh 2687 2011-11-14 11:17:51Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLUSTERSEQUENCEACTIVEAREAEXPLICITGHOSTS_HH_
+#define __FASTJET_CLUSTERSEQUENCEACTIVEAREAEXPLICITGHOSTS_HH_ 
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/ClusterSequenceAreaBase.hh"
+#include "fastjet/GhostedAreaSpec.hh"
+#include "fastjet/LimitedWarning.hh"
+#include<iostream>
+#include<vector>
+#include <cstdio>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//======================================================================
+/// @ingroup sec_area_classes
+/// \class ClusterSequenceActiveAreaExplicitGhosts
+/// Like ClusterSequence with computation of the active jet area with the
+/// addition of explicit ghosts
+///
+/// Class that behaves essentially like ClusterSequence except
+/// that it also provides access to the area of a jet (which
+/// will be a random quantity... Figure out what to do about seeds 
+/// later...)
+///
+/// This class should not be used directly. Rather use
+/// ClusterSequenceArea with the appropriate AreaDefinition
+class ClusterSequenceActiveAreaExplicitGhosts : 
+  public ClusterSequenceAreaBase {
+public:
+  /// constructor using a GhostedAreaSpec to specify how the area is
+  /// to be measured
+  template<class L> ClusterSequenceActiveAreaExplicitGhosts
+         (const std::vector<L> & pseudojets, 
+          const JetDefinition & jet_def_in,
+	  const GhostedAreaSpec & ghost_spec,
+	  const bool & writeout_combinations = false) 
+	   : ClusterSequenceAreaBase() {
+           std::vector<L> * ghosts = NULL;
+	   _initialise(pseudojets,jet_def_in,&ghost_spec,ghosts,0.0,
+                       writeout_combinations); }
+
+  template<class L> ClusterSequenceActiveAreaExplicitGhosts
+         (const std::vector<L> & pseudojets, 
+          const JetDefinition & jet_def_in,
+          const std::vector<L> & ghosts,
+          double ghost_area,
+	  const bool & writeout_combinations = false) 
+	   : ClusterSequenceAreaBase() {
+           const GhostedAreaSpec * ghost_spec = NULL;
+	   _initialise(pseudojets,jet_def_in,ghost_spec,&ghosts,ghost_area,
+                       writeout_combinations); }
+
+
+  /// does the actual work of initialisation
+  template<class L> void _initialise
+         (const std::vector<L> & pseudojets, 
+          const JetDefinition & jet_def_in,
+	  const GhostedAreaSpec * ghost_spec,
+	  const std::vector<L> * ghosts,
+	  double                 ghost_area,
+	  const bool & writeout_combinations); 
+
+  //vector<PseudoJet> constituents (const PseudoJet & jet) const;
+
+  /// returns the number of hard particles (i.e. those supplied by the user).
+  unsigned int n_hard_particles() const;
+
+  /// returns the area of a jet
+  virtual double area (const PseudoJet & jet) const;
+
+  /// returns a four vector corresponding to the sum (E-scheme) of the
+  /// ghost four-vectors composing the jet area, normalised such that
+  /// for a small contiguous area the p_t of the extended_area jet is
+  /// equal to area of the jet.
+  virtual PseudoJet area_4vector (const PseudoJet & jet) const;
+
+  /// true if a jet is made exclusively of ghosts
+  virtual bool is_pure_ghost(const PseudoJet & jet) const;
+
+  /// true if the entry in the history index corresponds to a
+  /// ghost; if hist_ix does not correspond to an actual particle
+  /// (i.e. hist_ix < 0), then the result is false.
+  bool is_pure_ghost(int history_index) const;
+
+  /// this class does have explicit ghosts
+  virtual bool has_explicit_ghosts() const {return true;}
+
+  /// return the total area, corresponding to a given Selector, that
+  /// consists of unclustered ghosts
+  ///
+  /// The selector needs to apply jet by jet
+  virtual double empty_area(const Selector & selector) const;
+
+  /// returns the total area under study
+  double total_area () const;
+  
+  /// returns the largest squared transverse momentum among
+  /// all ghosts
+  double max_ghost_perp2() const {return _max_ghost_perp2;}
+
+  /// returns true if there are any particles whose transverse momentum
+  /// if so low that there's a risk of the ghosts having modified the
+  /// clustering sequence
+  bool has_dangerous_particles() const {return _has_dangerous_particles;}
+
+  /// get the area of the ghosts
+  //double ghost_area() const{return _ghost_area;}
+
+private:
+
+  int    _n_ghosts;
+  double _ghost_area;
+  std::vector<bool> _is_pure_ghost;
+  std::vector<double> _areas;
+  std::vector<PseudoJet> _area_4vectors;
+  
+  // things related to checks for dangerous particles
+  double _max_ghost_perp2;
+  bool   _has_dangerous_particles; 
+  static LimitedWarning _warnings;
+
+  //static int _n_warn_dangerous_particles;
+  //static const int _max_warn_dangerous_particles = 5;
+
+  
+  unsigned int _initial_hard_n;
+
+  /// adds the "ghost" momenta, which will be used to estimate
+  /// the jet area
+  void _add_ghosts(const GhostedAreaSpec & ghost_spec); 
+
+  /// another way of adding ghosts
+  template<class L> void _add_ghosts (
+	  const std::vector<L> & ghosts,
+	  double                 ghost_area);
+
+  /// routine to be called after the processing is done so as to
+  /// establish summary information on all the jets (areas, whether
+  /// pure ghost, etc.)
+  void _post_process();
+
+};
+
+
+//----------------------------------------------------------------------
+// initialise from some generic type... Has to be made available
+// here in order for the template aspect of it to work...
+template<class L> void ClusterSequenceActiveAreaExplicitGhosts::_initialise
+         (const std::vector<L> & pseudojets, 
+          const JetDefinition & jet_def_in,
+	  const GhostedAreaSpec * ghost_spec,
+	  const std::vector<L> * ghosts,
+	  double                 ghost_area,
+	  const bool & writeout_combinations) {
+  // don't reserve space yet -- will be done below
+
+  // insert initial jets this way so that any type L that can be
+  // converted to a pseudojet will work fine (basically PseudoJet
+  // and any type that has [] subscript access to the momentum
+  // components, such as CLHEP HepLorentzVector).
+  for (unsigned int i = 0; i < pseudojets.size(); i++) {
+    PseudoJet mom(pseudojets[i]);
+    //mom.set_user_index(0); // for user's particles (user index now lost...)
+    _jets.push_back(mom);
+    _is_pure_ghost.push_back(false);
+  }
+
+  _initial_hard_n = _jets.size();
+
+  if (ghost_spec != NULL) {
+    //std::cout << "about to reserve " << (_jets.size()+ghost_spec->n_ghosts())*2 << std::endl;
+    _jets.reserve((_jets.size()+ghost_spec->n_ghosts()));
+    _add_ghosts(*ghost_spec);
+  } else {
+    _jets.reserve(_jets.size()+ghosts->size());
+    _add_ghosts(*ghosts, ghost_area);
+  }
+
+  if (writeout_combinations) {
+    std::cout << "# Printing particles including ghosts\n";
+    for (unsigned j = 0; j < _jets.size(); j++) {
+      printf("%5u %20.13f %20.13f %20.13e\n",
+	       j,_jets[j].rap(),_jets[j].phi_02pi(),_jets[j].kt2());
+    }
+    std::cout << "# Finished printing particles including ghosts\n";
+  }
+
+  // this will ensure that we can still point to jets without
+  // difficulties arising!
+  //std::cout << _jets.size() << " " << _jets.size()*2 << " " << _jets.max_size() << std::endl;
+  _jets.reserve(_jets.size()*2); //GPS tmp removed
+
+  // run the clustering
+  _initialise_and_run(jet_def_in,writeout_combinations);
+
+  // set up all other information
+  _post_process();
+}
+
+
+inline unsigned int ClusterSequenceActiveAreaExplicitGhosts::n_hard_particles() const {return _initial_hard_n;}
+
+
+//----------------------------------------------------------------------
+/// add an explicitly specified bunch of ghosts
+template<class L> void ClusterSequenceActiveAreaExplicitGhosts::_add_ghosts (
+	  const std::vector<L> & ghosts,
+	  double                 ghost_area) {
+
+  
+  for (unsigned i = 0; i < ghosts.size(); i++) {
+    _is_pure_ghost.push_back(true);
+    _jets.push_back(ghosts[i]);
+  }
+  // and record some info about ghosts
+  _ghost_area = ghost_area;
+  _n_ghosts   = ghosts.size();
+}
+
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_CLUSTERSEQUENCEACTIVEAREAEXPLICITGHOSTS_HH_
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceArea.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceArea.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceArea.cc	(revision 5)
@@ -0,0 +1,28 @@
+#include "fastjet/ClusterSequenceArea.hh"
+
+FASTJET_BEGIN_NAMESPACE
+
+LimitedWarning ClusterSequenceArea::_range_warnings;
+LimitedWarning ClusterSequenceArea::_explicit_ghosts_repeats_warnings;
+
+/// print a warning if the range is unsuitable for the current
+/// calculation of the area (e.g. because ghosts do not extend
+/// far enough).
+void ClusterSequenceArea::_warn_if_range_unsuitable(const Selector & selector) const {
+  _check_selector_good_for_median(selector);
+
+  bool no_ghosts = (_area_def.area_type() == voronoi_area)
+    || (_area_def.area_type() == passive_area
+        && jet_def().jet_algorithm() == kt_algorithm);
+  if (! no_ghosts) {
+    double rapmin, rapmax;
+    selector.get_rapidity_extent(rapmin, rapmax);
+    if (rapmin < -_area_def.ghost_spec().ghost_maxrap()+0.95*jet_def().R() ||
+        rapmax >  _area_def.ghost_spec().ghost_maxrap()-0.95*jet_def().R()) {
+      _range_warnings.warn("rapidity range for median (rho) extends beyond +-(ghost_maxrap - 0.95*R); this is likely to cause the results to be unreliable; safest option is to increase ghost_maxrap in the area definition");
+    }
+  }
+}
+
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceArea.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceArea.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceArea.hh	(revision 5)
@@ -0,0 +1,260 @@
+//STARTHEADER
+// $Id: ClusterSequenceArea.hh 2690 2011-11-14 14:57:54Z soyez $
+//
+// Copyright (c) 2006-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLUSTERSEQUENCEAREA_HH__
+#define __FASTJET_CLUSTERSEQUENCEAREA_HH__
+
+#include "fastjet/ClusterSequenceAreaBase.hh"
+#include "fastjet/ClusterSequenceActiveArea.hh"
+#include "fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh"
+#include "fastjet/ClusterSequencePassiveArea.hh"
+#include "fastjet/ClusterSequenceVoronoiArea.hh"
+#include "fastjet/AreaDefinition.hh"
+
+FASTJET_BEGIN_NAMESPACE
+
+/// @ingroup area_classes
+/// \class ClusterSequenceArea
+/// General class for user to obtain ClusterSequence with additional
+/// area information.
+///
+/// Based on the area_def, it automatically dispatches the work to the
+/// appropriate actual ClusterSequenceAreaBase-derived-class to do the
+/// real work.
+class ClusterSequenceArea : public ClusterSequenceAreaBase {
+public:
+  /// main constructor
+  template<class L> ClusterSequenceArea
+         (const std::vector<L> & pseudojets, 
+	  const JetDefinition & jet_def_in,
+	  const AreaDefinition & area_def_in)  : _area_def(area_def_in) {
+    initialize_and_run_cswa(pseudojets, jet_def_in);
+  }
+
+  /// constructor with a GhostedAreaSpec
+  template<class L> ClusterSequenceArea
+         (const std::vector<L> & pseudojets, 
+	  const JetDefinition & jet_def_in,
+	  const GhostedAreaSpec & ghost_spec)   : _area_def(ghost_spec){
+    initialize_and_run_cswa(pseudojets, jet_def_in);
+  }
+
+  /// constructor with a VoronoiAreaSpec
+  template<class L> ClusterSequenceArea
+         (const std::vector<L> & pseudojets, 
+	  const JetDefinition & jet_def_in,
+	  const VoronoiAreaSpec & voronoi_spec)   : _area_def(voronoi_spec){
+    initialize_and_run_cswa(pseudojets, jet_def_in);
+  }
+
+  /// return a reference to the area definition
+  const AreaDefinition & area_def() const {return _area_def;}
+
+
+  /// return the area associated with the given jet
+  virtual double area       (const PseudoJet & jet) const {
+    return _area_base->area(jet);}
+
+  /// return the error (uncertainty) associated with the determination
+  /// of the area of this jet
+  virtual double area_error (const PseudoJet & jet) const {
+    return _area_base->area_error(jet);}
+
+  /// return the 4-vector area
+  virtual PseudoJet area_4vector(const PseudoJet & jet) const {
+    return _area_base->area_4vector(jet);}
+
+  // /// return the total area, up to |y|<maxrap, that is free of jets
+  // virtual double empty_area(double maxrap) const {
+  //   return _area_base->empty_area(maxrap);}
+  // 
+  // /// return something similar to the number of pure ghost jets
+  // /// in the given rapidity range in an active area case.
+  // /// For the local implementation we return empty_area/(0.55 pi R^2),
+  // /// based on measured properties of ghost jets with kt and cam. Note
+  // /// that the number returned is a double.
+  // virtual double n_empty_jets(double maxrap) const {
+  //   return _area_base->n_empty_jets(maxrap);
+
+  /// return the total area, corresponding to the given selector, that
+  /// is free of jets
+  ///
+  /// The selector needs to have a finite area and be applicable jet by
+  /// jet (see the BackgroundEstimator and Subtractor tools for more
+  /// advanced usage)
+  virtual double empty_area(const Selector & selector) const {
+    return _area_base->empty_area(selector);}
+
+  /// return something similar to the number of pure ghost jets
+  /// in the given rap-phi range in an active area case.
+  /// For the local implementation we return empty_area/(0.55 pi R^2),
+  /// based on measured properties of ghost jets with kt and cam. Note
+  /// that the number returned is a double.
+  ///
+  /// The selector needs to have a finite area and be applicable jet by
+  /// jet (see the BackgroundEstimator and Subtractor tools for more
+  /// advanced usage)
+  virtual double n_empty_jets(const Selector & selector) const {
+    return _area_base->n_empty_jets(selector);
+  }
+
+  /// true if a jet is made exclusively of ghosts
+  virtual bool is_pure_ghost(const PseudoJet & jet) const {
+    return _area_base->is_pure_ghost(jet);
+  }
+
+  /// true if this ClusterSequence has explicit ghosts
+  virtual bool has_explicit_ghosts() const {
+    return _area_base->has_explicit_ghosts();
+  }
+  
+
+  /// overload version of what's in the ClusterSequenceAreaBase class, which 
+  /// additionally checks compatibility between "selector" and region in which
+  /// ghosts are thrown.
+  ///
+  /// The selector needs to have a finite area and be applicable jet by
+  /// jet (see the BackgroundEstimator and Subtractor tools for more
+  /// advanced usage)
+  virtual void get_median_rho_and_sigma(const std::vector<PseudoJet> & all_jets,
+					const Selector & selector, 
+                                        bool use_area_4vector,
+                                        double & median, double & sigma,
+                                        double & mean_area,
+					bool all_are_incl = false) const {
+    _warn_if_range_unsuitable(selector);
+    ClusterSequenceAreaBase::get_median_rho_and_sigma(
+                                 all_jets, selector, use_area_4vector,
+				 median, sigma, mean_area, all_are_incl);
+  }
+
+  /// overload version of what's in the ClusterSequenceAreaBase class,
+  /// which actually just does the same thing as the base version (but
+  /// since we've overridden the 5-argument version above, we have to
+  /// override the 4-argument version too.
+  virtual void get_median_rho_and_sigma(const Selector & selector, 
+                                        bool use_area_4vector,
+                                        double & median, double & sigma) const {
+    ClusterSequenceAreaBase::get_median_rho_and_sigma(selector,use_area_4vector,
+                                                      median,sigma);
+  }
+
+  /// overload version of what's in the ClusterSequenceAreaBase class,
+  /// which actually just does the same thing as the base version (but
+  /// since we've overridden the multi-argument version above, we have to
+  /// override the 5-argument version too.
+  virtual void get_median_rho_and_sigma(const Selector & selector, 
+                                        bool use_area_4vector,
+                                        double & median, double & sigma,
+					double & mean_area) const {
+    ClusterSequenceAreaBase::get_median_rho_and_sigma(selector,use_area_4vector,
+                                                      median,sigma, mean_area);
+  }
+
+
+  /// overload version of what's in the ClusterSequenceAreaBase class, which 
+  /// additionally checks compatibility between "range" and region in which
+  /// ghosts are thrown.
+  virtual void parabolic_pt_per_unit_area(double & a, double & b, 
+                                          const Selector & selector, 
+                                          double exclude_above=-1.0, 
+                                          bool use_area_4vector=false) const {
+    _warn_if_range_unsuitable(selector);
+    ClusterSequenceAreaBase::parabolic_pt_per_unit_area(
+                                a,b,selector, exclude_above, use_area_4vector);
+  }
+
+
+private:
+  
+  /// print a warning if the range is unsuitable for the current
+  /// calculation of the area (e.g. because ghosts do not extend
+  /// far enough).
+  void _warn_if_range_unsuitable(const Selector & selector) const;
+
+  template<class L> void initialize_and_run_cswa (
+                                 const std::vector<L> & pseudojets, 
+                                 const JetDefinition & jet_def);
+
+  std::auto_ptr<ClusterSequenceAreaBase> _area_base;
+  AreaDefinition _area_def;
+  static LimitedWarning _range_warnings;
+  static LimitedWarning _explicit_ghosts_repeats_warnings;
+
+};
+
+//----------------------------------------------------------------------
+template<class L> void ClusterSequenceArea::initialize_and_run_cswa(
+           const std::vector<L> & pseudojets, 
+           const JetDefinition  & jet_def_in)
+ {
+  
+  ClusterSequenceAreaBase * _area_base_ptr;
+  switch(_area_def.area_type()) {
+  case active_area:
+    _area_base_ptr = new ClusterSequenceActiveArea(pseudojets, 
+                                                   jet_def_in, 
+                                                   _area_def.ghost_spec());
+    break;
+  case active_area_explicit_ghosts:
+    if (_area_def.ghost_spec().repeat() != 1) 
+      _explicit_ghosts_repeats_warnings.warn("Requested active area with explicit ghosts with repeat != 1; only 1 set of ghosts will be used");
+    _area_base_ptr = new ClusterSequenceActiveAreaExplicitGhosts(pseudojets, 
+                                                   jet_def_in, 
+                                                   _area_def.ghost_spec());
+    break;
+  case voronoi_area:
+    _area_base_ptr = new ClusterSequenceVoronoiArea(pseudojets, 
+                                                   jet_def_in, 
+                                                   _area_def.voronoi_spec());
+    break;
+  case one_ghost_passive_area:
+    _area_base_ptr = new ClusterSequence1GhostPassiveArea(pseudojets, 
+						    jet_def_in, 
+						    _area_def.ghost_spec());
+    break;
+  case passive_area:
+    _area_base_ptr = new ClusterSequencePassiveArea(pseudojets, 
+						    jet_def_in, 
+						    _area_def.ghost_spec());
+    break;
+  default:
+    std::cerr << "Error: unrecognized area_type in ClusterSequenceArea:" 
+              << _area_def.area_type() << std::endl;
+    exit(-1);
+  }
+  // now copy across the information from the area base class
+  _area_base = std::auto_ptr<ClusterSequenceAreaBase>(_area_base_ptr);
+  transfer_from_sequence(*_area_base);
+}
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_CLUSTERSEQUENCEAREA_HH__
+
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceAreaBase.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceAreaBase.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceAreaBase.cc	(revision 5)
@@ -0,0 +1,403 @@
+
+//STARTHEADER
+// $Id: ClusterSequenceAreaBase.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+
+
+#include "fastjet/ClusterSequenceAreaBase.hh"
+#include <algorithm>
+
+FASTJET_BEGIN_NAMESPACE
+
+using namespace std;
+
+
+/// allow for warnings
+LimitedWarning ClusterSequenceAreaBase::_warnings;
+LimitedWarning ClusterSequenceAreaBase::_warnings_zero_area;
+LimitedWarning ClusterSequenceAreaBase::_warnings_empty_area;
+
+//----------------------------------------------------------------------
+/// return the total area, within the selector's range, that is free
+/// of jets.
+/// 
+/// Calculate this as (range area) - \sum_{i in range} A_i
+///
+/// for ClusterSequences with explicit ghosts, assume that there will
+/// never be any empty area, i.e. it is always filled in by pure
+/// ghosts jets. This holds for seq.rec. algorithms
+double ClusterSequenceAreaBase::empty_area(const Selector & selector) const {
+
+  if (has_explicit_ghosts()) {return 0.0;}
+  else { return empty_area_from_jets(inclusive_jets(0.0), selector);}
+
+}
+
+//----------------------------------------------------------------------
+/// return the total area, within range, that is free of jets.
+/// 
+/// Calculate this as (range area) - \sum_{i in range} A_i
+///
+double ClusterSequenceAreaBase::empty_area_from_jets(
+                      const std::vector<PseudoJet> & all_jets,
+                      const Selector & selector) const {
+  _check_selector_good_for_median(selector);
+
+  double empty = selector.area();
+  for (unsigned i = 0; i < all_jets.size(); i++) {
+    if (selector.pass(all_jets[i])) empty -= area(all_jets[i]);
+  }
+  return empty;
+}
+
+double ClusterSequenceAreaBase::median_pt_per_unit_area(const Selector & selector) const {
+  return median_pt_per_unit_something(selector,false);
+}
+
+double ClusterSequenceAreaBase::median_pt_per_unit_area_4vector(const Selector & selector) const {
+  return median_pt_per_unit_something(selector,true);
+}
+
+
+//----------------------------------------------------------------------
+/// the median of (pt/area) for jets contained within range, counting
+/// the empty area as if it were made up of a collection of empty
+/// jets each of area (0.55 * pi R^2).
+double ClusterSequenceAreaBase::median_pt_per_unit_something(
+                const Selector & selector, bool use_area_4vector) const {
+
+  double median, sigma, mean_area;
+  get_median_rho_and_sigma(selector, use_area_4vector, median, sigma, mean_area);
+  return median;
+
+}
+
+
+//----------------------------------------------------------------------
+/// fits a form pt_per_unit_area(y) = a + b*y^2 for jets in range. 
+/// exclude_above allows one to exclude large values of pt/area from fit. 
+/// use_area_4vector = true uses the 4vector areas.
+void ClusterSequenceAreaBase::parabolic_pt_per_unit_area(
+       double & a, double & b, const Selector & selector, 
+       double exclude_above, bool use_area_4vector) const {
+  // sanity check on the selector: we require a finite area and that
+  // it applies jet by jet (see BackgroundEstimator for more advanced
+  // usage)
+  _check_selector_good_for_median(selector);
+
+  int n=0;
+  int n_excluded = 0;
+  double mean_f=0, mean_x2=0, mean_x4=0, mean_fx2=0; 
+
+  vector<PseudoJet> incl_jets = inclusive_jets();
+
+  for (unsigned i = 0; i < incl_jets.size(); i++) {
+    if (selector.pass(incl_jets[i])) {
+      double this_area;
+      if ( use_area_4vector ) {
+          this_area = area_4vector(incl_jets[i]).perp();     
+      } else {
+          this_area = area(incl_jets[i]);
+      }
+      double f = incl_jets[i].perp()/this_area;
+      if (exclude_above <= 0.0 || f < exclude_above) {
+	double x = incl_jets[i].rap(); double x2 = x*x;
+	mean_f   += f;
+	mean_x2  += x2;
+	mean_x4  += x2*x2;
+	mean_fx2 += f*x2;
+	n++;
+      } else {
+	n_excluded++;
+      }
+    }
+  }
+
+  if (n <= 1) {
+    // meaningful results require at least two jets inside the
+    // area -- mind you if there are empty jets we should be in 
+    // any case doing something special...
+    a = 0.0;
+    b = 0.0;
+  } else {
+    mean_f   /= n;
+    mean_x2  /= n;
+    mean_x4  /= n;
+    mean_fx2 /= n;
+    
+    b = (mean_f*mean_x2 - mean_fx2)/(mean_x2*mean_x2 - mean_x4);
+    a = mean_f - b*mean_x2;
+  }
+  //cerr << "n_excluded = "<< n_excluded << endl;
+}
+
+
+
+void ClusterSequenceAreaBase::get_median_rho_and_sigma(
+            const Selector & selector, bool use_area_4vector,
+            double & median, double & sigma, double & mean_area) const {
+
+  vector<PseudoJet> incl_jets = inclusive_jets();
+  get_median_rho_and_sigma(incl_jets, selector, use_area_4vector,
+			   median, sigma, mean_area, true);
+}
+
+
+void ClusterSequenceAreaBase::get_median_rho_and_sigma(
+            const vector<PseudoJet> & all_jets,
+            const Selector & selector, bool use_area_4vector,
+            double & median, double & sigma, double & mean_area,
+	    bool all_are_incl) const {
+
+  _check_jet_alg_good_for_median();
+
+  // sanity check on the selector: we require a finite area and that
+  // it applies jet by jet (see BackgroundEstimator for more advanced
+  // usage)
+  _check_selector_good_for_median(selector);
+
+  vector<double> pt_over_areas;
+  double total_area  = 0.0;
+  double total_njets = 0;
+
+  for (unsigned i = 0; i < all_jets.size(); i++) {
+    if (selector.pass(all_jets[i])) {
+      double this_area;
+      if (use_area_4vector) {
+          this_area = area_4vector(all_jets[i]).perp();
+      } else {
+          this_area = area(all_jets[i]);
+      }
+
+      if (this_area>0) {
+	pt_over_areas.push_back(all_jets[i].perp()/this_area);
+      } else {
+	_warnings_zero_area.warn("ClusterSequenceAreaBase::get_median_rho_and_sigma(...): discarded jet with zero area. Zero-area jets may be due to (i) too large a ghost area (ii) a jet being outside the ghost range (iii) the computation not being done using an appropriate algorithm (kt;C/A).");
+      }
+
+      total_area  += this_area;
+      total_njets += 1.0;
+    }
+  }
+
+  // there is nothing inside our region, so answer will always be zero
+  if (pt_over_areas.size() == 0) {
+    median = 0.0;
+    sigma  = 0.0;
+    mean_area = 0.0;
+    return;
+  }
+  
+  // get median (pt/area) [this is the "old" median definition. It considers
+  // only the "real" jets in calculating the median, i.e. excluding the
+  // only-ghost ones; it will be supplemented with more info below]
+  sort(pt_over_areas.begin(), pt_over_areas.end());
+
+  // now get the median & error, accounting for empty jets
+  // define the fractions of distribution at median, median-1sigma
+  double posn[2] = {0.5, (1.0-0.6827)/2.0};
+  double res[2];
+  
+  double n_empty, empty_a;
+  if (has_explicit_ghosts()) {
+    // NB: the following lines of code are potentially incorrect in cases
+    //     where there are unclustered particles (empty_area would do a better job,
+    //     at least for active areas). This is not an issue with kt or C/A, or other
+    //     algorithms that cluster all particles (and the median estimation should in 
+    //     any case only be done with kt or C/A!)
+    empty_a = 0.0;
+    n_empty = 0;
+  } else if (all_are_incl) {
+    // the default case
+    empty_a = empty_area(selector);
+    n_empty = n_empty_jets(selector);
+  } else {
+    // this one is intended to be used when e.g. one runs C/A, then looks at its
+    // exclusive jets in order to get an effective smaller R value, and passes those
+    // to this routine.
+    empty_a = empty_area_from_jets(all_jets, selector);
+    mean_area = total_area / total_njets; // temporary value
+    n_empty   = empty_a / mean_area;
+  }
+  //cout << "*** tot_area = " << total_area << ", empty_a = " << empty_a << endl;
+  //cout << "*** n_empty = " << n_empty << ", ntotal =  " << total_njets << endl;
+  total_njets += n_empty;
+  total_area  += empty_a;
+
+  // we need an int (rather than an unsigned int) with the size of the
+  // pt_over_areas array, because we'll often be doing subtraction of
+  // -1, negating it, etc. All of these operations go crazy with unsigned ints.
+  int pt_over_areas_size = pt_over_areas.size();
+  if (n_empty < -pt_over_areas_size/4.0)
+    _warnings_empty_area.warn("ClusterSequenceAreaBase::get_median_rho_and_sigma(...): the estimated empty area is suspiciously large and negative and may lead to an over-estimation of rho. This may be due to (i) a rare statistical fluctuation or (ii) too small a range used to estimate the background properties.");
+
+  for (int i = 0; i < 2; i++) {
+    double nj_median_pos = 
+      (pt_over_areas_size-1.0 + n_empty)*posn[i] - n_empty;
+    double nj_median_ratio;
+    if (nj_median_pos >= 0 && pt_over_areas_size > 1) {
+      int int_nj_median = int(nj_median_pos);
+ 
+     // avoid potential overflow issues
+      if (int_nj_median+1 > pt_over_areas_size-1){
+	int_nj_median = pt_over_areas_size-2;
+	nj_median_pos = pt_over_areas_size-1;
+      }
+
+      nj_median_ratio = 
+        pt_over_areas[int_nj_median] * (int_nj_median+1-nj_median_pos)
+        + pt_over_areas[int_nj_median+1] * (nj_median_pos - int_nj_median);
+    } else {
+      nj_median_ratio = 0.0;
+    }
+    res[i] = nj_median_ratio;
+  }
+  median = res[0];
+  double error  = res[0] - res[1];
+  mean_area = total_area / total_njets;
+  sigma  = error * sqrt(mean_area);
+}
+
+
+/// return a vector of all subtracted jets, using area_4vector, given rho.
+/// Only inclusive_jets above ptmin are subtracted and returned.
+/// the ordering is the same as that of sorted_by_pt(cs.inclusive_jets()),
+/// i.e. not necessarily ordered in pt once subtracted
+vector<PseudoJet> ClusterSequenceAreaBase::subtracted_jets(const double rho,
+                                                           const double ptmin) 
+                                                           const {
+  vector<PseudoJet> sub_jets;
+  vector<PseudoJet> jets_local = sorted_by_pt(inclusive_jets(ptmin));
+  for (unsigned i=0; i<jets_local.size(); i++) {
+     PseudoJet sub_jet = subtracted_jet(jets_local[i],rho);
+     sub_jets.push_back(sub_jet);
+  }
+  return sub_jets;
+}
+
+/// return a vector of subtracted jets, using area_4vector.
+/// Only inclusive_jets above ptmin are subtracted and returned.
+/// the ordering is the same as that of sorted_by_pt(cs.inclusive_jets()),
+/// i.e. not necessarily ordered in pt once subtracted
+vector<PseudoJet> ClusterSequenceAreaBase::subtracted_jets(
+                                                 const Selector & selector, 
+						 const double ptmin)
+						 const {
+  double rho = median_pt_per_unit_area_4vector(selector);
+  return subtracted_jets(rho,ptmin);
+}
+
+
+/// return a subtracted jet, using area_4vector, given rho
+PseudoJet ClusterSequenceAreaBase::subtracted_jet(const PseudoJet & jet,
+                                                  const double rho) const {
+  PseudoJet area4vect = area_4vector(jet);
+  PseudoJet sub_jet;
+  // sanity check
+  if (rho*area4vect.perp() < jet.perp() ) { 
+    sub_jet = jet - rho*area4vect;
+  } else { sub_jet = PseudoJet(0.0,0.0,0.0,0.0); }
+  
+  // make sure the subtracted jet has the same index (cluster, user, csw)
+  // (i.e. "looks like") the original jet
+  sub_jet.set_cluster_hist_index(jet.cluster_hist_index());
+  sub_jet.set_user_index(jet.user_index());
+  // do not use CS::_set_structure_shared_ptr here, which should
+  // only be called to maintain the tally during construction
+  sub_jet.set_structure_shared_ptr(jet.structure_shared_ptr());
+  return sub_jet;
+}
+
+
+/// return a subtracted jet, using area_4vector;  note that this is
+/// potentially inefficient if repeatedly used for many different
+/// jets, because rho will be recalculated each time around.
+PseudoJet ClusterSequenceAreaBase::subtracted_jet(const PseudoJet & jet,
+                                       const Selector & selector) const {
+  double rho = median_pt_per_unit_area_4vector(selector);
+  PseudoJet sub_jet = subtracted_jet(jet, rho);
+  return sub_jet;
+}
+
+
+/// return the subtracted pt, given rho
+double ClusterSequenceAreaBase::subtracted_pt(const PseudoJet & jet,
+                                              const double rho,
+                                              bool use_area_4vector) const {
+  if ( use_area_4vector ) { 
+     PseudoJet sub_jet = subtracted_jet(jet,rho);
+     return sub_jet.perp();
+  } else {
+     return jet.perp() - rho*area(jet);
+  }
+}  
+
+
+/// return the subtracted pt; note that this is
+/// potentially inefficient if repeatedly used for many different
+/// jets, because rho will be recalculated each time around.
+double ClusterSequenceAreaBase::subtracted_pt(const PseudoJet & jet,
+                                              const Selector & selector,
+                                              bool use_area_4vector) const {
+  if ( use_area_4vector ) { 
+     PseudoJet sub_jet = subtracted_jet(jet,selector);
+     return sub_jet.perp();
+  } else {
+     double rho = median_pt_per_unit_area(selector);
+     return subtracted_pt(jet,rho,false);
+  }
+}  
+
+// check the selector is suited for the computations i.e. applies jet
+// by jet and has a finite area
+void ClusterSequenceAreaBase::_check_selector_good_for_median(const Selector &selector) const{
+  // make sure the selector has a finite area
+  if ((! has_explicit_ghosts()) &&  (! selector.has_finite_area())){
+    throw Error("ClusterSequenceAreaBase: empty area can only be computed from selectors with a finite area");
+  }
+
+  // make sure the selector applies jet by jet
+  if (! selector.applies_jet_by_jet()){
+    throw Error("ClusterSequenceAreaBase: empty area can only be computed from selectors that apply jet by jet");
+  }
+}
+
+
+/// check the jet algorithm is suitable (and if not issue a warning)
+void ClusterSequenceAreaBase::_check_jet_alg_good_for_median() const {
+  if (jet_def().jet_algorithm() != kt_algorithm
+      && jet_def().jet_algorithm() != cambridge_algorithm
+      && jet_def().jet_algorithm() !=  cambridge_for_passive_algorithm) {
+    _warnings.warn("ClusterSequenceAreaBase: jet_def being used may not be suitable for estimating diffuse backgrounds (good options are kt, cam)");
+  }
+}
+
+
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceAreaBase.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceAreaBase.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceAreaBase.hh	(revision 5)
@@ -0,0 +1,312 @@
+//STARTHEADER
+// $Id: ClusterSequenceAreaBase.hh 2687 2011-11-14 11:17:51Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLUSTERSEQUENCEAREABASE_HH__
+#define __FASTJET_CLUSTERSEQUENCEAREABASE_HH__
+
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/LimitedWarning.hh"
+#include "fastjet/Selector.hh"
+
+FASTJET_BEGIN_NAMESPACE
+
+/// @ingroup area_classes
+/// \class ClusterSequenceAreaBase
+/// base class that sets interface for extensions of ClusterSequence
+/// that provide information about the area of each jet
+///
+/// the virtual functions here all return 0, since no area determination
+/// is implemented.
+class ClusterSequenceAreaBase : public ClusterSequence {
+public:
+  
+  /// a constructor which just carries out the construction of the
+  /// parent class
+  template<class L> ClusterSequenceAreaBase
+         (const std::vector<L> & pseudojets, 
+	  const JetDefinition & jet_def_in,
+	  const bool & writeout_combinations = false) :
+           ClusterSequence(pseudojets, jet_def_in, writeout_combinations) {}
+
+
+  /// default constructor
+  ClusterSequenceAreaBase() {}
+
+
+  /// destructor
+  virtual ~ClusterSequenceAreaBase() {}
+
+
+  /// return the area associated with the given jet; this base class
+  /// returns 0.
+  virtual double area       (const PseudoJet & ) const {return 0.0;}
+
+  /// return the error (uncertainty) associated with the determination
+  /// of the area of this jet; this base class returns 0.
+  virtual double area_error (const PseudoJet & ) const {return 0.0;}
+
+  /// return a PseudoJet whose 4-vector is defined by the following integral
+  ///
+  ///       \int drap d\phi PseudoJet("rap,phi,pt=one") *
+  ///                           * Theta("rap,phi inside jet boundary")
+  ///
+  /// where PseudoJet("rap,phi,pt=one") is a 4-vector with the given
+  /// rapidity (rap), azimuth (phi) and pt=1, while Theta("rap,phi
+  /// inside jet boundary") is a function that is 1 when rap,phi
+  /// define a direction inside the jet boundary and 0 otherwise.
+  ///
+  /// This base class returns a null 4-vector.
+  virtual PseudoJet area_4vector(const PseudoJet & ) const {
+    return PseudoJet(0.0,0.0,0.0,0.0);}
+
+  /// true if a jet is made exclusively of ghosts
+  ///
+  /// NB: most area classes do not give any explicit ghost jets, but
+  /// some do, and they should replace this function with their own
+  /// version.
+  virtual bool is_pure_ghost(const PseudoJet & ) const {
+    return false;
+  }
+
+  /// returns true if ghosts are explicitly included within 
+  /// jets for this ClusterSequence; 
+  ///
+  /// Derived classes that do include explicit ghosts should provide
+  /// an alternative version of this routine and set it properly.
+  virtual bool has_explicit_ghosts() const {
+    return false;
+  }
+
+  /// return the total area, corresponding to the given Selector, that
+  /// is free of jets, in general based on the inclusive jets.
+  /// 
+  /// The selector passed as an argument has to have a finite area and
+  /// apply jet-by-jet (see the BackgroundEstimator and Subtractor
+  /// tools for more generic usages)
+  virtual double empty_area(const Selector & selector) const;
+
+  /// return the total area, corresponding to the given Selector, that
+  /// is free of jets, based on the supplied all_jets
+  /// 
+  /// The selector passed as an argument has to have a finite area and
+  /// apply jet-by-jet (see the BackgroundEstimator and Subtractor
+  /// tools for more generic usages)
+  double empty_area_from_jets(const std::vector<PseudoJet> & all_jets,
+			      const Selector & selector) const;
+
+  /// return something similar to the number of pure ghost jets
+  /// in the given selector's range in an active area case.
+  /// For the local implementation we return empty_area/(0.55 pi R^2),
+  /// based on measured properties of ghost jets with kt and cam
+  /// (cf arXiv:0802.1188).
+  ///
+  /// Note that the number returned is a double.
+  /// 
+  /// The selector passed as an argument has to have a finite area and
+  /// apply jet-by-jet (see the BackgroundEstimator and Subtractor
+  /// tools for more generic usages)
+  virtual double n_empty_jets(const Selector & selector) const {
+    double R = jet_def().R();
+    return empty_area(selector)/(0.55*pi*R*R);
+  }
+
+  /// the median of (pt/area) for jets contained within the selector
+  /// range, making use also of the info on n_empty_jets
+  /// 
+  /// The selector passed as an argument has to have a finite area and
+  /// apply jet-by-jet (see the BackgroundEstimator and Subtractor
+  /// tools for more generic usages)
+  double median_pt_per_unit_area(const Selector & selector) const;
+
+  /// the median of (pt/area_4vector) for jets contained within the
+  /// selector range, making use also of the info on n_empty_jets
+  /// 
+  /// The selector passed as an argument has to have a finite area and
+  /// apply jet-by-jet
+  double median_pt_per_unit_area_4vector(const Selector & selector) const;
+  
+  /// the function that does the work for median_pt_per_unit_area and 
+  /// median_pt_per_unit_area_4vector: 
+  /// - something_is_area_4vect = false -> use plain area
+  /// - something_is_area_4vect = true  -> use 4-vector area
+  double median_pt_per_unit_something(
+                    const Selector & selector, bool use_area_4vector) const;
+
+  /// using jets withing the selector range (and with 4-vector areas if
+  /// use_area_4vector), calculate the median pt/area, as well as an
+  /// "error" (uncertainty), which is defined as the 1-sigma
+  /// half-width of the distribution of pt/A, obtained by looking for
+  /// the point below which we have (1-0.6827)/2 of the jets
+  /// (including empty jets).
+  ///
+  /// The subtraction for a jet with uncorrected pt pt^U and area A is
+  ///
+  ///   pt^S = pt^U - median*A +- sigma*sqrt(A)
+  ///
+  /// where the error is only that associated with the fluctuations
+  /// in the noise and not that associated with the noise having 
+  /// caused changes in the hard-particle content of the jet.
+  /// 
+  /// The selector passed as an argument has to have a finite area and
+  /// apply jet-by-jet (see the BackgroundEstimator and Subtractor
+  /// tools for more generic usages)
+  ///
+  /// NB: subtraction may also be done with 4-vector area of course,
+  /// and this is recommended for jets with larger values of R, as
+  /// long as rho has also been determined with a 4-vector area;
+  /// using a scalar area causes one to neglect terms of relative
+  /// order $R^2/8$ in the jet $p_t$.
+  virtual void get_median_rho_and_sigma(const Selector & selector, 
+                                        bool use_area_4vector,
+                                        double & median, double & sigma,
+                                        double & mean_area) const;
+
+  /// a more advanced version of get_median_rho_and_sigma, which allows
+  /// one to use any "view" of the event containing all jets (so that, 
+  /// e.g. one might use Cam on a different resolution scale without
+  /// have to rerun the algorithm).
+  ///
+  /// By default it will assume that "all" are not inclusive jets, 
+  /// so that in dealing with empty area it has to calculate
+  /// the number of empty jets based on the empty area and the
+  /// the observed <area> of jets rather than a surmised area
+  ///
+  /// Note that for small effective radii, this can cause problems
+  /// because the harder jets get an area >> <ghost-jet-area>
+  /// and so the estimate comes out all wrong. In these situations
+  /// it is highly advisable to use an area with explicit ghosts, since
+  /// then the "empty" jets are actually visible.
+  /// 
+  /// The selector passed as an argument has to have a finite area and
+  /// apply jet-by-jet (see the BackgroundEstimator and Subtractor
+  /// tools for more generic usages)
+  virtual void get_median_rho_and_sigma(const std::vector<PseudoJet> & all_jets,
+					const Selector & selector, 
+                                        bool use_area_4vector,
+                                        double & median, double & sigma,
+                                        double & mean_area,
+					bool all_are_inclusive = false) const;
+
+  /// same as the full version of get_median_rho_and_error, but without
+  /// access to the mean_area
+  /// 
+  /// The selector passed as an argument has to have a finite area and
+  /// apply jet-by-jet (see the BackgroundEstimator and Subtractor
+  /// tools for more generic usages)
+  virtual void get_median_rho_and_sigma(const Selector & selector, 
+                                bool use_area_4vector,
+                                double & median, double & sigma) const {
+    double mean_area;
+    get_median_rho_and_sigma(selector,  use_area_4vector,
+                             median,  sigma, mean_area);
+  }
+  
+
+  /// fits a form pt_per_unit_area(y) = a + b*y^2 in the selector range. 
+  /// exclude_above allows one to exclude large values of pt/area from fit. 
+  ///               (if negative, the cut is discarded)
+  /// use_area_4vector = true uses the 4vector areas.
+  /// 
+  /// The selector passed as an argument has to have a finite area and
+  /// apply jet-by-jet (see the BackgroundEstimator and Subtractor
+  /// tools for more generic usages)
+  virtual void parabolic_pt_per_unit_area(double & a, double & b, 
+                                          const Selector & selector, 
+                                          double exclude_above=-1.0, 
+                                          bool use_area_4vector=false) const;
+
+  /// return a vector of all subtracted jets, using area_4vector, given rho.
+  /// Only inclusive_jets above ptmin are subtracted and returned.
+  /// the ordering is the same as that of sorted_by_pt(cs.inclusive_jets()),
+  /// i.e. not necessarily ordered in pt once subtracted
+  std::vector<PseudoJet> subtracted_jets(const double rho,
+                                         const double ptmin=0.0) const;
+
+  /// return a vector of subtracted jets, using area_4vector.
+  /// Only inclusive_jets above ptmin are subtracted and returned.
+  /// the ordering is the same as that of sorted_by_pt(cs.inclusive_jets()),
+  /// i.e. not necessarily ordered in pt once subtracted
+  /// 
+  /// The selector passed as an argument has to have a finite area and
+  /// apply jet-by-jet (see the BackgroundEstimator and Subtractor
+  /// tools for more generic usages)
+  std::vector<PseudoJet> subtracted_jets(const Selector & selector, 
+                                         const double ptmin=0.0) const;
+
+  /// return a subtracted jet, using area_4vector, given rho
+  PseudoJet subtracted_jet(const PseudoJet & jet,
+                           const double rho) const;
+
+  /// return a subtracted jet, using area_4vector; note
+  /// that this is potentially inefficient if repeatedly used for many
+  /// different jets, because rho will be recalculated each time
+  /// around.
+  /// 
+  /// The selector passed as an argument has to have a finite area and
+  /// apply jet-by-jet (see the BackgroundEstimator and Subtractor
+  /// tools for more generic usages)
+  PseudoJet subtracted_jet(const PseudoJet & jet,
+                           const Selector & selector) const;
+
+  /// return the subtracted pt, given rho
+  double subtracted_pt(const PseudoJet & jet,
+                       const double rho,
+	               bool use_area_4vector=false) const;
+
+  /// return the subtracted pt; note that this is
+  /// potentially inefficient if repeatedly used for many different
+  /// jets, because rho will be recalculated each time around.
+  /// 
+  /// The selector passed as an argument has to have a finite area and
+  /// apply jet-by-jet (see the BackgroundEstimator and Subtractor
+  /// tools for more generic usages)
+  double subtracted_pt(const PseudoJet & jet,
+                       const Selector & selector,
+	               bool use_area_4vector=false) const;
+
+protected:
+  /// check the selector is suited for the computations i.e. applies jet by jet and has a finite area
+  void _check_selector_good_for_median(const Selector &selector) const;
+
+
+private:
+  /// handle warning messages
+  static LimitedWarning _warnings;
+  static LimitedWarning _warnings_zero_area;
+  static LimitedWarning _warnings_empty_area;
+
+  /// check the jet algorithm is suitable (and if not issue a warning)
+  void _check_jet_alg_good_for_median() const;
+  
+};
+
+
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_CLUSTERSEQUENCEAREABASE_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequencePassiveArea.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequencePassiveArea.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequencePassiveArea.cc	(revision 5)
@@ -0,0 +1,106 @@
+//STARTHEADER
+// $Id: ClusterSequencePassiveArea.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/ClusterSequencePassiveArea.hh"
+#include "fastjet/ClusterSequenceVoronoiArea.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+
+using namespace std;
+
+//----------------------------------------------------------------------
+/// global routine for initialising and running a passive area that is
+/// correct in general, but that chooses an optimal approach for
+/// various special cases.
+void ClusterSequencePassiveArea::_initialise_and_run_PA (
+		const JetDefinition & jet_def_in,
+		const GhostedAreaSpec & area_spec,
+		const bool & writeout_combinations) {
+
+  if (jet_def_in.jet_algorithm() == kt_algorithm) {
+    // first run the passive area
+    ClusterSequenceVoronoiArea csva(_jets,jet_def_in,VoronoiAreaSpec(1.0));
+    // now set up and transfer relevant information    
+    // first the clustering sequence
+    transfer_from_sequence(csva);
+    // then the areas
+    _resize_and_zero_AA();
+    for (unsigned i = 0; i < _history.size(); i++) {
+      int ijetp = _history[i].jetp_index;
+      if (ijetp != Invalid) {
+        _average_area[i] = csva.area(_jets[ijetp]);
+        _average_area_4vector[i] = csva.area_4vector(_jets[ijetp]);
+      }
+    }
+
+  } else if (jet_def_in.jet_algorithm() == cambridge_algorithm) {
+    // run a variant of the cambridge algorithm that has been hacked
+    // to deal with passive areas
+    JetDefinition tmp_jet_def = jet_def_in;
+    tmp_jet_def.set_jet_finder(cambridge_for_passive_algorithm);
+    tmp_jet_def.set_extra_param(sqrt(area_spec.mean_ghost_kt()));
+    _initialise_and_run_AA(tmp_jet_def, area_spec, writeout_combinations);
+    _jet_def = jet_def_in;
+
+  } else if (jet_def_in.jet_algorithm() == antikt_algorithm) {
+    // for the antikt algorithm, passive and active are identical
+    _initialise_and_run_AA(jet_def_in, area_spec, writeout_combinations);
+
+  } else if (jet_def_in.jet_algorithm() == plugin_algorithm &&
+             jet_def_in.plugin()->supports_ghosted_passive_areas()) {
+    // for some plugin algorithms, one can "prime" the algorithm with information
+    // about the ghost scale, and then an "AA" run will actually give a passive
+    // area
+    double ghost_sep_scale_store = jet_def_in.plugin()->ghost_separation_scale();
+    jet_def_in.plugin()->set_ghost_separation_scale(sqrt(area_spec.mean_ghost_kt()));
+    _initialise_and_run_AA(jet_def_in, area_spec, writeout_combinations);
+
+    // restore the original ghost_sep_scale
+    jet_def_in.plugin()->set_ghost_separation_scale(ghost_sep_scale_store);
+
+  } else {
+    // for a generic algorithm, just run the 1GhostPassiveArea
+    _initialise_and_run_1GPA(jet_def_in, area_spec, writeout_combinations);
+  }
+}
+
+//----------------------------------------------------------------------
+// dispatch to most relevant empty area calculation...
+double ClusterSequencePassiveArea::empty_area (const Selector & selector) const {
+  if (jet_def().jet_algorithm() == kt_algorithm) {
+    // run the naive algorithm
+    return ClusterSequenceAreaBase::empty_area(selector);
+  } else {
+    return ClusterSequence1GhostPassiveArea::empty_area(selector);
+  }
+}
+
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequencePassiveArea.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequencePassiveArea.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequencePassiveArea.hh	(revision 5)
@@ -0,0 +1,98 @@
+//STARTHEADER
+// $Id: ClusterSequencePassiveArea.hh 2687 2011-11-14 11:17:51Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLUSTERSEQUENCEPASSIVEAREA_HH__
+#define __FASTJET_CLUSTERSEQUENCEPASSIVEAREA_HH__
+
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/ClusterSequence1GhostPassiveArea.hh"
+#include<iostream>
+#include<vector>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//using namespace std;
+
+/// @ingroup sec_area_classes
+/// \class ClusterSequencePassiveArea
+/// Like ClusterSequence with computation of the passive jet area
+///
+/// Class that behaves essentially like ClusterSequence except
+/// that it also provides access to the area of a jet (which
+/// will be a random quantity... Figure out what to do about seeds 
+/// later...)
+///
+/// This class should not be used directly. Rather use
+/// ClusterSequenceArea with the appropriate AreaDefinition
+class ClusterSequencePassiveArea : public ClusterSequence1GhostPassiveArea {
+public:
+
+  /// constructor based on JetDefinition and PassiveAreaSpec
+  template<class L> ClusterSequencePassiveArea
+         (const std::vector<L> & pseudojets, 
+	  const JetDefinition & jet_def_in,
+	  const GhostedAreaSpec & area_spec,
+	  const bool & writeout_combinations = false) ;
+
+  /// return an empty area that's appropriate to the passive area
+  /// determination carried out
+  virtual double empty_area(const Selector & selector) const;
+
+private:
+
+  /// does the initialisation and running specific to the passive
+  /// areas class
+  void _initialise_and_run_PA (const JetDefinition & jet_def_in,
+                               const GhostedAreaSpec & area_spec,
+                               const bool & writeout_combinations = false);
+
+};
+
+
+
+
+template<class L> ClusterSequencePassiveArea::ClusterSequencePassiveArea 
+(const std::vector<L> & pseudojets, 
+ const JetDefinition & jet_def_in,
+ const GhostedAreaSpec & area_spec,
+ const bool & writeout_combinations) {
+
+  // transfer the initial jets (type L) into our own array
+  _transfer_input_jets(pseudojets);
+
+  // run the clustering for passive areas
+  _initialise_and_run_PA(jet_def_in, area_spec, writeout_combinations);
+
+}
+
+
+  
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_CLUSTERSEQUENCEPASSIVEAREA_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceStructure.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceStructure.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceStructure.cc	(revision 5)
@@ -0,0 +1,299 @@
+//STARTHEADER
+// $Id: ClusterSequenceStructure.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/ClusterSequenceStructure.hh"
+#include "fastjet/Error.hh"
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/ClusterSequenceAreaBase.hh"
+#include <iostream>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+
+ClusterSequenceStructure::~ClusterSequenceStructure(){
+  if (_associated_cs != NULL 
+      && _associated_cs->will_delete_self_when_unused()) {
+    // automatically handle deletion of the cluster sequence;
+    // execution should only ever reach this point if the user had
+    // called CS::delete_self_when_unused, which resets the count of
+    // the shared pointer to CSS (otherwise the CS's own destructor
+    // will have zeroed the _associated_cs pointer before the shared
+    // pointer count goes to zero [on destruction of the last of the
+    // jets in the CS and the destruction of the CS's copy of the
+    // shared pointer)
+    _associated_cs->signal_imminent_self_deletion();
+    delete _associated_cs;
+  }
+}
+
+
+//----------------------------------------------------------------------
+// Direct access to the associated ClusterSequence object.
+//----------------------------------------------------------------------
+
+// check whether this PseudoJet has an associated parent
+// ClusterSequence
+bool ClusterSequenceStructure::has_valid_cluster_sequence() const{
+  return (_associated_cs != NULL);
+}
+
+// get a (const) pointer to the associated ClusterSequence (NULL if
+// inexistent)
+const ClusterSequence* ClusterSequenceStructure::associated_cluster_sequence() const{
+  return _associated_cs;
+}
+
+
+// If there is a valid cluster sequence associated with this jet,
+// returns a pointer to it; otherwise throws an Error.
+//
+// Open question: should these errors be upgraded to classes of their
+// own so that they can be caught? [Maybe, but later]
+const ClusterSequence * ClusterSequenceStructure::validated_cs() const {
+  if (!_associated_cs) 
+    throw Error("you requested information about the internal structure of a jet, but its associated ClusterSequence has gone out of scope.");
+  return _associated_cs;
+}
+
+
+//----------------------------------------------------------------------
+// Methods for access to information about jet structure
+//----------------------------------------------------------------------
+
+// check if it has been recombined with another PseudoJet in which
+// case, return its partner through the argument. Otherwise,
+// 'partner' is set to 0.
+//
+// false is also returned if this PseudoJet has no associated
+// ClusterSequence
+bool ClusterSequenceStructure::has_partner(const PseudoJet &reference, PseudoJet &partner) const{
+  return validated_cs()->has_partner(reference, partner);
+}
+
+// check if it has been recombined with another PseudoJet in which
+// case, return its child through the argument. Otherwise, 'child'
+// is set to 0.
+// 
+// false is also returned if this PseudoJet has no associated
+// ClusterSequence, with the child set to 0
+bool ClusterSequenceStructure::has_child(const PseudoJet &reference, PseudoJet &child) const{
+  return validated_cs()->has_child(reference, child);
+}
+
+// check if it is the product of a recombination, in which case
+// return the 2 parents through the 'parent1' and 'parent2'
+// arguments. Otherwise, set these to 0.
+//
+// false is also returned if this PseudoJet has no parent
+// ClusterSequence
+bool ClusterSequenceStructure::has_parents(const PseudoJet &reference, PseudoJet &parent1, PseudoJet &parent2) const{
+  return validated_cs()->has_parents(reference, parent1, parent2);
+}
+
+
+// check if the reference PseudoJet is inside the "jet" passed as an argument
+//
+// an error is thrown if there is no CS associated with one of the 2 jets.
+// fasle is returned if teh 2 jets do not belong to the same CS
+bool ClusterSequenceStructure::object_in_jet(const PseudoJet &reference, const PseudoJet &jet) const{
+  if ((!has_associated_cluster_sequence()) || (!jet.has_associated_cluster_sequence()))
+    throw Error("you requested information about the internal structure of a jet, but it is not associated with a ClusterSequence or its associated ClusterSequence has gone out of scope."); 
+
+  if (reference.associated_cluster_sequence() != jet.associated_cluster_sequence()) return false;
+
+  return validated_cs()->object_in_jet(reference, jet);
+}
+
+
+// return true if the structure supports constituents. 
+//
+// an Error is thrown if this PseudoJet has no currently valid
+// associated ClusterSequence
+bool ClusterSequenceStructure::has_constituents() const{
+  if (!has_associated_cluster_sequence())
+    throw Error("you requested information about the internal structure of a jet, but it is not associated with a ClusterSequence or its associated ClusterSequence has gone out of scope."); 
+
+  return true;
+}
+
+
+// retrieve the constituents. An empty vector is returned if there is
+// no associated ClusterSequence
+vector<PseudoJet> ClusterSequenceStructure::constituents(const PseudoJet &reference) const{
+  return validated_cs()->constituents(reference);
+}
+
+// return true if the structure supports exclusive_subjets. 
+//
+// an Error is thrown if this PseudoJet has no currently valid
+// associated ClusterSequence
+bool ClusterSequenceStructure::has_exclusive_subjets() const{
+  if (!has_associated_cluster_sequence())
+    throw Error("you requested information about the internal structure of a jet, but it is not associated with a ClusterSequence or its associated ClusterSequence has gone out of scope."); 
+
+  return true;
+}
+
+// return a vector of all subjets of the current jet (in the sense
+// of the exclusive algorithm) that would be obtained when running
+// the algorithm with the given dcut. 
+//
+// Time taken is O(m ln m), where m is the number of subjets that
+// are found. If m gets to be of order of the total number of
+// constituents in the jet, this could be substantially slower than
+// just getting that list of constituents.
+//
+// an Error is thrown if this PseudoJet has no currently valid
+// associated ClusterSequence
+std::vector<PseudoJet> ClusterSequenceStructure::exclusive_subjets (const PseudoJet &reference, const double & dcut) const {
+  return validated_cs()->exclusive_subjets(reference, dcut);
+}
+
+// return the size of exclusive_subjets(...); still n ln n with same
+// coefficient, but marginally more efficient than manually taking
+// exclusive_subjets.size()
+//
+// an Error is thrown if this PseudoJet has no currently valid
+// associated ClusterSequence
+int ClusterSequenceStructure::n_exclusive_subjets(const PseudoJet &reference, const double & dcut) const {
+  return validated_cs()->n_exclusive_subjets(reference, dcut);
+}
+
+// return the list of subjets obtained by unclustering the supplied
+// jet down to n subjets (or all constituents if there are fewer
+// than n).
+//
+// requires n ln n time
+//
+// an Error is thrown if this PseudoJet has no currently valid
+// associated ClusterSequence
+std::vector<PseudoJet> ClusterSequenceStructure::exclusive_subjets_up_to (const PseudoJet &reference, int nsub) const {
+  return validated_cs()->exclusive_subjets_up_to(reference, nsub);
+}
+
+// return the dij that was present in the merging nsub+1 -> nsub 
+// subjets inside this jet.
+//
+// an Error is thrown if this PseudoJet has no currently valid
+// associated ClusterSequence
+double ClusterSequenceStructure::exclusive_subdmerge(const PseudoJet &reference, int nsub) const {
+  return validated_cs()->exclusive_subdmerge(reference, nsub);
+}
+
+// return the maximum dij that occurred in the whole event at the
+// stage that the nsub+1 -> nsub merge of subjets occurred inside 
+// this jet.
+//
+// an Error is thrown if this PseudoJet has no currently valid
+// associated ClusterSequence
+double ClusterSequenceStructure::exclusive_subdmerge_max(const PseudoJet &reference, int nsub) const {
+  return validated_cs()->exclusive_subdmerge_max(reference, nsub);
+}
+
+
+//----------------------------------------------------------------------
+// information related to the pieces of the jet
+//----------------------------------------------------------------------
+
+// by convention, a jet associated with a ClusterSequence will have
+// pieces if it has parents in the cluster sequence.
+//
+// an error is thrown if the ClusterSequence is out of scope (since
+// the answer depends on information in the Cluster Sequence)
+bool ClusterSequenceStructure::has_pieces(const PseudoJet &reference) const{
+  PseudoJet dummy1, dummy2;
+  return has_parents(reference, dummy1, dummy2);
+}
+
+// by convention, the pieces of a jet associated with a
+// ClusterSequence are its parents in the Cluster Sequence. If it has
+// no parents, an empty jet is returned.
+//
+// an error is thrown if the ClusterSequence is out of scope
+vector<PseudoJet> ClusterSequenceStructure::pieces(const PseudoJet &reference) const{
+  PseudoJet j1, j2;
+  vector<PseudoJet> res;
+  if (has_parents(reference, j1, j2)){
+    res.push_back(j1);
+    res.push_back(j2);
+  }
+
+  return res;
+}
+
+
+//----------------------------------------------------------------------
+// the following ones require a computation of the area in the
+// associated ClusterSequence (See ClusterSequenceAreaBase for details)
+//----------------------------------------------------------------------
+
+// if possible, return a valid ClusterSequenceAreaBase pointer; otherwise
+// throw an error
+const ClusterSequenceAreaBase * ClusterSequenceStructure::validated_csab() const {
+  const ClusterSequenceAreaBase *csab = dynamic_cast<const ClusterSequenceAreaBase*>(validated_cs());
+  if (csab == NULL) throw Error("you requested jet-area related information, but the PseudoJet does not have associated area information.");
+  return csab;
+}
+
+
+// check if it has a defined area
+bool ClusterSequenceStructure::has_area() const{
+  if (! has_associated_cluster_sequence()) return false;
+  return (dynamic_cast<const ClusterSequenceAreaBase*>(_associated_cs) != NULL);
+}
+
+// return the jet (scalar) area.
+// throw an Error if there is no support for area in the associated CS
+double ClusterSequenceStructure::area(const PseudoJet &reference) const{
+  return validated_csab()->area(reference);
+}
+
+// return the error (uncertainty) associated with the determination
+// of the area of this jet.
+// throws an Error if there is no support for area in the associated CS
+double ClusterSequenceStructure::area_error(const PseudoJet &reference) const{
+  return validated_csab()->area_error(reference);
+}
+
+// return the jet 4-vector area
+// throws an Error if there is no support for area in the associated CS
+PseudoJet ClusterSequenceStructure::area_4vector(const PseudoJet &reference) const{
+  return validated_csab()->area_4vector(reference);
+}
+
+// true if this jet is made exclusively of ghosts
+// throws an Error if there is no support for area in the associated CS
+bool ClusterSequenceStructure::is_pure_ghost(const PseudoJet &reference) const{
+  return validated_csab()->is_pure_ghost(reference);
+}
+
+
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceStructure.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceStructure.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceStructure.hh	(revision 5)
@@ -0,0 +1,268 @@
+//STARTHEADER
+// $Id: ClusterSequenceStructure.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_CLUSTER_SEQUENCE_STRUCTURE_HH__
+#define __FASTJET_CLUSTER_SEQUENCE_STRUCTURE_HH__
+
+#include "fastjet/internal/base.hh"
+#include "fastjet/SharedPtr.hh"
+#include "fastjet/PseudoJetStructureBase.hh"
+
+#include <vector>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+/// @ingroup extra_info
+/// \class ClusterSequenceStructure
+///
+/// Contains any information related to the clustering that should be
+/// directly accessible to PseudoJet.
+///
+/// By default, this class implements basic access to the
+/// ClusterSequence related to a PseudoJet (like its constituents or
+/// its area). But it can be overloaded in order e.g. to give access
+/// to the jet substructure.
+///
+// Design question: Do we only put the methods that can be overloaded
+// or do we put everything a PJ can have access to? I think both cost
+// the same number of indirections. The first option limits the amount
+// of coding and maybe has a clearer structure. The second is more
+// consistent (everything related to the same thing is at the same
+// place) and gives better access for derived classes. We'll go for
+// the second option.
+class ClusterSequenceStructure : public PseudoJetStructureBase{
+public:
+  /// default ctor
+  ClusterSequenceStructure() : _associated_cs(NULL){}
+
+  /// ctor with initialisation to a given ClusterSequence
+  /// 
+  /// In principle, this is reserved for initialisation by the parent
+  /// ClusterSequence
+  ClusterSequenceStructure(const ClusterSequence *cs){
+    set_associated_cs(cs);
+  };
+
+  /// default (virtual) dtor
+  virtual ~ClusterSequenceStructure();
+
+  /// description
+  virtual std::string description() const{ return "PseudoJet with an associated ClusterSequence"; }
+
+  //-------------------------------------------------------------
+  /// @name Direct access to the associated ClusterSequence object.
+  ///
+  /// Get access to the associated ClusterSequence (if any)
+  //\{
+  //-------------------------------------------------------------
+  /// returns true if there is an associated ClusterSequence
+  virtual bool has_associated_cluster_sequence() const{ return true;}
+
+  /// get a (const) pointer to the parent ClusterSequence (NULL if
+  /// inexistent)
+  virtual const ClusterSequence* associated_cluster_sequence() const;
+  
+  /// returns true if there is a valid associated ClusterSequence
+  virtual bool has_valid_cluster_sequence() const;
+
+  /// if the jet has a valid associated cluster sequence then return a
+  /// pointer to it; otherwise throw an error
+  virtual const ClusterSequence * validated_cs() const;
+
+  /// if the jet has valid area information then return a pointer to
+  /// the associated ClusterSequenceAreaBase object; otherwise throw an error
+  virtual const ClusterSequenceAreaBase * validated_csab() const;
+
+  /// set the associated csw
+  virtual void set_associated_cs(const ClusterSequence * new_cs){
+    _associated_cs = new_cs;
+  }
+  //\}
+
+  //-------------------------------------------------------------
+  /// @name Methods for access to information about jet structure
+  ///
+  /// These allow access to jet constituents, and other jet
+  /// subtructure information. They only work if the jet is associated
+  /// with a ClusterSequence.
+  //-------------------------------------------------------------
+  //\{
+
+  /// check if it has been recombined with another PseudoJet in which
+  /// case, return its partner through the argument. Otherwise,
+  /// 'partner' is set to 0.
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  virtual bool has_partner(const PseudoJet &reference, PseudoJet &partner) const;
+
+  /// check if it has been recombined with another PseudoJet in which
+  /// case, return its child through the argument. Otherwise, 'child'
+  /// is set to 0.
+  /// 
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  virtual bool has_child(const PseudoJet &reference, PseudoJet &child) const;
+
+  /// check if it is the product of a recombination, in which case
+  /// return the 2 parents through the 'parent1' and 'parent2'
+  /// arguments. Otherwise, set these to 0.
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  virtual bool has_parents(const PseudoJet &reference, PseudoJet &parent1, PseudoJet &parent2) const;
+
+  /// check if the reference PseudoJet is contained in the second one
+  /// passed as argument.
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  ///
+  /// false is returned if the 2 PseudoJet do not belong the same
+  /// ClusterSequence
+  virtual bool object_in_jet(const PseudoJet &reference, const PseudoJet &jet) const;
+
+  /// return true if the structure supports constituents. 
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  virtual bool has_constituents() const;
+
+  /// retrieve the constituents. 
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  virtual std::vector<PseudoJet> constituents(const PseudoJet &reference) const;
+
+
+  /// return true if the structure supports exclusive_subjets. 
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  virtual bool has_exclusive_subjets() const;
+
+  /// return a vector of all subjets of the current jet (in the sense
+  /// of the exclusive algorithm) that would be obtained when running
+  /// the algorithm with the given dcut. 
+  ///
+  /// Time taken is O(m ln m), where m is the number of subjets that
+  /// are found. If m gets to be of order of the total number of
+  /// constituents in the jet, this could be substantially slower than
+  /// just getting that list of constituents.
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  virtual std::vector<PseudoJet> exclusive_subjets(const PseudoJet &reference, const double & dcut) const;
+
+  /// return the size of exclusive_subjets(...); still n ln n with same
+  /// coefficient, but marginally more efficient than manually taking
+  /// exclusive_subjets.size()
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  virtual int n_exclusive_subjets(const PseudoJet &reference, const double & dcut) const;
+
+  /// return the list of subjets obtained by unclustering the supplied
+  /// jet down to nsub subjets (or all constituents if there are fewer
+  /// than nsub).
+  ///
+  /// requires nsub ln nsub time
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  virtual std::vector<PseudoJet> exclusive_subjets_up_to (const PseudoJet &reference, int nsub) const;
+
+  /// return the dij that was present in the merging nsub+1 -> nsub 
+  /// subjets inside this jet.
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  virtual double exclusive_subdmerge(const PseudoJet &reference, int nsub) const;
+
+  /// return the maximum dij that occurred in the whole event at the
+  /// stage that the nsub+1 -> nsub merge of subjets occurred inside 
+  /// this jet.
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  virtual double exclusive_subdmerge_max(const PseudoJet &reference, int nsub) const;
+
+
+  //-------------------------------------------------------------------
+  // information related to the pieces of the jet
+  //-------------------------------------------------------------------
+  /// by convention, a jet associated with a ClusterSequence will have
+  /// its parents as pieces
+  virtual bool has_pieces(const PseudoJet &reference) const;
+
+  /// by convention, a jet associated with a ClusterSequence will have
+  /// its parents as pieces
+  ///
+  /// if it has no parents, then there will only be a single piece:
+  /// itself
+  ///
+  /// Note that to answer that question, we need to access the cluster
+  /// sequence. If the cluster sequence has gone out of scope, an
+  /// error will be thrown
+  virtual std::vector<PseudoJet> pieces(const PseudoJet &reference) const;
+
+
+  // the following ones require a computation of the area in the
+  // parent ClusterSequence (See ClusterSequenceAreaBase for details)
+  //------------------------------------------------------------------
+
+  /// check if it has a defined area
+  virtual bool has_area() const;
+
+  /// return the jet (scalar) area.
+  /// throws an Error if there is no support for area in the parent CS
+  virtual double area(const PseudoJet &reference) const;
+
+  /// return the error (uncertainty) associated with the determination
+  /// of the area of this jet.
+  /// throws an Error if there is no support for area in the parent CS
+  virtual double area_error(const PseudoJet &reference) const;
+
+  /// return the jet 4-vector area.
+  /// throws an Error if there is no support for area in the parent CS
+  virtual PseudoJet area_4vector(const PseudoJet &reference) const;
+
+  /// true if this jet is made exclusively of ghosts.
+  /// throws an Error if there is no support for area in the parent CS
+  virtual bool is_pure_ghost(const PseudoJet &reference) const;
+
+  //\} --- end of jet structure -------------------------------------
+
+protected:
+  const ClusterSequence *_associated_cs;
+};
+
+FASTJET_END_NAMESPACE
+
+#endif  //  __FASTJET_CLUSTER_SEQUENCE_STRUCTURE_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceVoronoiArea.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceVoronoiArea.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceVoronoiArea.cc	(revision 5)
@@ -0,0 +1,315 @@
+//STARTHEADER
+// $Id: ClusterSequenceVoronoiArea.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2006-2007 Matteo Cacciari, Gavin Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of a simple command-line handling environment
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/ClusterSequenceVoronoiArea.hh"
+#include "fastjet/internal/Voronoi.hh"
+#include <list>
+#include <cassert>
+#include <ostream>
+#include <fstream>
+#include <iterator>
+#include <cmath>
+#include <limits>
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+typedef ClusterSequenceVoronoiArea::VoronoiAreaCalc VAC;
+
+/// class for carrying out a voronoi area calculation on a set of
+/// initial vectors
+class ClusterSequenceVoronoiArea::VoronoiAreaCalc {
+public:
+  /// constructor that takes a range of a vector together with the
+  /// effective radius for the intersection of discs with voronoi
+  /// cells
+  VoronoiAreaCalc(const vector<PseudoJet>::const_iterator &,
+		  const vector<PseudoJet>::const_iterator &,
+		  double effective_R);
+
+  /// return the area of the particle associated with the given
+  /// index
+  inline double area (int index) const {return _areas[index];};
+
+private:
+  std::vector<double> _areas;     ///< areas, numbered as jets
+  double _effective_R;            ///< effective radius
+  double _effective_R_squared;    ///< effective radius squared
+
+  /**
+   * compute the intersection of one triangle with the circle
+   * the area is returned
+   */
+  double edge_circle_intersection(const VPoint &p0,
+				  const GraphEdge &edge);
+
+  /// get the area of a circle of radius R centred on the point 0 with
+  /// 1 and 2 on each "side" of the arc. dij is the distance between
+  /// point i and point j and all distances are squared
+  inline double circle_area(const double d12_2, double d01_2, double d02_2){
+    return 0.5*_effective_R_squared
+      *acos(min(1.0,(d01_2+d02_2-d12_2)/(2*sqrt(d01_2*d02_2))));
+  }
+};
+
+
+/**
+ * compute the intersection of one triangle with the circle
+ * the area is returned
+ */
+double VAC::edge_circle_intersection(const VPoint &p0,
+				     const GraphEdge &edge){
+  VPoint p1(edge.x1-p0.x, edge.y1-p0.y);
+  VPoint p2(edge.x2-p0.x, edge.y2-p0.y);
+  VPoint pdiff = p2-p1;
+
+  //fprintf(stdout, "\tpt(%f,%f)\n", p0.x, p0.y);
+
+  double cross = vector_product(p1, p2);
+  double d12_2 = norm(pdiff);
+  double d01_2 = norm(p1);
+  double d02_2 = norm(p2);
+
+  // compute intersections between edge line and circle
+  double delta = d12_2*_effective_R_squared - cross*cross;
+  
+  // if no intersection, area=area_circle
+  if (delta<=0){
+    return circle_area(d12_2, d01_2, d02_2);
+  }
+
+  // we'll only need delta's sqrt now
+  delta = sqrt(delta);
+
+  // b is the projection of 01 onto 12
+  double b = scalar_product(pdiff, p1);
+
+  // intersections with the circle:
+  //   we compute the "coordinate along the line" of the intersection
+  //   with t=0 (1) corresponding to p1 (p2)
+  // points with 0<t<1 are within the circle others are outside
+
+  // positive intersection
+  double tp = (delta-b)/d12_2;
+
+  // if tp is negative, tm also => inters = circle
+  if (tp<0)
+    return circle_area(d12_2, d01_2, d02_2);
+
+  // we need the second intersection
+  double tm = -(delta+b)/d12_2;
+
+  // if tp<1, it lies in the circle
+  if (tp<1){
+    // if tm<0, the segment has one intersection
+    // with the circle at p (t=tp)
+    // the area is a triangle from 1 to p
+    //        then a circle   from p to 2
+    // several tricks can be used:
+    //  - the area of the triangle is tp*area triangle
+    //  - the lenght for the circle are easily obtained
+    if (tm<0)
+      return tp*0.5*fabs(cross)
+        +circle_area((1-tp)*(1-tp)*d12_2, _effective_R_squared, d02_2);
+
+    // now, 0 < tm < tp < 1
+    // the segment intersects twice the circle
+    //   area = 2 cirles at ends + a triangle in the middle
+    // again, simplifications are staightforward
+    return (tp-tm)*0.5*fabs(cross)
+      + circle_area(tm*tm*d12_2, d01_2, _effective_R_squared)
+      + circle_area((1-tp)*(1-tp)*d12_2, _effective_R_squared, d02_2);
+  }
+
+  // now, we have tp>1
+
+  // if in addition tm>1, intersectino is a circle
+  if (tm>1)
+    return circle_area(d12_2, d01_2, d02_2);
+
+  // if tm<0, the triangle is inside the circle
+  if (tm<0)
+    return 0.5*fabs(cross);
+
+  // otherwise, only the "tm point" is on the segment
+  //   area = circle from 1 to m and triangle from m to 2
+
+  return (1-tm)*0.5*fabs(cross)
+    +circle_area(tm*tm*d12_2, d01_2, _effective_R_squared);
+}
+
+
+// the constructor...
+//----------------------------------------------------------------------
+VAC::VoronoiAreaCalc(const vector<PseudoJet>::const_iterator &jet_begin,
+		     const vector<PseudoJet>::const_iterator &jet_end,
+		     double effective_R) {
+
+  assert(effective_R < 0.5*pi);
+
+  vector<VPoint> voronoi_particles;
+  vector<int> voronoi_indices;
+
+  _effective_R         = effective_R;
+  _effective_R_squared = effective_R*effective_R;
+
+  double minrap = numeric_limits<double>::max();
+  double maxrap = -minrap;
+
+  unsigned int n_tot = 0, n_added = 0;
+
+  // loop over jets and create the triangulation, as well as cross-referencing
+  // info
+  for (vector<PseudoJet>::const_iterator jet_it = jet_begin; 
+       jet_it != jet_end; jet_it++) {
+    _areas.push_back(0.0);
+    if ((jet_it->perp2()) != 0.0 || (jet_it->E() != jet_it->pz())){
+      // generate the corresponding point
+      double rap = jet_it->rap(), phi = jet_it->phi();
+      voronoi_particles.push_back(VPoint(rap, phi));
+      voronoi_indices.push_back(n_tot);
+      n_added++;
+
+      // insert a copy of the point if it falls within 2*_R_effective
+      // of the 0,2pi borders (because we are interested in any
+      // voronoi edge within _R_effective of the other border)
+      if (phi < 2*_effective_R) {
+	voronoi_particles.push_back(VPoint(rap,phi+twopi));
+	voronoi_indices.push_back(-1);
+	n_added++;
+      } else if (twopi-phi < 2*_effective_R) {
+	voronoi_particles.push_back(VPoint(rap,phi-twopi));
+	voronoi_indices.push_back(-1);
+	n_added++;
+      }
+
+      // track the rapidity range
+      maxrap = max(maxrap,rap);
+      minrap = min(minrap,rap);
+    }
+    n_tot++;
+  }
+
+  // allow for 0-particle case in graceful way
+  if (n_added == 0) return;
+  // assert(n_added > 0); // old (pre 2.4) non-graceful exit
+
+  // add extreme cases (corner particles):
+  double max_extend = 2*max(maxrap-minrap+4*_effective_R, twopi+8*_effective_R);
+  voronoi_particles.push_back(VPoint(0.5*(minrap+maxrap)-max_extend, pi));
+  voronoi_particles.push_back(VPoint(0.5*(minrap+maxrap)+max_extend, pi));
+  voronoi_particles.push_back(VPoint(0.5*(minrap+maxrap), pi-max_extend));
+  voronoi_particles.push_back(VPoint(0.5*(minrap+maxrap), pi+max_extend));
+
+  // Build the VD
+  VoronoiDiagramGenerator vdg;
+  vdg.generateVoronoi(&voronoi_particles, 
+		      0.5*(minrap+maxrap)-max_extend, 0.5*(minrap+maxrap)+max_extend,
+		      pi-max_extend, pi+max_extend);
+
+  vdg.resetIterator();
+  GraphEdge *e=NULL;
+  unsigned int v_index;
+  int p_index;
+  vector<PseudoJet>::const_iterator jet;
+
+  while(vdg.getNext(&e)){
+    v_index = e->point1;
+    if (v_index<n_added){ // this removes the corner particles
+      p_index = voronoi_indices[v_index];
+      if (p_index!=-1){   // this removes the copies
+	jet = jet_begin+voronoi_indices[v_index];
+	_areas[p_index]+=
+	  edge_circle_intersection(voronoi_particles[v_index], *e);
+      }
+    }
+    v_index = e->point2;
+    if (v_index<n_added){ // this removes the corner particles
+      p_index = voronoi_indices[v_index];
+      if (p_index!=-1){   // this removes the copies
+	jet = jet_begin+voronoi_indices[v_index];
+	_areas[p_index]+=
+	  edge_circle_intersection(voronoi_particles[v_index], *e);
+      }
+    }
+  }
+
+
+}
+
+
+//----------------------------------------------------------------------
+///
+void ClusterSequenceVoronoiArea::_initializeVA () {
+  // run the VAC on our original particles
+  _pa_calc = new VAC(_jets.begin(), 
+		     _jets.begin()+n_particles(),
+		     _effective_Rfact*_jet_def.R());
+
+  // transfer the areas to our local structure
+  //  -- first the initial ones
+  _voronoi_area.reserve(2*n_particles());
+  for (unsigned int i=0; i<n_particles(); i++) {
+    _voronoi_area.push_back(_pa_calc->area(i));
+    // make a stab at a 4-vector area
+    if (_jets[i].perp2() > 0) {
+      _voronoi_area_4vector.push_back((_pa_calc->area(i)/_jets[i].perp())
+                                      * _jets[i]);
+    } else {
+      // not sure what to do here -- just put zero (it won't be meaningful
+      // anyway)
+      _voronoi_area_4vector.push_back(PseudoJet(0.0,0.0,0.0,0.0));
+    }
+  }
+	   
+  //  -- then the combined areas that arise from the clustering
+  for (unsigned int i = n_particles(); i < _history.size(); i++) {
+    double area_local;
+    PseudoJet area_4vect;
+    if (_history[i].parent2 >= 0) {
+      area_local = _voronoi_area[_history[i].parent1] + 
+  	           _voronoi_area[_history[i].parent2];
+      area_4vect = _voronoi_area_4vector[_history[i].parent1] + 
+                   _voronoi_area_4vector[_history[i].parent2];
+    } else {
+      area_local = _voronoi_area[_history[i].parent1];
+      area_4vect = _voronoi_area_4vector[_history[i].parent1];
+    }
+    _voronoi_area.push_back(area_local);
+    _voronoi_area_4vector.push_back(area_4vect);
+  }
+
+}
+
+//----------------------------------------------------------------------
+ClusterSequenceVoronoiArea::~ClusterSequenceVoronoiArea() {
+  delete _pa_calc;
+}
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceVoronoiArea.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceVoronoiArea.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceVoronoiArea.hh	(revision 5)
@@ -0,0 +1,119 @@
+//STARTHEADER
+// $Id: ClusterSequenceVoronoiArea.hh 2687 2011-11-14 11:17:51Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLUSTERSEQUENCEVORONOIAREA_HH__
+#define __FASTJET_CLUSTERSEQUENCEVORONOIAREA_HH__
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/AreaDefinition.hh"
+#include "fastjet/ClusterSequenceAreaBase.hh"
+#include <memory>
+#include <vector>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+/// @ingroup sec_area_classes
+/// \class ClusterSequenceVoronoiArea
+/// Like ClusterSequence with computation of the Voronoi jet area
+///
+/// Handle the computation of Voronoi jet area.
+///
+/// This class should not be used directly. Rather use
+/// ClusterSequenceArea with the appropriate AreaDefinition
+class ClusterSequenceVoronoiArea : public ClusterSequenceAreaBase {
+public:
+  /// template ctor
+  /// \param pseudojet              list of jets (template type)
+  /// \param jet_def                jet definition
+  /// \param effective_Rfact        effective radius
+  /// \param writeout_combinations  ??????
+  template<class L> ClusterSequenceVoronoiArea
+         (const std::vector<L> & pseudojets, 
+	  const JetDefinition & jet_def,
+	  const VoronoiAreaSpec & spec = VoronoiAreaSpec(),
+	  const bool & writeout_combinations = false);
+  
+  /// default dtor
+  ~ClusterSequenceVoronoiArea();
+
+  /// return the area associated with the given jet
+  virtual inline double area(const PseudoJet & jet) const {
+    return _voronoi_area[jet.cluster_hist_index()];}
+
+  /// return a 4-vector area associated with the given jet -- stricly
+  /// this is not the exact 4-vector area, but rather an approximation
+  /// made of sums of centres of all Voronoi cells in jet, each
+  /// contributing with a normalisation equal to the area of the cell
+  virtual inline PseudoJet area_4vector(const PseudoJet & jet) const {
+    return _voronoi_area_4vector[jet.cluster_hist_index()];}
+
+  /// return the error of the area associated with the given jet
+  /// (0 by definition for a voronoi area)
+  virtual inline double area_error(const PseudoJet & /*jet*/) const {
+    return 0.0;}
+
+  /// passive area calculator -- to be defined in the .cc file (it will do
+  /// the true hard work)
+  class VoronoiAreaCalc; 
+  
+
+private:  
+  /// initialisation of the Voronoi Area
+  void _initializeVA();
+
+  std::vector<double> _voronoi_area;  ///< vector containing the result
+  std::vector<PseudoJet> _voronoi_area_4vector; ///< vector containing approx 4-vect areas
+  VoronoiAreaCalc *_pa_calc;          ///< area calculator
+  double _effective_Rfact;            ///< effective radius
+};
+
+
+
+
+/// template constructor need to be specified in the header!
+//----------------------------------------------------------------------
+template<class L> ClusterSequenceVoronoiArea::ClusterSequenceVoronoiArea
+(const std::vector<L> &pseudojets, 
+ const JetDefinition &jet_def_in,
+ const VoronoiAreaSpec & spec,
+ const bool & writeout_combinations) :
+  _effective_Rfact(spec.effective_Rfact()) {
+
+  // transfer the initial jets (type L) into our own array
+  _transfer_input_jets(pseudojets);
+
+  // run the clustering
+  _initialise_and_run(jet_def_in,writeout_combinations);
+
+  // the jet clustering's already been done, now worry about areas...
+  _initializeVA();
+}
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_CLUSTERSEQUENCEVORONOIAREA_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceWithArea.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceWithArea.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequenceWithArea.hh	(revision 5)
@@ -0,0 +1,55 @@
+//STARTHEADER
+// $Id: ClusterSequenceWithArea.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2006-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLUSTERSEQUENCEWITHAREA_HH__
+#define __FASTJET_CLUSTERSEQUENCEWITHAREA_HH__
+
+// for backwards compatibility fastjet/ClusterSequenceWithArea.hh
+// provides the ClusterSequenceWithArea class that is equivalent to
+// ClusterSequenceArea. The latter should now be used together with
+// the fastjet/ClusterSequenceArea.hh. ClusterSequenceWithArea is not
+// guaranteed to work in future release of FastJet
+#warning You have included fastjet/ClusterSequenceWithArea.hh, \
+a deprecated FastJet header provided only for backward compatibility. \
+This is not guaranteed to work in future releases of FastJet. \
+Please consider including fastjet/ClusterSequenceArea.hh directly. \
+Similarily, if you use the (deprecated) class ClusterSequenceWithArea, \
+please switch to the equivalent ClusterSequenceArea instead.
+
+#include "fastjet/ClusterSequenceAreaBase.hh"
+
+FASTJET_BEGIN_NAMESPACE
+
+//----- backwards compatibility with version 2.1 ---------------
+typedef ClusterSequenceAreaBase ClusterSequenceWithArea;
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_CLUSTERSEQUENCEWITHAREA_HH__
+
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence_CP2DChan.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence_CP2DChan.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence_CP2DChan.cc	(revision 5)
@@ -0,0 +1,354 @@
+//STARTHEADER
+// $Id: ClusterSequence_CP2DChan.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/internal/ClosestPair2D.hh"
+#include<limits>
+#include<vector>
+#include<cmath>
+#include<iostream>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+
+// place for things we don't want outside world to run into
+namespace Private {
+  /// class for helping us deal with mirror-image particles.
+  class MirrorInfo{
+  public:
+    int orig, mirror;
+    MirrorInfo(int a, int b) : orig(a), mirror(b) {};
+    MirrorInfo() {};
+  };
+
+  /// if there is a need for a mirror when looking for closest pairs
+  /// up to distance D, then return true and turn the supplied point
+  /// into its mirror copy
+  bool make_mirror(Coord2D & point, double Dlim) {
+    if (point.y < Dlim)       {point.y += twopi; return true;}
+    if (twopi-point.y < Dlim) {point.y -= twopi; return true;}
+    return false;
+  }
+  
+}
+
+using namespace Private;
+
+
+//----------------------------------------------------------------------
+/// clusters only up to a distance Dlim -- does not deal with "inclusive" jets
+/// -- these are left to some other part of the program
+void ClusterSequence::_CP2DChan_limited_cluster (double Dlim) {
+  
+  unsigned int n = _initial_n;
+
+  vector<MirrorInfo>   coordIDs(2*n); // coord IDs of a given jetID
+  vector<int>          jetIDs(2*n);   // jet ID for a given coord ID
+  vector<Coord2D>      coords(2*n);   // our coordinates (and copies)
+
+  // particles within a distance Dlim of the phi edges (phi<Dlim ||
+  // phi>2pi-Dli;) will be mirrored. For Dlim>pi, this could lead to
+  // particles copies outside the fixed range in phi which is
+  // [-pi:3pi] (see make_mirror above). Since in that case all
+  // particles get copied anywaym we can just copy particles up to a
+  // distance "pi" from the edges
+  double Dlim4mirror = min(Dlim,pi);
+
+  // start things off...
+  double minrap = numeric_limits<double>::max();
+  double maxrap = -minrap;
+  int coord_index = -1;
+  int n_active = 0;
+  for (unsigned jet_i = 0; jet_i < _jets.size(); jet_i++) {
+
+    // skip jets that already have children or that have infinite
+    // rapidity
+    if (_history[_jets[jet_i].cluster_hist_index()].child != Invalid ||
+	(_jets[jet_i].E() == abs(_jets[jet_i].pz()) && 
+	 _jets[jet_i].perp2() == 0.0)
+	) {continue;}
+
+    n_active++;
+
+    coordIDs[jet_i].orig = ++coord_index;
+    coords[coord_index]  = Coord2D(_jets[jet_i].rap(), _jets[jet_i].phi_02pi());
+    jetIDs[coord_index]  = jet_i;
+    minrap = min(coords[coord_index].x,minrap);
+    maxrap = max(coords[coord_index].x,maxrap);
+
+    Coord2D mirror_point(coords[coord_index]);
+    if (make_mirror(mirror_point, Dlim4mirror)) {
+      coordIDs[jet_i].mirror = ++coord_index;
+      coords[coord_index] = mirror_point;
+      jetIDs[coord_index] = jet_i;
+    } else {
+      coordIDs[jet_i].mirror = Invalid;
+    }
+  }
+
+  // set them to their actual size...
+  coords.resize(coord_index+1);
+
+  // establish limits (with some leeway on rapidity)
+  Coord2D left_edge(minrap-1.0, -3.15); // a security margin below  -pi
+  Coord2D right_edge(maxrap+1.0, 9.45); // a security margin above 3*pi
+
+  //cerr << "minrap, maxrap = " << minrap << " " << maxrap << endl;
+
+  // now create the closest pair search object
+  ClosestPair2D cp(coords, left_edge, right_edge);
+
+  // cross check to see what's going on...
+  //cerr << "Tree depths before: ";
+  //cp.print_tree_depths(cerr);
+
+  // and start iterating...
+  vector<Coord2D> new_points(2);
+  vector<unsigned int> cIDs_to_remove(4);
+  vector<unsigned int> new_cIDs(2);
+
+  do {
+    // find out which pair we recombine
+    unsigned int cID1, cID2;
+    double distance2;
+    cp.closest_pair(cID1,cID2,distance2);
+
+    // if the closest distance > Dlim, we exit and go to "inclusive" stage
+    if (distance2 > Dlim*Dlim) {break;}
+
+    // normalise distance as we like it
+    distance2 *= _invR2;
+
+    // do the recombination...
+    int jet_i = jetIDs[cID1];
+    int jet_j = jetIDs[cID2];
+    assert (jet_i != jet_j); // to catch issue of recombining with mirror point
+    int newjet_k;
+    _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
+
+    // don't bother with any further action if only one active particle
+    // is left (also avoid closest-pair error [cannot remove last particle]).
+    if (--n_active == 1) {break;}
+
+    // now prepare operations on CP structure
+    cIDs_to_remove.resize(0);
+    cIDs_to_remove.push_back(coordIDs[jet_i].orig);
+    cIDs_to_remove.push_back(coordIDs[jet_j].orig);
+    if (coordIDs[jet_i].mirror != Invalid) 
+      cIDs_to_remove.push_back(coordIDs[jet_i].mirror);
+    if (coordIDs[jet_j].mirror != Invalid) 
+      cIDs_to_remove.push_back(coordIDs[jet_j].mirror);
+
+    Coord2D new_point(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
+    new_points.resize(0);
+    new_points.push_back(new_point);
+    if (make_mirror(new_point, Dlim4mirror)) new_points.push_back(new_point);  //< same warning as before concerning the mirroring
+    
+    // carry out actions on search tree
+    cp.replace_many(cIDs_to_remove, new_points, new_cIDs);
+
+    // now fill in info for new points...
+    coordIDs[newjet_k].orig = new_cIDs[0];
+    jetIDs[new_cIDs[0]]       = newjet_k;
+    if (new_cIDs.size() == 2) {
+      coordIDs[newjet_k].mirror = new_cIDs[1];
+      jetIDs[new_cIDs[1]]         = newjet_k;
+    } else {coordIDs[newjet_k].mirror = Invalid;}
+    
+    //// if we've reached one "active" jet we should exit...
+    //n_active--;
+    //if (n_active == 1) {break;}
+
+  } while(true);
+  
+  // cross check to see what's going on...
+  //cerr << "Max tree depths after: ";
+  //cp.print_tree_depths(cerr);
+
+}
+
+
+//----------------------------------------------------------------------
+/// a variant of the closest pair clustering which uses a region of
+/// size 2pi+2R in phi.
+void ClusterSequence::_CP2DChan_cluster_2pi2R () {
+
+  if (_jet_algorithm != cambridge_algorithm) throw Error("CP2DChan clustering method called for a jet-finder that is not the cambridge algorithm");
+
+  // run the clustering with mirror copies kept such that only things
+  // within _Rparam of a border are mirrored
+  _CP2DChan_limited_cluster(_Rparam);
+
+  //
+  _do_Cambridge_inclusive_jets();
+}
+
+
+//----------------------------------------------------------------------
+/// a variant of the closest pair clustering which uses a region of
+/// size 2pi + 2*0.3 and then carries on with 2pi+2*R
+void ClusterSequence::_CP2DChan_cluster_2piMultD () {
+
+  // do a first run of clustering up to a small distance parameter,
+  if (_Rparam >= 0.39) {
+    _CP2DChan_limited_cluster(min(_Rparam/2,0.3));
+  }
+
+  // and then the final round of clustering
+  _CP2DChan_cluster_2pi2R ();
+}
+
+
+//----------------------------------------------------------------------
+/// a 4pi variant of the closest pair clustering
+void ClusterSequence::_CP2DChan_cluster () {
+
+  if (_jet_algorithm != cambridge_algorithm) throw Error("_CP2DChan_cluster called for a jet-finder that is not the cambridge algorithm");
+
+  unsigned int n = _jets.size();
+
+  vector<MirrorInfo>   coordIDs(2*n);  // link from original to mirror indices
+  vector<int>          jetIDs(2*n);     // link from mirror to original indices
+  vector<Coord2D>      coords(2*n);   // our coordinates (and copies)
+
+  // start things off...
+  double minrap = numeric_limits<double>::max();
+  double maxrap = -minrap;
+  int coord_index = 0;
+  for (unsigned i = 0; i < n; i++) {
+    // separate out points with infinite rapidity
+    if (_jets[i].E() == abs(_jets[i].pz()) && _jets[i].perp2() == 0.0) {
+      coordIDs[i] = MirrorInfo(BeamJet,BeamJet);
+    } else {
+      coordIDs[i].orig   = coord_index;
+      coordIDs[i].mirror = coord_index+1;
+      coords[coord_index]   = Coord2D(_jets[i].rap(), _jets[i].phi_02pi());
+      coords[coord_index+1] = Coord2D(_jets[i].rap(), _jets[i].phi_02pi()+twopi);
+      jetIDs[coord_index]   = i;
+      jetIDs[coord_index+1] = i;
+      minrap = min(coords[coord_index].x,minrap);
+      maxrap = max(coords[coord_index].x,maxrap);
+      coord_index += 2;
+    }
+  }
+  // label remaining "mirror info" as saying that there are no jets
+  for (unsigned i = n; i < 2*n; i++) {coordIDs[i].orig = Invalid;}
+
+  // set them to their actual size...
+  coords.resize(coord_index);
+
+  // establish limits (with some leeway on rapidity)
+  Coord2D left_edge(minrap-1.0, 0.0);
+  Coord2D right_edge(maxrap+1.0, 2*twopi);
+
+  // now create the closest pair search object
+  ClosestPair2D cp(coords, left_edge, right_edge);
+
+  // and start iterating...
+  vector<Coord2D> new_points(2);
+  vector<unsigned int> cIDs_to_remove(4);
+  vector<unsigned int> new_cIDs(2);
+  do {
+    // find out which pair we recombine
+    unsigned int cID1, cID2;
+    double distance2;
+    cp.closest_pair(cID1,cID2,distance2);
+    distance2 *= _invR2;
+
+    // if the closest distance > 1, we exit and go to "inclusive" stage
+    if (distance2 > 1.0) {break;}
+
+    // do the recombination...
+    int jet_i = jetIDs[cID1];
+    int jet_j = jetIDs[cID2];
+    assert (jet_i != jet_j); // to catch issue of recombining with mirror point
+    int newjet_k;
+    _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
+
+    // now prepare operations on CP structure
+    cIDs_to_remove[0] = coordIDs[jet_i].orig;
+    cIDs_to_remove[1] = coordIDs[jet_i].mirror;
+    cIDs_to_remove[2] = coordIDs[jet_j].orig;
+    cIDs_to_remove[3] = coordIDs[jet_j].mirror;
+    new_points[0] = Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
+    new_points[1] = Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi()+twopi);
+    // carry out the CP operation
+    //cp.replace_many(cIDs_to_remove, new_points, new_cIDs);
+    // remarkable the following is faster...
+    new_cIDs[0] = cp.replace(cIDs_to_remove[0], cIDs_to_remove[2], new_points[0]);
+    new_cIDs[1] = cp.replace(cIDs_to_remove[1], cIDs_to_remove[3], new_points[1]);
+    // signal that the following jets no longer exist
+    coordIDs[jet_i].orig = Invalid;
+    coordIDs[jet_j].orig = Invalid;
+    // and do bookkeeping for new jet
+    coordIDs[newjet_k] = MirrorInfo(new_cIDs[0], new_cIDs[1]);
+    jetIDs[new_cIDs[0]] = newjet_k;
+    jetIDs[new_cIDs[1]] = newjet_k;
+
+    // if we've reached one jet we should exit...
+    n--;
+    if (n == 1) {break;}
+
+  } while(true);
+  
+
+  // now do "beam" recombinations 
+  //for (unsigned int jet_i = 0; jet_i < coordIDs.size(); jet_i++) {
+  //  // if we have a predeclared beam jet or a valid set of mirror
+  //  // coordinates, recombine then recombine this jet with the beam
+  //  if (coordIDs[jet_i].orig == BeamJet || coordIDs[jet_i].orig > 0) {
+  //    // diB = 1 _always_ (for the cambridge alg.)
+  //    _do_iB_recombination_step(jet_i, 1.0);
+  //  }
+  //}
+
+  _do_Cambridge_inclusive_jets();
+
+  //n = _history.size();
+  //for (unsigned int hist_i = 0; hist_i < n; hist_i++) {
+  //  if (_history[hist_i].child == Invalid) {
+  //    _do_iB_recombination_step(_history[hist_i].jetp_index, 1.0);
+  //  }
+  //}
+
+}
+
+
+//----------------------------------------------------------------------
+void ClusterSequence::_do_Cambridge_inclusive_jets () {
+  unsigned int n = _history.size();
+  for (unsigned int hist_i = 0; hist_i < n; hist_i++) {
+    if (_history[hist_i].child == Invalid) {
+      _do_iB_recombination_step(_history[hist_i].jetp_index, 1.0);
+    }
+  }
+}
+
+FASTJET_END_NAMESPACE
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence_Delaunay.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence_Delaunay.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence_Delaunay.cc	(revision 5)
@@ -0,0 +1,253 @@
+//STARTHEADER
+// $Id: ClusterSequence_Delaunay.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#include "fastjet/Error.hh"
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/ClusterSequence.hh"
+#include<iostream>
+#include<sstream>
+#include<cmath>
+#include <cstdlib>
+#include<cassert>
+#include<memory>
+//
+#ifndef DROP_CGAL // in case we do not have the code for CGAL
+#include "fastjet/internal/Dnn4piCylinder.hh"
+#include "fastjet/internal/Dnn3piCylinder.hh"
+#include "fastjet/internal/Dnn2piCylinder.hh"
+#endif //  DROP_CGAL 
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+
+
+//----------------------------------------------------------------------
+/// Run the clustering using a Hierarchical Delaunay triangulation and
+/// STL maps to achieve O(N*ln N) behaviour.
+///
+/// There may be internally asserted assumptions about absence of
+/// points with coincident eta-phi coordinates.
+void ClusterSequence::_delaunay_cluster () {
+
+  int n = _jets.size();
+
+  vector<EtaPhi> points(n); // recall EtaPhi is just a typedef'd pair<double>
+  for (int i = 0; i < n; i++) {
+    points[i] = EtaPhi(_jets[i].rap(),_jets[i].phi_02pi());
+    points[i].sanitize(); // make sure things are in the right range
+  }
+
+  // initialise our DNN structure with the set of points
+  auto_ptr<DynamicNearestNeighbours> DNN;
+#ifndef DROP_CGAL // strategy = NlnN* are not supported if we drop CGAL...
+  bool verbose = false;
+  bool ignore_nearest_is_mirror = (_Rparam < twopi);
+  if (_strategy == NlnN4pi) {
+    DNN.reset(new Dnn4piCylinder(points,verbose));
+  } else if (_strategy == NlnN3pi) {
+    DNN.reset(new Dnn3piCylinder(points,ignore_nearest_is_mirror,verbose));
+  } else if (_strategy == NlnN) {
+    DNN.reset(new Dnn2piCylinder(points,ignore_nearest_is_mirror,verbose));
+  } else 
+#else
+  if (_strategy == NlnN4pi || _strategy == NlnN3pi || _strategy == NlnN) {
+    ostringstream err;
+    err << "ERROR: Requested strategy "<<strategy_string()<<" but it is not"<<endl;
+    err << "       supported because FastJet was compiled without CGAL"<<endl;
+    throw Error(err.str());
+    //assert(false);
+  }
+#endif // DROP_CGAL
+  {
+    ostringstream err;
+    err << "ERROR: Unrecognized value for strategy: "<<_strategy<<endl;
+    assert(false);
+    throw Error(err.str());
+  }
+
+  // We will find nearest neighbour for each vertex, and include
+  // distance in map (NB DistMap is a typedef given in the .h file)
+  DistMap DijMap;
+
+  // fill the map with the minimal (as far as we know) subset of Dij
+  // distances (i.e. nearest neighbour ones).
+  for (int ii = 0; ii < n; ii++) {
+    _add_ktdistance_to_map(ii, DijMap, DNN.get());
+  }
+
+  // run the clustering (go up to i=n-1, but then will stop half-way down,
+  // when we reach that point -- it will be the final beam jet and there
+  // will be no nearest neighbours to find).
+  for (int i=0;i<n;i++) {
+    // find nearest vertices
+    // NB: skip cases where the point is not there anymore!
+    TwoVertices SmallestDijPair;
+    int jet_i, jet_j;
+    double SmallestDij;
+    bool Valid2;
+    bool recombine_with_beam;
+    do { 
+      SmallestDij = DijMap.begin()->first;
+      SmallestDijPair = DijMap.begin()->second;
+      jet_i = SmallestDijPair.first;
+      jet_j = SmallestDijPair.second;
+      // distance is immediately removed regardless of whether or not
+      // it is used.
+      // Some temporary testing code relating to problems with the gcc-3.2 compiler
+      //cout << "got here and size is "<< DijMap.size()<< " and it is "<<SmallestDij <<"\n";
+      //cout <<  jet_i << " "<< jet_j<<"\n";
+      DijMap.erase(DijMap.begin());
+      //cout << "got beyond here\n";
+
+      // need to "prime" the validity of jet_j in such a way that 
+      // if it corresponds to the beam then it is automatically valid.
+      recombine_with_beam = (jet_j == BeamJet);
+      if (!recombine_with_beam) {Valid2 = DNN->Valid(jet_j);} 
+      else {Valid2 = true;}
+
+    } while ( !DNN->Valid(jet_i) || !Valid2);
+
+
+    // The following part acts just on jet momenta and on the history.
+    // The action on the nearest-neighbour structures takes place
+    // later (only if at least 2 jets are around).
+    if (! recombine_with_beam) {
+      int nn; // will be index of new jet
+      _do_ij_recombination_step(jet_i, jet_j, SmallestDij, nn);
+      //OBS // merge the two jets, add new jet, remove old ones
+      //OBS _jets.push_back(_jets[jet_i] + _jets[jet_j]);
+      //OBS 
+      //OBS int nn = _jets.size()-1;
+      //OBS _jets[nn].set_cluster_hist_index(n+i);
+      //OBS 
+      //OBS // get corresponding indices in history structure
+      //OBS int hist_i = _jets[jet_i].cluster_hist_index();
+      //OBS int hist_j = _jets[jet_j].cluster_hist_index();
+      //OBS 
+      //OBS 
+      //OBS _add_step_to_history(n+i,min(hist_i,hist_j), max(hist_i,hist_j),
+      //OBS 		      _jets.size()-1, SmallestDij);
+
+      // add new point to points vector
+      EtaPhi newpoint(_jets[nn].rap(), _jets[nn].phi_02pi());
+      newpoint.sanitize(); // make sure it is in correct range
+      points.push_back(newpoint);
+    } else {
+      // recombine the jet with the beam
+      _do_iB_recombination_step(jet_i, SmallestDij);
+      //OBS _add_step_to_history(n+i,_jets[jet_i].cluster_hist_index(),BeamJet,
+      //OBS 			   Invalid, SmallestDij);
+    }
+
+    // exit the loop because we do not want to look for nearest neighbours
+    // etc. of zero partons
+    if (i == n-1) {break;}
+
+    vector<int> updated_neighbours;
+    if (! recombine_with_beam) {
+      // update DNN
+      int point3;
+      DNN->RemoveCombinedAddCombination(jet_i, jet_j, 
+				       points[points.size()-1], point3,
+				       updated_neighbours);
+      // C++ beginners' comment: static_cast to unsigned int is necessary
+      // to do away with warnings about type mismatch between point3 (int) 
+      // and points.size (unsigned int)
+      if (static_cast<unsigned int> (point3) != points.size()-1) {
+	throw Error("INTERNAL ERROR: point3 != points.size()-1");}
+    } else {
+      // update DNN
+      DNN->RemovePoint(jet_i, updated_neighbours);
+    }
+
+    // update map
+    vector<int>::iterator it = updated_neighbours.begin();
+    for (; it != updated_neighbours.end(); ++it) {
+      int ii = *it;
+      _add_ktdistance_to_map(ii, DijMap, DNN.get());
+    }
+      
+  } // end clustering loop 
+  
+}
+
+
+//----------------------------------------------------------------------
+/// Add the current kt distance for particle ii to the map (DijMap)
+/// using information from the DNN object. Work as follows:
+/// 
+/// . if the kt is zero then it's nearest neighbour is taken to be the
+///   the beam jet and the distance is zero.
+///
+/// . if cylinder distance to nearest neighbour > _Rparam then it is
+///   yiB that is smallest and this is added to map.
+///
+/// . otherwise if the nearest neighbour jj has a larger kt then add
+///   dij to the map.
+///
+/// . otherwise do nothing
+///
+void ClusterSequence::_add_ktdistance_to_map(
+                          const int & ii, 
+			  DistMap & DijMap,
+			  const DynamicNearestNeighbours * DNN) {
+  
+  double yiB = jet_scale_for_algorithm(_jets[ii]);
+  if (yiB == 0.0) {
+    // in this case convention is that we do not worry about distances
+    // but directly state that nearest neighbour is beam
+    DijMap.insert(DijEntry(yiB,  TwoVertices(ii,-1)));
+  } else {
+    double DeltaR2 = DNN->NearestNeighbourDistance(ii) * _invR2;
+    // Logic of following bit is: only add point to map if it has
+    // smaller kt2 than nearest neighbour j (if it has larger kt,
+    // then: either it is j's nearest neighbour and then we will
+    // include dij when we come to j; or it is not j's nearest
+    // neighbour and j will recombine with someone else).
+    
+    // If DeltaR2 > 1.0 then in any case it will recombine with beam rather
+    // than with any neighbours.
+    // (put general normalisation here at some point)
+    if (DeltaR2 > 1.0) {
+      DijMap.insert(DijEntry(yiB,  TwoVertices(ii,-1)));
+    } else {
+      double kt2i = jet_scale_for_algorithm(_jets[ii]);
+      int jj = DNN->NearestNeighbourIndex(ii);
+      if (kt2i <= jet_scale_for_algorithm(_jets[jj])) {
+	double dij = DeltaR2 * kt2i;
+	DijMap.insert(DijEntry(dij, TwoVertices(ii,jj)));
+      }
+    }
+  }
+}
+
+
+FASTJET_END_NAMESPACE
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence_DumbN3.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence_DumbN3.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence_DumbN3.cc	(revision 5)
@@ -0,0 +1,133 @@
+//STARTHEADER
+// $Id: ClusterSequence_DumbN3.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/ClusterSequence.hh"
+#include<iostream>
+#include<cmath>
+#include <cstdlib>
+#include<cassert>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+
+using namespace std;
+
+
+//----------------------------------------------------------------------
+/// Run the clustering in a very slow variant of the N^3 algorithm. 
+///
+/// The only thing this routine has going for it is that memory usage
+/// is O(N)!
+void ClusterSequence::_really_dumb_cluster () {
+
+  // the array that will be overwritten here will be one
+  // of pointers to jets.
+  vector<PseudoJet *> jetsp(_jets.size());
+  vector<int>         indices(_jets.size());
+
+  for (size_t i = 0; i<_jets.size(); i++) {
+    jetsp[i] = & _jets[i];
+    indices[i] = i;
+  }
+
+  for (int n = jetsp.size(); n > 0; n--) {
+    int ii, jj;
+    // find smallest beam distance [remember jet_scale_for_algorithm 
+    // will return kt^2 for the kt-algorithm and 1 for the Cambridge/Aachen]
+    double ymin = jet_scale_for_algorithm(*(jetsp[0]));
+    ii = 0; jj = -2;
+    for (int i = 0; i < n; i++) {
+      double yiB = jet_scale_for_algorithm(*(jetsp[i]));
+      if (yiB < ymin) {
+	ymin = yiB; ii = i; jj = -2;}
+    }
+
+    // find smallest distance between pair of jetsp
+    for (int i = 0; i < n-1; i++) {
+      for (int j = i+1; j < n; j++) {
+	//double y = jetsp[i]->kt_distance(*jetsp[j])*_invR2;
+	double y = min(jet_scale_for_algorithm(*(jetsp[i])), 
+		       jet_scale_for_algorithm(*(jetsp[j])))
+	            * jetsp[i]->plain_distance(*jetsp[j])*_invR2;
+	if (y < ymin) {ymin = y; ii = i; jj = j;}
+      }
+    }
+
+    // output recombination sequence
+    // old "ktclus" way of labelling
+    //cout <<n<< " "<< ii+1 << " with " << jj+1 << "; y = "<< ymin<<endl;
+    //OBS // new delaunay way of labelling
+    //OBS int jjindex_or_beam, iiindex;
+    //OBS if (jj < 0) {jjindex_or_beam = BeamJet; iiindex = indices[ii];} 
+    //OBS else {
+    //OBS   jjindex_or_beam = max(indices[ii],indices[jj]);
+    //OBS   iiindex =         min(indices[ii],indices[jj]);
+    //OBS }
+
+    // now recombine
+    int newn = 2*jetsp.size() - n;
+    if (jj >= 0) {
+      // combine pair
+      int nn; // new jet index
+      _do_ij_recombination_step(jetsp[ii]-&_jets[0], 
+				jetsp[jj]-&_jets[0], ymin, nn);
+      
+      // sort out internal bookkeeping
+      jetsp[ii] = &_jets[nn];
+      // have jj point to jet that was pointed at by n-1 
+      // (since original jj is no longer current, so put n-1 into jj)
+      jetsp[jj] = jetsp[n-1];
+      indices[ii] = newn;
+      indices[jj] = indices[n-1];
+
+      //OBS_jets.push_back(*jetsp[ii] + *jetsp[jj]);
+      //OBSjetsp[ii] = &_jets[_jets.size()-1];
+      //OBS// have jj point to jet that was pointed at by n-1 
+      //OBS// (since original jj is no longer current, so put n-1 into jj)
+      //OBSjetsp[jj] = jetsp[n-1];
+      //OBS
+      //OBSindices[ii] = newn;
+      //OBSindices[jj] = indices[n-1];
+      //OBS_add_step_to_history(newn,iiindex,
+      //OBS			      jjindex_or_beam,_jets.size()-1,ymin);
+    } else {
+      // combine ii with beam
+      _do_iB_recombination_step(jetsp[ii]-&_jets[0], ymin);
+      // put last jet (pointer) in place of ii (which has disappeared)
+      jetsp[ii] = jetsp[n-1];
+      indices[ii] = indices[n-1];
+      //OBS_add_step_to_history(newn,iiindex,jjindex_or_beam,Invalid, ymin);
+    }
+  }
+
+}
+
+FASTJET_END_NAMESPACE
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence_N2.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence_N2.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence_N2.cc	(revision 5)
@@ -0,0 +1,128 @@
+//STARTHEADER
+// $Id: ClusterSequence_N2.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+// The plain N^2 part of the ClusterSequence class -- separated out
+// from the rest of the class implementation so as to speed up
+// compilation of this particular part while it is under test.
+
+#include "fastjet/internal/ClusterSequence_N2.icc"
+
+#include<iostream>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+
+using namespace std;
+
+
+//*************************************************************************
+//
+//                             THINGS FOR E+E-
+//
+//*************************************************************************
+
+
+//----------------------------------------------------------------------
+template<> inline void ClusterSequence::_bj_set_jetinfo(
+                           EEBriefJet * const jetA, const int _jets_index) const {
+
+  double E = _jets[_jets_index].E();
+  double scale = E*E; // the default energy scale for the kt alg
+  double p  = jet_def().extra_param(); // in case we're ee_genkt
+  switch (_jet_algorithm) {
+  case ee_kt_algorithm:
+    assert(_Rparam > 2.0); // force this to be true! [not best place, but works]
+    // recall that _invR2 is artificially set to 1 for this alg
+    // so that we automatically have dij = scale * 2(1-cos theta_ij)
+    // Normally, _Rparam should be automatically set to 4 from JetDefinition
+    break; 
+  case ee_genkt_algorithm:
+    if (p <= 0 && scale < 1e-300) scale = 1e-300; // same dodgy safety as genkt
+    scale = pow(scale,p);
+    break;
+  default:
+    throw Error("Unrecognised jet algorithm");
+  }
+  jetA->kt2  = scale; // "kt2" might one day be renamed as "scale" or some such
+
+  double norm = _jets[_jets_index].modp2();
+  if (norm > 0) {
+    norm = 1.0/sqrt(norm);
+    jetA->nx = norm * _jets[_jets_index].px();
+    jetA->ny = norm * _jets[_jets_index].py();
+    jetA->nz = norm * _jets[_jets_index].pz();
+  } else {
+    jetA->nx = 0.0;
+    jetA->ny = 0.0;
+    jetA->nz = 1.0;
+  }
+  jetA->_jets_index = _jets_index;
+  // initialise NN info as well
+  jetA->NN_dist = _R2;
+  jetA->NN      = NULL;
+}
+
+//----------------------------------------------------------------------
+// returns the angular distance between the two jets
+template<> double ClusterSequence::_bj_dist(
+                const EEBriefJet * const jeta, 
+                const EEBriefJet * const jetb) const {
+  double dist = 1.0 
+    - jeta->nx*jetb->nx
+    - jeta->ny*jetb->ny
+    - jeta->nz*jetb->nz;
+  dist *= 2; // distance is _2_*min(Ei^2,Ej^2)*(1-cos theta)
+  return dist;
+}
+
+
+
+// get explicit copies of the two N2 cluster cases we need
+// plain BriefJet
+void ClusterSequence::_simple_N2_cluster_BriefJet() {  
+  _simple_N2_cluster<BriefJet>();
+}
+
+
+// e+e- BriefJet
+void ClusterSequence::_simple_N2_cluster_EEBriefJet() {  
+  _simple_N2_cluster<EEBriefJet>();
+}
+
+// //----------------------------------------------------------------------
+// /// Force instantiation of desired versions of _simple_N2_cluster
+// ///
+// /// This is not very elegant...
+// void ClusterSequence::_dummy_N2_cluster_instantiation() {
+//   _simple_N2_cluster<BriefJet>();
+//   _simple_N2_cluster<EEBriefJet>();
+// }
+
+FASTJET_END_NAMESPACE
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence_TiledN2.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence_TiledN2.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/ClusterSequence_TiledN2.cc	(revision 5)
@@ -0,0 +1,941 @@
+//STARTHEADER
+// $Id: ClusterSequence_TiledN2.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+// The plain N^2 part of the ClusterSequence class -- separated out
+// from the rest of the class implementation so as to speed up
+// compilation of this particular part while it is under test.
+
+#include<iostream>
+#include<vector>
+#include<cmath>
+#include<algorithm>
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/internal/MinHeap.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+
+
+//----------------------------------------------------------------------
+void ClusterSequence::_bj_remove_from_tiles(TiledJet * const jet) {
+  Tile * tile = & _tiles[jet->tile_index];
+
+  if (jet->previous == NULL) {
+    // we are at head of the tile, so reset it.
+    // If this was the only jet on the tile then tile->head will now be NULL
+    tile->head = jet->next;
+  } else {
+    // adjust link from previous jet in this tile
+    jet->previous->next = jet->next;
+  }
+  if (jet->next != NULL) {
+    // adjust backwards-link from next jet in this tile
+    jet->next->previous = jet->previous;
+  }
+}
+
+//----------------------------------------------------------------------
+/// Set up the tiles:
+///  - decide the range in eta
+///  - allocate the tiles
+///  - set up the cross-referencing info between tiles
+///
+/// The neighbourhood of a tile is set up as follows
+///
+/// 	      LRR
+///           LXR
+///           LLR
+///
+/// such that tiles is an array containing XLLLLRRRR with pointers
+///                                         |   \ RH_tiles
+///                                         \ surrounding_tiles
+///
+/// with appropriate precautions when close to the edge of the tiled
+/// region.
+///
+void ClusterSequence::_initialise_tiles() {
+
+  // first decide tile sizes (with a lower bound to avoid huge memory use with
+  // very small R)
+  double default_size = max(0.1,_Rparam);
+  _tile_size_eta = default_size;
+  // it makes no sense to go below 3 tiles in phi -- 3 tiles is
+  // sufficient to make sure all pair-wise combinations up to pi in
+  // phi are possible
+  _n_tiles_phi   = max(3,int(floor(twopi/default_size)));
+  _tile_size_phi = twopi / _n_tiles_phi; // >= _Rparam and fits in 2pi
+
+  // always include zero rapidity in the tiling region
+  _tiles_eta_min = 0.0;
+  _tiles_eta_max = 0.0;
+  // but go no further than following
+  const double maxrap = 7.0;
+
+  // and find out how much further one should go
+  for(unsigned int i = 0; i < _jets.size(); i++) {
+    double eta = _jets[i].rap();
+    // first check if eta is in range -- to avoid taking into account
+    // very spurious rapidities due to particles with near-zero kt.
+    if (abs(eta) < maxrap) {
+      if (eta < _tiles_eta_min) {_tiles_eta_min = eta;}
+      if (eta > _tiles_eta_max) {_tiles_eta_max = eta;}
+    }
+  }
+
+  // now adjust the values
+  _tiles_ieta_min = int(floor(_tiles_eta_min/_tile_size_eta));
+  _tiles_ieta_max = int(floor( _tiles_eta_max/_tile_size_eta));
+  _tiles_eta_min = _tiles_ieta_min * _tile_size_eta;
+  _tiles_eta_max = _tiles_ieta_max * _tile_size_eta;
+
+  // allocate the tiles
+  _tiles.resize((_tiles_ieta_max-_tiles_ieta_min+1)*_n_tiles_phi);
+
+  // now set up the cross-referencing between tiles
+  for (int ieta = _tiles_ieta_min; ieta <= _tiles_ieta_max; ieta++) {
+    for (int iphi = 0; iphi < _n_tiles_phi; iphi++) {
+      Tile * tile = & _tiles[_tile_index(ieta,iphi)];
+      // no jets in this tile yet
+      tile->head = NULL; // first element of tiles points to itself
+      tile->begin_tiles[0] =  tile;
+      Tile ** pptile = & (tile->begin_tiles[0]);
+      pptile++;
+      //
+      // set up L's in column to the left of X
+      tile->surrounding_tiles = pptile;
+      if (ieta > _tiles_ieta_min) {
+	// with the itile subroutine, we can safely run tiles from
+	// idphi=-1 to idphi=+1, because it takes care of
+	// negative and positive boundaries
+	for (int idphi = -1; idphi <=+1; idphi++) {
+	  *pptile = & _tiles[_tile_index(ieta-1,iphi+idphi)];
+	  pptile++;
+	}	
+      }
+      // now set up last L (below X)
+      *pptile = & _tiles[_tile_index(ieta,iphi-1)];
+      pptile++;
+      // set up first R (above X)
+      tile->RH_tiles = pptile;
+      *pptile = & _tiles[_tile_index(ieta,iphi+1)];
+      pptile++;
+      // set up remaining R's, to the right of X
+      if (ieta < _tiles_ieta_max) {
+	for (int idphi = -1; idphi <= +1; idphi++) {
+	  *pptile = & _tiles[_tile_index(ieta+1,iphi+idphi)];
+	  pptile++;
+	}	
+      }
+      // now put semaphore for end tile
+      tile->end_tiles = pptile;
+      // finally make sure tiles are untagged
+      tile->tagged = false;
+    }
+  }
+
+}
+
+
+//----------------------------------------------------------------------
+/// return the tile index corresponding to the given eta,phi point
+int ClusterSequence::_tile_index(const double & eta, const double & phi) const {
+  int ieta, iphi;
+  if      (eta <= _tiles_eta_min) {ieta = 0;}
+  else if (eta >= _tiles_eta_max) {ieta = _tiles_ieta_max-_tiles_ieta_min;}
+  else {
+    //ieta = int(floor((eta - _tiles_eta_min) / _tile_size_eta));
+    ieta = int(((eta - _tiles_eta_min) / _tile_size_eta));
+    // following needed in case of rare but nasty rounding errors
+    if (ieta > _tiles_ieta_max-_tiles_ieta_min) {
+      ieta = _tiles_ieta_max-_tiles_ieta_min;} 
+  }
+  // allow for some extent of being beyond range in calculation of phi
+  // as well
+  //iphi = (int(floor(phi/_tile_size_phi)) + _n_tiles_phi) % _n_tiles_phi;
+  // with just int and no floor, things run faster but beware
+  iphi = int((phi+twopi)/_tile_size_phi) % _n_tiles_phi;
+  return (iphi + ieta * _n_tiles_phi);
+}
+
+
+//----------------------------------------------------------------------
+// overloaded version which additionally sets up information regarding the
+// tiling
+inline void ClusterSequence::_tj_set_jetinfo( TiledJet * const jet,
+					      const int _jets_index) {
+  // first call the generic setup
+  _bj_set_jetinfo<>(jet, _jets_index);
+
+  // Then do the setup specific to the tiled case.
+
+  // Find out which tile it belonds to
+  jet->tile_index = _tile_index(jet->eta, jet->phi);
+
+  // Insert it into the tile's linked list of jets
+  Tile * tile = &_tiles[jet->tile_index];
+  jet->previous   = NULL;
+  jet->next       = tile->head;
+  if (jet->next != NULL) {jet->next->previous = jet;}
+  tile->head      = jet;
+}
+
+
+//----------------------------------------------------------------------
+/// output the contents of the tiles
+void ClusterSequence::_print_tiles(TiledJet * briefjets ) const {
+  for (vector<Tile>::const_iterator tile = _tiles.begin(); 
+       tile < _tiles.end(); tile++) {
+    cout << "Tile " << tile - _tiles.begin()<<" = ";
+    vector<int> list;
+    for (TiledJet * jetI = tile->head; jetI != NULL; jetI = jetI->next) {
+      list.push_back(jetI-briefjets);
+      //cout <<" "<<jetI-briefjets;
+    }
+    sort(list.begin(),list.end());
+    for (unsigned int i = 0; i < list.size(); i++) {cout <<" "<<list[i];}
+    cout <<"\n";
+  }
+}
+
+
+//----------------------------------------------------------------------
+/// Add to the vector tile_union the tiles that are in the neighbourhood
+/// of the specified tile_index, including itself -- start adding
+/// from position n_near_tiles-1, and increase n_near_tiles as
+/// you go along (could have done it more C++ like with vector with reserved
+/// space, but fear is that it would have been slower, e.g. checking
+/// for end of vector at each stage to decide whether to resize it)
+void ClusterSequence::_add_neighbours_to_tile_union(const int tile_index, 
+	       vector<int> & tile_union, int & n_near_tiles) const {
+  for (Tile * const * near_tile = _tiles[tile_index].begin_tiles; 
+       near_tile != _tiles[tile_index].end_tiles; near_tile++){
+    // get the tile number
+    tile_union[n_near_tiles] = *near_tile - & _tiles[0];
+    n_near_tiles++;
+  }
+}
+
+
+//----------------------------------------------------------------------
+/// Like _add_neighbours_to_tile_union, but only adds neighbours if 
+/// their "tagged" status is false; when a neighbour is added its
+/// tagged status is set to true.
+inline void ClusterSequence::_add_untagged_neighbours_to_tile_union(
+               const int tile_index, 
+	       vector<int> & tile_union, int & n_near_tiles)  {
+  for (Tile ** near_tile = _tiles[tile_index].begin_tiles; 
+       near_tile != _tiles[tile_index].end_tiles; near_tile++){
+    if (! (*near_tile)->tagged) {
+      (*near_tile)->tagged = true;
+      // get the tile number
+      tile_union[n_near_tiles] = *near_tile - & _tiles[0];
+      n_near_tiles++;
+    }
+  }
+}
+
+
+//----------------------------------------------------------------------
+/// run a tiled clustering
+void ClusterSequence::_tiled_N2_cluster() {
+
+  _initialise_tiles();
+
+  int n = _jets.size();
+  TiledJet * briefjets = new TiledJet[n];
+  TiledJet * jetA = briefjets, * jetB;
+  TiledJet oldB;
+  
+
+  // will be used quite deep inside loops, but declare it here so that
+  // memory (de)allocation gets done only once
+  vector<int> tile_union(3*n_tile_neighbours);
+  
+  // initialise the basic jet info 
+  for (int i = 0; i< n; i++) {
+    _tj_set_jetinfo(jetA, i);
+    //cout << i<<": "<<jetA->tile_index<<"\n";
+    jetA++; // move on to next entry of briefjets
+  }
+  TiledJet * tail = jetA; // a semaphore for the end of briefjets
+  TiledJet * head = briefjets; // a nicer way of naming start
+
+  // set up the initial nearest neighbour information
+  vector<Tile>::const_iterator tile;
+  for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
+    // first do it on this tile
+    for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
+      for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
+	double dist = _bj_dist(jetA,jetB);
+	if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
+	if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
+      }
+    }
+    // then do it for RH tiles
+    for (Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
+      for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
+	for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
+	  double dist = _bj_dist(jetA,jetB);
+	  if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
+	  if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
+	}
+      }
+    }
+  }
+  
+  // now create the diJ (where J is i's NN) table -- remember that 
+  // we differ from standard normalisation here by a factor of R2
+  double * diJ = new double[n];
+  jetA = head;
+  for (int i = 0; i < n; i++) {
+    diJ[i] = _bj_diJ(jetA);
+    jetA++; // have jetA follow i
+  }
+
+  // now run the recombination loop
+  int history_location = n-1;
+  while (tail != head) {
+
+    // find the minimum of the diJ on this round
+    double diJ_min = diJ[0];
+    int diJ_min_jet = 0;
+    for (int i = 1; i < n; i++) {
+      if (diJ[i] < diJ_min) {diJ_min_jet = i; diJ_min  = diJ[i];}
+    }
+
+    // do the recombination between A and B
+    history_location++;
+    jetA = & briefjets[diJ_min_jet];
+    jetB = jetA->NN;
+    // put the normalisation back in
+    diJ_min *= _invR2; 
+
+    //if (n == 19) {cout << "Hello "<<jetA-head<<" "<<jetB-head<<"\n";}
+
+    //cout <<" WILL RECOMBINE "<< jetA-briefjets<<" "<<jetB-briefjets<<"\n";
+
+    if (jetB != NULL) {
+      // jet-jet recombination
+      // If necessary relabel A & B to ensure jetB < jetA, that way if
+      // the larger of them == newtail then that ends up being jetA and 
+      // the new jet that is added as jetB is inserted in a position that
+      // has a future!
+      if (jetA < jetB) {std::swap(jetA,jetB);}
+
+      int nn; // new jet index
+      _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
+
+      //OBS// get the two history indices
+      //OBSint hist_a = _jets[jetA->_jets_index].cluster_hist_index();
+      //OBSint hist_b = _jets[jetB->_jets_index].cluster_hist_index();
+      //OBS// create the recombined jet
+      //OBS_jets.push_back(_jets[jetA->_jets_index] + _jets[jetB->_jets_index]);
+      //OBSint nn = _jets.size() - 1;
+      //OBS_jets[nn].set_cluster_hist_index(history_location);
+      //OBS// update history
+      //OBS//cout <<n-1<<" "<<jetA-head<<" "<<jetB-head<<"; ";
+      //OBS_add_step_to_history(history_location, 
+      //OBS  		   min(hist_a,hist_b),max(hist_a,hist_b),
+      //OBS			   nn, diJ_min);
+
+      // what was jetB will now become the new jet
+      _bj_remove_from_tiles(jetA);
+      oldB = * jetB;  // take a copy because we will need it...
+      _bj_remove_from_tiles(jetB);
+      _tj_set_jetinfo(jetB, nn); // also registers the jet in the tiling
+    } else {
+      // jet-beam recombination
+      _do_iB_recombination_step(jetA->_jets_index, diJ_min);
+	    
+      //OBS// get the hist_index
+      //OBSint hist_a = _jets[jetA->_jets_index].cluster_hist_index();
+      //OBS//cout <<n-1<<" "<<jetA-head<<" "<<-1<<"; ";
+      //OBS_add_step_to_history(history_location,hist_a,BeamJet,Invalid,diJ_min); 
+      _bj_remove_from_tiles(jetA);
+    }
+
+    // first establish the set of tiles over which we are going to 
+    // have to run searches for updated and new nearest-neighbours
+    int n_near_tiles = 0;
+    _add_neighbours_to_tile_union(jetA->tile_index, tile_union, n_near_tiles);
+    if (jetB != NULL) {
+      bool sort_it = false;
+      if (jetB->tile_index != jetA->tile_index) {
+	sort_it = true;
+	_add_neighbours_to_tile_union(jetB->tile_index,tile_union,n_near_tiles);
+      }
+      if (oldB.tile_index != jetA->tile_index && 
+	  oldB.tile_index != jetB->tile_index) {
+	sort_it = true;
+	_add_neighbours_to_tile_union(oldB.tile_index,tile_union,n_near_tiles);
+      }
+
+      if (sort_it) {
+	// sort the tiles before then compressing the list
+	sort(tile_union.begin(), tile_union.begin()+n_near_tiles);
+	// and now condense the list
+	int nnn = 1;
+	for (int i = 1; i < n_near_tiles; i++) {
+	  if (tile_union[i] != tile_union[nnn-1]) {
+	    tile_union[nnn] = tile_union[i]; 
+	    nnn++;
+	  }
+	}
+	n_near_tiles = nnn;
+      }
+    }
+
+    // now update our nearest neighbour info and diJ table
+    // first reduce size of table
+    tail--; n--;
+    if (jetA == tail) {
+      // there is nothing to be done
+    } else {
+      // Copy last jet contents and diJ info into position of jetA
+      *jetA = *tail;
+      diJ[jetA - head] = diJ[tail-head];
+      // IN the tiling fix pointers to tail and turn them into
+      // pointers to jetA (from predecessors, successors and the tile
+      // head if need be)
+      if (jetA->previous == NULL) {
+	_tiles[jetA->tile_index].head = jetA;
+      } else {
+	jetA->previous->next = jetA;
+      }
+      if (jetA->next != NULL) {jetA->next->previous = jetA;}
+    }
+
+    // Initialise jetB's NN distance as well as updating it for 
+    // other particles.
+    for (int itile = 0; itile < n_near_tiles; itile++) {
+      Tile * tile_ptr = &_tiles[tile_union[itile]];
+      for (TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
+	// see if jetI had jetA or jetB as a NN -- if so recalculate the NN
+	if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
+	  jetI->NN_dist = _R2;
+	  jetI->NN      = NULL;
+	  // now go over tiles that are neighbours of I (include own tile)
+	  for (Tile ** near_tile  = tile_ptr->begin_tiles; 
+	               near_tile != tile_ptr->end_tiles; near_tile++) {
+	    // and then over the contents of that tile
+	    for (TiledJet * jetJ  = (*near_tile)->head; 
+                            jetJ != NULL; jetJ = jetJ->next) {
+	      double dist = _bj_dist(jetI,jetJ);
+	      if (dist < jetI->NN_dist && jetJ != jetI) {
+		jetI->NN_dist = dist; jetI->NN = jetJ;
+	      }
+	    }
+	  }
+	  diJ[jetI-head] = _bj_diJ(jetI); // update diJ 
+	}
+	// check whether new jetB is closer than jetI's current NN and
+	// if need to update things
+	if (jetB != NULL) {
+	  double dist = _bj_dist(jetI,jetB);
+	  if (dist < jetI->NN_dist) {
+	    if (jetI != jetB) {
+	      jetI->NN_dist = dist;
+	      jetI->NN = jetB;
+	      diJ[jetI-head] = _bj_diJ(jetI); // update diJ...
+	    }
+	  }
+	  if (dist < jetB->NN_dist) {
+	    if (jetI != jetB) {
+	      jetB->NN_dist = dist;
+	      jetB->NN      = jetI;}
+	  }
+	}
+      }
+    }
+
+
+    if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
+    //cout << n<<" "<<briefjets[95].NN-briefjets<<" "<<briefjets[95].NN_dist <<"\n";
+
+    // remember to update pointers to tail
+    for (Tile ** near_tile = _tiles[tail->tile_index].begin_tiles; 
+	         near_tile!= _tiles[tail->tile_index].end_tiles; near_tile++){
+      // and then the contents of that tile
+      for (TiledJet * jetJ = (*near_tile)->head; 
+	             jetJ != NULL; jetJ = jetJ->next) {
+	if (jetJ->NN == tail) {jetJ->NN = jetA;}
+      }
+    }
+
+    //for (int i = 0; i < n; i++) {
+    //  if (briefjets[i].NN-briefjets >= n && briefjets[i].NN != NULL) {cout <<"YOU MUST BE CRAZY for n ="<<n<<", i = "<<i<<", NN = "<<briefjets[i].NN-briefjets<<"\n";}
+    //}
+
+
+    if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
+    //cout << briefjets[95].NN-briefjets<<" "<<briefjets[95].NN_dist <<"\n";
+
+  }
+
+  // final cleaning up;
+  delete[] diJ;
+  delete[] briefjets;
+}
+
+
+//----------------------------------------------------------------------
+/// run a tiled clustering
+void ClusterSequence::_faster_tiled_N2_cluster() {
+
+  _initialise_tiles();
+
+  int n = _jets.size();
+  TiledJet * briefjets = new TiledJet[n];
+  TiledJet * jetA = briefjets, * jetB;
+  TiledJet oldB;
+  
+
+  // will be used quite deep inside loops, but declare it here so that
+  // memory (de)allocation gets done only once
+  vector<int> tile_union(3*n_tile_neighbours);
+  
+  // initialise the basic jet info 
+  for (int i = 0; i< n; i++) {
+    _tj_set_jetinfo(jetA, i);
+    //cout << i<<": "<<jetA->tile_index<<"\n";
+    jetA++; // move on to next entry of briefjets
+  }
+  TiledJet * head = briefjets; // a nicer way of naming start
+
+  // set up the initial nearest neighbour information
+  vector<Tile>::const_iterator tile;
+  for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
+    // first do it on this tile
+    for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
+      for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
+	double dist = _bj_dist(jetA,jetB);
+	if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
+	if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
+      }
+    }
+    // then do it for RH tiles
+    for (Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
+      for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
+	for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
+	  double dist = _bj_dist(jetA,jetB);
+	  if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
+	  if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
+	}
+      }
+    }
+    // no need to do it for LH tiles, since they are implicitly done
+    // when we set NN for both jetA and jetB on the RH tiles.
+  }
+
+  
+  // now create the diJ (where J is i's NN) table -- remember that 
+  // we differ from standard normalisation here by a factor of R2
+  // (corrected for at the end). 
+  struct diJ_plus_link {
+    double     diJ; // the distance
+    TiledJet * jet; // the jet (i) for which we've found this distance
+                    // (whose NN will the J).
+  };
+  diJ_plus_link * diJ = new diJ_plus_link[n];
+  jetA = head;
+  for (int i = 0; i < n; i++) {
+    diJ[i].diJ = _bj_diJ(jetA); // kt distance * R^2
+    diJ[i].jet = jetA;  // our compact diJ table will not be in	     
+    jetA->diJ_posn = i; // one-to-one corresp. with non-compact jets,
+                        // so set up bi-directional correspondence here.
+    jetA++; // have jetA follow i 
+  }
+
+  // now run the recombination loop
+  int history_location = n-1;
+  while (n > 0) {
+
+    // find the minimum of the diJ on this round
+    diJ_plus_link * best, *stop; // pointers a bit faster than indices
+    // could use best to keep track of diJ min, but it turns out to be
+    // marginally faster to have a separate variable (avoids n
+    // dereferences at the expense of n/2 assignments).
+    double diJ_min = diJ[0].diJ; // initialise the best one here.
+    best = diJ;                  // and here
+    stop = diJ+n;
+    for (diJ_plus_link * here = diJ+1; here != stop; here++) {
+      if (here->diJ < diJ_min) {best = here; diJ_min  = here->diJ;}
+    }
+
+    // do the recombination between A and B
+    history_location++;
+    jetA = best->jet;
+    jetB = jetA->NN;
+    // put the normalisation back in
+    diJ_min *= _invR2; 
+
+    if (jetB != NULL) {
+      // jet-jet recombination
+      // If necessary relabel A & B to ensure jetB < jetA, that way if
+      // the larger of them == newtail then that ends up being jetA and 
+      // the new jet that is added as jetB is inserted in a position that
+      // has a future!
+      if (jetA < jetB) {std::swap(jetA,jetB);}
+
+      int nn; // new jet index
+      _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
+      
+      //OBS// get the two history indices
+      //OBSint ihstry_a = _jets[jetA->_jets_index].cluster_hist_index();
+      //OBSint ihstry_b = _jets[jetB->_jets_index].cluster_hist_index();
+      //OBS// create the recombined jet
+      //OBS_jets.push_back(_jets[jetA->_jets_index] + _jets[jetB->_jets_index]);
+      //OBSint nn = _jets.size() - 1;
+      //OBS_jets[nn].set_cluster_hist_index(history_location);
+      //OBS// update history
+      //OBS//cout <<n-1<<" "<<jetA-head<<" "<<jetB-head<<"; ";
+      //OBS_add_step_to_history(history_location, 
+      //OBS  		   min(ihstry_a,ihstry_b),max(ihstry_a,ihstry_b),
+      //OBS			   nn, diJ_min);
+      // what was jetB will now become the new jet
+      _bj_remove_from_tiles(jetA);
+      oldB = * jetB;  // take a copy because we will need it...
+      _bj_remove_from_tiles(jetB);
+      _tj_set_jetinfo(jetB, nn); // cause jetB to become _jets[nn]
+                                 // (also registers the jet in the tiling)
+    } else {
+      // jet-beam recombination
+      // get the hist_index
+      _do_iB_recombination_step(jetA->_jets_index, diJ_min);
+      //OBSint ihstry_a = _jets[jetA->_jets_index].cluster_hist_index();
+      //OBS//cout <<n-1<<" "<<jetA-head<<" "<<-1<<"; ";
+      //OBS_add_step_to_history(history_location,ihstry_a,BeamJet,Invalid,diJ_min); 
+      _bj_remove_from_tiles(jetA);
+    }
+
+    // first establish the set of tiles over which we are going to
+    // have to run searches for updated and new nearest-neighbours --
+    // basically a combination of vicinity of the tiles of the two old
+    // and one new jet.
+    int n_near_tiles = 0;
+    _add_untagged_neighbours_to_tile_union(jetA->tile_index, 
+					   tile_union, n_near_tiles);
+    if (jetB != NULL) {
+      if (jetB->tile_index != jetA->tile_index) {
+	_add_untagged_neighbours_to_tile_union(jetB->tile_index,
+					       tile_union,n_near_tiles);
+      }
+      if (oldB.tile_index != jetA->tile_index && 
+	  oldB.tile_index != jetB->tile_index) {
+	_add_untagged_neighbours_to_tile_union(oldB.tile_index,
+					       tile_union,n_near_tiles);
+      }
+    }
+
+    // now update our nearest neighbour info and diJ table
+    // first reduce size of table
+    n--;
+    // then compactify the diJ by taking the last of the diJ and copying
+    // it to the position occupied by the diJ for jetA
+    diJ[n].jet->diJ_posn = jetA->diJ_posn;
+    diJ[jetA->diJ_posn] = diJ[n];
+
+    // Initialise jetB's NN distance as well as updating it for 
+    // other particles.
+    // Run over all tiles in our union 
+    for (int itile = 0; itile < n_near_tiles; itile++) {
+      Tile * tile_ptr = &_tiles[tile_union[itile]];
+      tile_ptr->tagged = false; // reset tag, since we're done with unions
+      // run over all jets in the current tile
+      for (TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
+	// see if jetI had jetA or jetB as a NN -- if so recalculate the NN
+	if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
+	  jetI->NN_dist = _R2;
+	  jetI->NN      = NULL;
+	  // now go over tiles that are neighbours of I (include own tile)
+	  for (Tile ** near_tile  = tile_ptr->begin_tiles; 
+	               near_tile != tile_ptr->end_tiles; near_tile++) {
+	    // and then over the contents of that tile
+	    for (TiledJet * jetJ  = (*near_tile)->head; 
+                            jetJ != NULL; jetJ = jetJ->next) {
+	      double dist = _bj_dist(jetI,jetJ);
+	      if (dist < jetI->NN_dist && jetJ != jetI) {
+		jetI->NN_dist = dist; jetI->NN = jetJ;
+	      }
+	    }
+	  }
+	  diJ[jetI->diJ_posn].diJ = _bj_diJ(jetI); // update diJ kt-dist
+	}
+	// check whether new jetB is closer than jetI's current NN and
+	// if jetI is closer than jetB's current (evolving) nearest
+	// neighbour. Where relevant update things
+	if (jetB != NULL) {
+	  double dist = _bj_dist(jetI,jetB);
+	  if (dist < jetI->NN_dist) {
+	    if (jetI != jetB) {
+	      jetI->NN_dist = dist;
+	      jetI->NN = jetB;
+	      diJ[jetI->diJ_posn].diJ = _bj_diJ(jetI); // update diJ...
+	    }
+	  }
+	  if (dist < jetB->NN_dist) {
+	    if (jetI != jetB) {
+	      jetB->NN_dist = dist;
+	      jetB->NN      = jetI;}
+	  }
+	}
+      }
+    }
+
+    // finally, register the updated kt distance for B
+    if (jetB != NULL) {diJ[jetB->diJ_posn].diJ = _bj_diJ(jetB);}
+
+  }
+
+  // final cleaning up;
+  delete[] diJ;
+  delete[] briefjets;
+}
+
+
+
+//----------------------------------------------------------------------
+/// run a tiled clustering, with our minheap for keeping track of the
+/// smallest dij
+void ClusterSequence::_minheap_faster_tiled_N2_cluster() {
+
+  _initialise_tiles();
+
+  int n = _jets.size();
+  TiledJet * briefjets = new TiledJet[n];
+  TiledJet * jetA = briefjets, * jetB;
+  TiledJet oldB;
+  
+
+  // will be used quite deep inside loops, but declare it here so that
+  // memory (de)allocation gets done only once
+  vector<int> tile_union(3*n_tile_neighbours);
+  
+  // initialise the basic jet info 
+  for (int i = 0; i< n; i++) {
+    _tj_set_jetinfo(jetA, i);
+    //cout << i<<": "<<jetA->tile_index<<"\n";
+    jetA++; // move on to next entry of briefjets
+  }
+  TiledJet * head = briefjets; // a nicer way of naming start
+
+  // set up the initial nearest neighbour information
+  vector<Tile>::const_iterator tile;
+  for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
+    // first do it on this tile
+    for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
+      for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
+	double dist = _bj_dist(jetA,jetB);
+	if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
+	if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
+      }
+    }
+    // then do it for RH tiles
+    for (Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
+      for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
+	for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
+	  double dist = _bj_dist(jetA,jetB);
+	  if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
+	  if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
+	}
+      }
+    }
+    // no need to do it for LH tiles, since they are implicitly done
+    // when we set NN for both jetA and jetB on the RH tiles.
+  }
+
+  
+  //// now create the diJ (where J is i's NN) table -- remember that 
+  //// we differ from standard normalisation here by a factor of R2
+  //// (corrected for at the end). 
+  //struct diJ_plus_link {
+  //  double     diJ; // the distance
+  //  TiledJet * jet; // the jet (i) for which we've found this distance
+  //                  // (whose NN will the J).
+  //};
+  //diJ_plus_link * diJ = new diJ_plus_link[n];
+  //jetA = head;
+  //for (int i = 0; i < n; i++) {
+  //  diJ[i].diJ = _bj_diJ(jetA); // kt distance * R^2
+  //  diJ[i].jet = jetA;  // our compact diJ table will not be in	     
+  //  jetA->diJ_posn = i; // one-to-one corresp. with non-compact jets,
+  //                      // so set up bi-directional correspondence here.
+  //  jetA++; // have jetA follow i 
+  //}
+
+  vector<double> diJs(n);
+  for (int i = 0; i < n; i++) {
+    diJs[i] = _bj_diJ(&briefjets[i]);
+    briefjets[i].label_minheap_update_done();
+  }
+  MinHeap minheap(diJs);
+  // have a stack telling us which jets we'll have to update on the heap
+  vector<TiledJet *> jets_for_minheap;
+  jets_for_minheap.reserve(n); 
+
+  // now run the recombination loop
+  int history_location = n-1;
+  while (n > 0) {
+
+    double diJ_min = minheap.minval() *_invR2;
+    jetA = head + minheap.minloc();
+
+    // do the recombination between A and B
+    history_location++;
+    jetB = jetA->NN;
+
+    if (jetB != NULL) {
+      // jet-jet recombination
+      // If necessary relabel A & B to ensure jetB < jetA, that way if
+      // the larger of them == newtail then that ends up being jetA and 
+      // the new jet that is added as jetB is inserted in a position that
+      // has a future!
+      if (jetA < jetB) {std::swap(jetA,jetB);}
+
+      int nn; // new jet index
+      _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
+      
+      // what was jetB will now become the new jet
+      _bj_remove_from_tiles(jetA);
+      oldB = * jetB;  // take a copy because we will need it...
+      _bj_remove_from_tiles(jetB);
+      _tj_set_jetinfo(jetB, nn); // cause jetB to become _jets[nn]
+                                 // (also registers the jet in the tiling)
+    } else {
+      // jet-beam recombination
+      // get the hist_index
+      _do_iB_recombination_step(jetA->_jets_index, diJ_min);
+      _bj_remove_from_tiles(jetA);
+    }
+
+    // remove the minheap entry for jetA
+    minheap.remove(jetA-head);
+
+    // first establish the set of tiles over which we are going to
+    // have to run searches for updated and new nearest-neighbours --
+    // basically a combination of vicinity of the tiles of the two old
+    // and one new jet.
+    int n_near_tiles = 0;
+    _add_untagged_neighbours_to_tile_union(jetA->tile_index, 
+					   tile_union, n_near_tiles);
+    if (jetB != NULL) {
+      if (jetB->tile_index != jetA->tile_index) {
+	_add_untagged_neighbours_to_tile_union(jetB->tile_index,
+					       tile_union,n_near_tiles);
+      }
+      if (oldB.tile_index != jetA->tile_index && 
+	  oldB.tile_index != jetB->tile_index) {
+	// GS: the line below generates a warning that oldB.tile_index
+	// may be used uninitialised. However, to reach this point, we
+	// ned jetB != NULL (see test a few lines above) and is jetB
+	// !=NULL, one would have gone through "oldB = *jetB before
+	// (see piece of code ~20 line above), so the index is
+	// initialised. We do not do anything to avoid the warning to
+	// avoid any potential speed impact.
+	_add_untagged_neighbours_to_tile_union(oldB.tile_index,
+					       tile_union,n_near_tiles);
+      }
+      // indicate that we'll have to update jetB in the minheap
+      jetB->label_minheap_update_needed();
+      jets_for_minheap.push_back(jetB);
+    }
+
+
+    // Initialise jetB's NN distance as well as updating it for 
+    // other particles.
+    // Run over all tiles in our union 
+    for (int itile = 0; itile < n_near_tiles; itile++) {
+      Tile * tile_ptr = &_tiles[tile_union[itile]];
+      tile_ptr->tagged = false; // reset tag, since we're done with unions
+      // run over all jets in the current tile
+      for (TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
+	// see if jetI had jetA or jetB as a NN -- if so recalculate the NN
+	if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
+	  jetI->NN_dist = _R2;
+	  jetI->NN      = NULL;
+	  // label jetI as needing heap action...
+	  if (!jetI->minheap_update_needed()) {
+	    jetI->label_minheap_update_needed();
+	    jets_for_minheap.push_back(jetI);}
+	  // now go over tiles that are neighbours of I (include own tile)
+	  for (Tile ** near_tile  = tile_ptr->begin_tiles; 
+	               near_tile != tile_ptr->end_tiles; near_tile++) {
+	    // and then over the contents of that tile
+	    for (TiledJet * jetJ  = (*near_tile)->head; 
+                            jetJ != NULL; jetJ = jetJ->next) {
+	      double dist = _bj_dist(jetI,jetJ);
+	      if (dist < jetI->NN_dist && jetJ != jetI) {
+		jetI->NN_dist = dist; jetI->NN = jetJ;
+	      }
+	    }
+	  }
+	}
+	// check whether new jetB is closer than jetI's current NN and
+	// if jetI is closer than jetB's current (evolving) nearest
+	// neighbour. Where relevant update things
+	if (jetB != NULL) {
+	  double dist = _bj_dist(jetI,jetB);
+	  if (dist < jetI->NN_dist) {
+	    if (jetI != jetB) {
+	      jetI->NN_dist = dist;
+	      jetI->NN = jetB;
+	      // label jetI as needing heap action...
+	      if (!jetI->minheap_update_needed()) {
+		jetI->label_minheap_update_needed();
+		jets_for_minheap.push_back(jetI);}
+	    }
+	  }
+	  if (dist < jetB->NN_dist) {
+	    if (jetI != jetB) {
+	      jetB->NN_dist = dist;
+	      jetB->NN      = jetI;}
+	  }
+	}
+      }
+    }
+
+    // deal with jets whose minheap entry needs updating
+    while (jets_for_minheap.size() > 0) {
+      TiledJet * jetI = jets_for_minheap.back(); 
+      jets_for_minheap.pop_back();
+      minheap.update(jetI-head, _bj_diJ(jetI));
+      jetI->label_minheap_update_done();
+    }
+    n--;
+  }
+
+  // final cleaning up;
+  delete[] briefjets;
+}
+
+
+FASTJET_END_NAMESPACE
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/CompositeJetStructure.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/CompositeJetStructure.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/CompositeJetStructure.cc	(revision 5)
@@ -0,0 +1,171 @@
+//STARTHEADER
+// $Id: CompositeJetStructure.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include <fastjet/CompositeJetStructure.hh>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+
+
+//-------------------------------------------------------------------------------
+// \class CompositeJetStructure
+// The structure for a jet made of pieces
+//
+// This stores the vector of the pieces that make the jet and provide
+// the methods to access them
+// -------------------------------------------------------------------------------
+
+CompositeJetStructure::CompositeJetStructure(const std::vector<PseudoJet> & initial_pieces, 
+					     const JetDefinition::Recombiner * recombiner)
+  : _pieces(initial_pieces){
+  // deal with area support (cache the area if needed)
+  //--------------------------------------------------
+  // check if all the pieces have area, in which case store it
+  bool has_area_local = true;
+  for (vector<PseudoJet>::const_iterator pit=_pieces.begin(); pit!=_pieces.end(); pit++){
+    if (!pit->has_area()){
+      has_area_local = false;
+      continue;
+    }
+  }
+
+  if (has_area_local){
+    _area_4vector_ptr = new PseudoJet();
+    for (unsigned int i=0; i<_pieces.size(); i++){
+      const PseudoJet & p = _pieces[i];
+      if (recombiner)
+	recombiner->plus_equal(*_area_4vector_ptr, p.area_4vector());
+      else
+	*_area_4vector_ptr += p.area_4vector();
+    } 
+  } else {
+    _area_4vector_ptr = 0;
+  }
+
+}
+
+
+// description
+std::string CompositeJetStructure::description() const{ 
+  string str = "Composite PseudoJet";
+  return str; 
+}
+
+
+
+// things reimplemented from the base structure
+//------------------------------------------------------------------------------
+bool CompositeJetStructure::has_constituents() const{
+  //for (vector<PseudoJet>::const_iterator pit=_pieces.begin(); pit!=_pieces.end(); pit++)
+  //  if (!pit->has_constituents()) return false;
+  //
+  //return true;
+
+  // the only case where we do not have constituents is the case where
+  // there is no pieces!
+  return _pieces.size()!=0;
+}
+
+std::vector<PseudoJet> CompositeJetStructure::constituents(const PseudoJet & /*jet*/) const{
+  // recurse into the pieces that ahve constituents, just append the others
+  // the following code automatically throws an Error if any of the
+  // pieces has no constituents
+  vector<PseudoJet> all_constituents;
+  for (unsigned i = 0; i < _pieces.size(); i++) {
+    if (_pieces[i].has_constituents()){
+      vector<PseudoJet> constits = _pieces[i].constituents();
+      copy(constits.begin(), constits.end(), back_inserter(all_constituents));
+    } else {
+      all_constituents.push_back(_pieces[i]);
+    }
+  }
+ 
+  return all_constituents;
+}
+
+std::vector<PseudoJet> CompositeJetStructure::pieces(const PseudoJet & /*jet*/) const{
+  return _pieces;
+}
+
+
+// area-related material
+
+// check if it has a well-defined area
+bool CompositeJetStructure::has_area() const{
+  return (_area_4vector_ptr != 0);
+}
+
+// return the jet (scalar) area.
+double CompositeJetStructure::area(const PseudoJet & /*reference*/) const{
+  if (! has_area())
+    throw Error("One or more of this composite jet's pieces does not support area");
+
+  double a=0;
+  for (unsigned i = 0; i < _pieces.size(); i++)
+    a += _pieces[i].area();
+
+  return a;
+}
+
+// return the error (uncertainty) associated with the determination
+// of the area of this jet.
+// 
+// Be conservative: return the sum of the errors
+double CompositeJetStructure::area_error(const PseudoJet & /*reference*/) const{
+  if (! has_area())
+    throw Error("One or more of this composite jet's pieces does not support area");
+
+  double a_err=0;
+  for (unsigned i = 0; i < _pieces.size(); i++)
+    a_err += _pieces[i].area();
+
+  return a_err;
+}
+
+// return the jet 4-vector area.
+PseudoJet CompositeJetStructure::area_4vector(const PseudoJet & /*reference*/) const{
+  if (! has_area())
+    throw Error("One or more of this composite jet's pieces does not support area");
+
+  return *_area_4vector_ptr; // one is supposed to call has_area before!
+}
+
+// true if this jet is made exclusively of ghosts.
+//
+// In this case, it will be true if all pieces are pure ghost
+bool CompositeJetStructure::is_pure_ghost(const PseudoJet & /*reference*/) const{
+  for (unsigned i = 0; i < _pieces.size(); i++)
+    if (! _pieces[i].is_pure_ghost()) return false;
+
+  return true;
+}
+
+
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/CompositeJetStructure.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/CompositeJetStructure.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/CompositeJetStructure.hh	(revision 5)
@@ -0,0 +1,259 @@
+//STARTHEADER
+// $Id: CompositeJetStructure.hh 2684 2011-11-14 07:41:44Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_COMPOSITEJET_STRUCTURE_HH__
+#define __FASTJET_COMPOSITEJET_STRUCTURE_HH__
+
+#include <fastjet/PseudoJet.hh>
+#include <fastjet/PseudoJetStructureBase.hh>
+
+// to have access to the recombiner we need to include the JetDefinition header
+#include <fastjet/JetDefinition.hh>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+/// @ingroup extra_info
+/// \class CompositeJetStructure
+/// The structure for a jet made of pieces
+///
+/// This stores the vector of the pieces that make the jet and provide
+/// the methods to access them
+class CompositeJetStructure : public PseudoJetStructureBase{
+public:
+  // basic class info
+  //-------------------------------------------------------------------
+  /// default ctor
+  CompositeJetStructure() : _area_4vector_ptr(0){};
+
+  /// ctor with initialisation
+  CompositeJetStructure(const std::vector<PseudoJet> & initial_pieces, 
+			const JetDefinition::Recombiner * recombiner = 0);
+
+  /// default dtor
+  virtual ~CompositeJetStructure(){
+    if (_area_4vector_ptr) delete _area_4vector_ptr;
+  };
+
+  /// description
+  virtual std::string description() const;
+
+  // things reimplemented from the base structure
+  //-------------------------------------------------------------------
+  /// true unless the jet has no pieces (see also the description of
+  /// constituents() below)
+  virtual bool has_constituents() const;
+
+  /// return the constituents (i.e. the union of the constituents of each piece)
+  /// 
+  /// If any of the pieces has no constituent, the piece itself is
+  /// considered as a constituent
+  /// Note that as a consequence, a composite jet with no pieces will
+  /// have an empty vector as constituents
+  virtual std::vector<PseudoJet> constituents(const PseudoJet &jet) const;
+
+  //-------------------------------------------------------------------
+  // information related to the pieces of the jet
+  //-------------------------------------------------------------------
+  /// true if it has pieces (always the case)
+  virtual bool has_pieces(const PseudoJet & /*jet*/) const {return true;}
+
+  /// returns the pieces
+  virtual std::vector<PseudoJet> pieces(const PseudoJet &jet) const;
+
+  // area-related material
+
+  /// check if it has a well-defined area
+  virtual bool has_area() const;
+
+  /// return the jet (scalar) area.
+  virtual double area(const PseudoJet &reference) const;
+
+  /// return the error (uncertainty) associated with the determination
+  /// of the area of this jet.
+  ///
+  /// Be conservative: return the sum of the errors
+  virtual double area_error(const PseudoJet &reference) const;
+
+  /// return the jet 4-vector area.
+  virtual PseudoJet area_4vector(const PseudoJet &reference) const;
+
+  /// true if this jet is made exclusively of ghosts.
+  ///
+  /// In this case, it will be true if all pieces are pure ghost
+  virtual bool is_pure_ghost(const PseudoJet &reference) const;
+
+  // allow to modify the area information
+  // (for use in join())
+  //------------------------------------------------------------------------------
+  void set_area_information(PseudoJet *area_4vector_ptr){
+    _area_4vector_ptr = area_4vector_ptr;
+  }
+
+
+protected:
+  std::vector<PseudoJet> _pieces;  ///< the pieces building the jet
+  PseudoJet * _area_4vector_ptr;   ///< pointer to the 4-vector jet area
+};
+
+
+
+// helpers to "join" jets and produce a structure derived from
+// CompositeJetStructure
+//
+// The template structure T must have a constructor accepting as
+// argument the pieces and of the composite jet
+// ------------------------------------------------------------------------
+
+/// build a "CompositeJet" from the vector of its pieces with an
+/// extended structure of type T derived from CompositeJetStructure
+template<typename T> PseudoJet join(const std::vector<PseudoJet> & pieces){
+  PseudoJet result(0.0,0.0,0.0,0.0);
+  for (unsigned int i=0; i<pieces.size(); i++){
+    const PseudoJet it = pieces[i];
+    result += it;
+  }
+
+  T *cj_struct = new T(pieces);
+  result.set_structure_shared_ptr(SharedPtr<PseudoJetStructureBase>(cj_struct));
+
+  return result;
+}
+
+
+/// build a "CompositeJet" from a single PseudoJet with an extended
+/// structure of type T derived from CompositeJetStructure
+template<typename T> PseudoJet join(const PseudoJet & j1){
+  return join<T>(std::vector<PseudoJet>(1,j1));
+}
+
+/// build a "CompositeJet" from two PseudoJet with an extended
+/// structure of type T derived from CompositeJetStructure
+template<typename T> PseudoJet join(const PseudoJet & j1, const PseudoJet & j2){
+  std::vector<PseudoJet> pieces;
+  pieces.push_back(j1);
+  pieces.push_back(j2);
+  return join<T>(pieces);
+}
+
+/// build a "CompositeJet" from 3 PseudoJet with an extended structure
+/// of type T derived from CompositeJetStructure
+template<typename T> PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, 
+				    const PseudoJet & j3){
+  std::vector<PseudoJet> pieces;
+  pieces.push_back(j1);
+  pieces.push_back(j2);
+  pieces.push_back(j3);
+  return join<T>(pieces);
+}
+
+/// build a "CompositeJet" from 4 PseudoJet with an extended structure
+/// of type T derived from CompositeJetStructure
+template<typename T> PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, 
+				    const PseudoJet & j3, const PseudoJet & j4){
+  std::vector<PseudoJet> pieces;
+  pieces.push_back(j1);
+  pieces.push_back(j2);
+  pieces.push_back(j3);
+  pieces.push_back(j4);
+  return join<T>(pieces);
+}
+
+
+// the same as above with an additional argument for a
+// user-defined recombiner
+//
+// The template structure T must be derived from CompositeJetStructure
+// and have a constructor accepting as arguments the pieces and a
+// pointer to the recombination scheme
+// ----------------------------------------------------------------------
+
+/// build a "CompositeJet" from the vector of its pieces with an
+/// extended structure of type T derived from CompositeJetStructure
+template<typename T> PseudoJet join(const std::vector<PseudoJet> & pieces, 
+				    const JetDefinition::Recombiner & recombiner){
+  PseudoJet result;
+  if (pieces.size()>0){
+    result = pieces[0];
+    for (unsigned int i=1; i<pieces.size(); i++){
+      recombiner.plus_equal(result, pieces[i]);
+    }
+  }
+
+  T *cj_struct = new T(pieces, &recombiner);
+  result.set_structure_shared_ptr(SharedPtr<PseudoJetStructureBase>(cj_struct));
+
+  return result;
+}
+
+/// build a "CompositeJet" from a single PseudoJet with an extended
+/// structure of type T derived from CompositeJetStructure
+template<typename T> PseudoJet join(const PseudoJet & j1, 
+				    const JetDefinition::Recombiner & recombiner){
+  return join<T>(std::vector<PseudoJet>(1,j1), recombiner);
+}
+
+/// build a "CompositeJet" from two PseudoJet with an extended
+/// structure of type T derived from CompositeJetStructure
+template<typename T> PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, 
+				    const JetDefinition::Recombiner & recombiner){
+  std::vector<PseudoJet> pieces;
+  pieces.push_back(j1);
+  pieces.push_back(j2);
+  return join<T>(pieces, recombiner);
+}
+
+/// build a "CompositeJet" from 3 PseudoJet with an extended structure
+/// of type T derived from CompositeJetStructure
+template<typename T> PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, 
+				    const PseudoJet & j3, 
+				    const JetDefinition::Recombiner & recombiner){
+  std::vector<PseudoJet> pieces;
+  pieces.push_back(j1);
+  pieces.push_back(j2);
+  pieces.push_back(j3);
+  return join<T>(pieces, recombiner);
+}
+
+/// build a "CompositeJet" from 4 PseudoJet with an extended structure
+/// of type T derived from CompositeJetStructure
+template<typename T> PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, 
+				    const PseudoJet & j3, const PseudoJet & j4, 
+				    const JetDefinition::Recombiner & recombiner){
+  std::vector<PseudoJet> pieces;
+  pieces.push_back(j1);
+  pieces.push_back(j2);
+  pieces.push_back(j3);
+  pieces.push_back(j4);
+  return join<T>(pieces, recombiner);
+}
+
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
+
+#endif // __FASTJET_MERGEDJET_STRUCTURE_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/Dnn2piCylinder.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/Dnn2piCylinder.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/Dnn2piCylinder.cc	(revision 5)
@@ -0,0 +1,242 @@
+//STARTHEADER
+// $Id: Dnn2piCylinder.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef DROP_CGAL // in case we do not have the code for CGAL
+#include <set>
+#include "fastjet/internal/Dnn2piCylinder.hh"
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+/// initialiser...
+Dnn2piCylinder::Dnn2piCylinder(
+	const vector<EtaPhi> & input_points, 
+	const bool & ignore_nearest_is_mirror,
+	const bool & verbose) {
+  
+  _verbose = verbose;
+  _ignore_nearest_is_mirror = ignore_nearest_is_mirror;
+  vector<EtaPhi> plane_points;
+  vector<int>    plane_point_indices(input_points.size());
+  //plane_points.reserve(2*input_points.size());
+
+  for (unsigned int i=0; i < input_points.size(); i++) {
+    _RegisterCylinderPoint(input_points[i], plane_points);
+    plane_point_indices[i] = i;
+  }
+  
+  if (_verbose) cout << "============== Preparing _DNN" << endl;
+  _DNN = new DnnPlane(plane_points, verbose);
+
+
+  vector<int> updated_point_indices; // we'll not use information from this
+  _CreateNecessaryMirrorPoints(plane_point_indices,updated_point_indices);
+}
+
+
+//----------------------------------------------------------------------
+/// Actions here are similar to those in the
+/// Dnn3piCylinder::_RegisterCylinderPoint case, however here we do
+/// NOT create the mirror point -- instead we initialise the structure
+/// as if there were no need for the mirror point.
+///
+/// ADDITIONALLY push the cylinder_point onto the vector plane_points.
+void Dnn2piCylinder::_RegisterCylinderPoint (const EtaPhi & cylinder_point,
+					     vector<EtaPhi> & plane_points) {
+  double phi = cylinder_point.second;
+  assert(phi >= 0.0 && phi < 2*pi);
+  
+  // do main point
+  MirrorVertexInfo mvi;
+  mvi.main_index = _cylinder_index_of_plane_vertex.size();
+  _cylinder_index_of_plane_vertex.push_back(_mirror_info.size());
+  plane_points.push_back(cylinder_point);
+  mvi.mirror_index = INEXISTENT_VERTEX;
+  
+  // 
+  _mirror_info.push_back(mvi);
+}
+
+
+
+//----------------------------------------------------------------------
+/// For each plane point specified in the vector plane_indices,
+/// establish whether there is a need to create a mirror point
+/// according to the following criteria:
+///
+/// . phi < pi
+/// . mirror does not already exist
+/// . phi < NearestNeighbourDistance 
+///   (if this is not true then there is no way that its mirror point
+///   could have a nearer neighbour).
+///
+/// If conditions all hold, then create the mirror point, insert it
+/// into the _DNN structure, adjusting any nearest neighbours, and
+/// return the list of plane points whose nearest neighbours have
+/// changed (this will include the new neighbours that have just been
+/// added)
+void Dnn2piCylinder::_CreateNecessaryMirrorPoints(
+			  const vector<int> & plane_indices,
+			  vector<int> & updated_plane_points) {
+
+  vector<EtaPhi> new_plane_points;
+
+  for (size_t i = 0; i < plane_indices.size(); i++) {
+
+    int ip = plane_indices[i]; // plane index
+    EtaPhi position = _DNN->etaphi(ip);
+    double phi = position.second;
+
+    //BAD // require phi < pi
+    //BAD if (phi >= pi) {continue;}
+
+    // require absence of mirror
+    int ic = _cylinder_index_of_plane_vertex[ip];
+    if (_mirror_info[ic].mirror_index != INEXISTENT_VERTEX) {continue;}
+
+    //printf("%3d %3d %10.5f %10.5f %3d\n",ic, ip, phi, 
+    //	   _DNN->NearestNeighbourDistance(ip),_DNN->NearestNeighbourIndex(ip));
+
+
+    // check that we are sufficiently close to the border --
+    // i.e. closer than nearest neighbour distance. But RECALL:
+    // nearest neighbourDistance actually returns a squared distance
+    // (this was really stupid on our part -- caused considerable loss
+    // of time ... )
+    double nndist = _DNN->NearestNeighbourDistance(ip); 
+    if (phi*phi >= nndist && (twopi-phi)*(twopi-phi) >= nndist) {continue;}
+
+    // now proceed to prepare the point for addition
+    new_plane_points.push_back(_remap_phi(position));
+    _mirror_info[ic].mirror_index = _cylinder_index_of_plane_vertex.size();
+    _cylinder_index_of_plane_vertex.push_back(ic);
+  }
+
+  vector<int> indices_to_remove; // empty
+  vector<int> indices_added;     // will be filled as result of call
+  _DNN->RemoveAndAddPoints(indices_to_remove,new_plane_points,indices_added, 
+			   updated_plane_points);
+
+  // occasionally, addition of points might cause a change in the
+  // nearest neighbour of a point in the 0--pi range? (But should be
+  // impossible -- we add points beyond 2pi, so they can only be
+  // nearest neighbours of points in the range pi--2pi; there is one
+  // exception -- the nearest neighbour of one's self -- but in that
+  // case this will already have been discovered, so there should be
+  // nothing left to do). 
+
+  // To be on the safe side, check to see if we have updated points
+  // with phi<pi and no current mirror point. BUT: this check, as
+  // written, only makes sense when the mirror image was created only
+  // beyond 2pi, which is no longer the case. Only apparent
+  // alternative is to run separate insertions for beyond 2pi and
+  // below phi=0, with separate checks in the two cases. But, given
+  // that across a large number of recombinations and events in the
+  // old method (single mirror), we never ran into this problem, it's
+  // probably safe to assume that the arguments given above are OK! So
+  // comment out the check...
+  //NOTNEEDED for (size_t i = 0; i < updated_plane_points.size(); i++) {
+  //NOTNEEDED   int ip = updated_plane_points[i];
+  //NOTNEEDED   double phi  = _DNN->phi(ip);
+  //NOTNEEDED   int ic = _cylinder_index_of_plane_vertex[ip];
+  //NOTNEEDED   assert (!(phi < pi && _mirror_info[ic].mirror_index == INEXISTENT_VERTEX));
+  //NOTNEEDED }
+  // alternative recursive code
+  //vector<int> extra_updated_plane_points;
+  //_CreateNecessaryMirrorPoints(updated_plane_points,extra_updated_plane_points)
+  //updated_plane_points.push_back(extra_updated_plane_points);
+}
+
+
+
+//----------------------------------------------------------------------
+/// insertion and removal of points
+void Dnn2piCylinder::RemoveAndAddPoints(const vector<int> & indices_to_remove,
+				const vector<EtaPhi> & points_to_add,
+				vector<int> & indices_added,
+				vector<int> & indices_of_updated_neighbours) {
+
+  // translate from "cylinder" indices of points to remove to the
+  // plane indices of points to remove, bearing in mind that sometimes
+  // there are multple plane points to remove.
+  vector<int> plane_indices_to_remove;
+  for (unsigned int i=0; i < indices_to_remove.size(); i++) {
+    MirrorVertexInfo * mvi;
+    mvi = & _mirror_info[indices_to_remove[i]];
+    plane_indices_to_remove.push_back(mvi->main_index);
+    if (mvi->mirror_index != INEXISTENT_VERTEX) {
+      plane_indices_to_remove.push_back(mvi->mirror_index);
+    }
+  }
+
+  // given "cylinder" points to add get hold of the list of
+  // plane-points to add.
+  vector<EtaPhi> plane_points_to_add;
+  indices_added.clear();
+  for (unsigned int i=0; i < points_to_add.size(); i++) {
+    indices_added.push_back(_mirror_info.size());
+    _RegisterCylinderPoint(points_to_add[i], plane_points_to_add);
+  }
+
+  // now get the hard work done (note that we need to supply the
+  // plane_indices_added vector but that we will not actually check
+  // its contents in any way -- the indices_added that is actually
+  // returned has been calculated above).
+  vector<int> updated_plane_neighbours, plane_indices_added;
+  _DNN->RemoveAndAddPoints(plane_indices_to_remove, plane_points_to_add,
+			     plane_indices_added, updated_plane_neighbours);
+
+  vector<int> extra_updated_plane_neighbours;
+  _CreateNecessaryMirrorPoints(updated_plane_neighbours,
+			       extra_updated_plane_neighbours);
+
+  // extract, from the updated_plane_neighbours, and
+  // extra_updated_plane_neighbours, the set of cylinder neighbours
+  // that have changed
+  set<int> index_set;
+  unsigned int i;
+  for (i=0; i < updated_plane_neighbours.size(); i++) {
+    index_set.insert(
+       _cylinder_index_of_plane_vertex[updated_plane_neighbours[i]]);}
+  for (i=0; i < extra_updated_plane_neighbours.size(); i++) {
+    index_set.insert(
+       _cylinder_index_of_plane_vertex[extra_updated_plane_neighbours[i]]);}
+
+  // decant the set into the vector that needs to be returned
+  indices_of_updated_neighbours.clear();
+  for (set<int>::iterator iter = index_set.begin(); 
+       iter != index_set.end(); iter++) {
+    indices_of_updated_neighbours.push_back(*iter);
+  }
+}
+
+FASTJET_END_NAMESPACE
+
+#endif //  DROP_CGAL 
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/Dnn3piCylinder.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/Dnn3piCylinder.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/Dnn3piCylinder.cc	(revision 5)
@@ -0,0 +1,159 @@
+//STARTHEADER
+// $Id: Dnn3piCylinder.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef DROP_CGAL // in case we do not have the code for CGAL
+#include <set>
+#include "fastjet/internal/Dnn3piCylinder.hh"
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+/// initialiser...
+Dnn3piCylinder::Dnn3piCylinder(
+	const vector<EtaPhi> & input_points, 
+	const bool & ignore_nearest_is_mirror,
+	const bool & verbose) {
+  
+  _verbose = verbose;
+  _ignore_nearest_is_mirror = ignore_nearest_is_mirror;
+  vector<EtaPhi> plane_points;
+  //plane_points.reserve(2*input_points.size());
+
+  for (unsigned int i=0; i < input_points.size(); i++) {
+    _RegisterCylinderPoint(input_points[i], plane_points);
+  }
+
+  if (_verbose) cout << "============== Preparing _DNN" << endl;
+  _DNN = new DnnPlane(plane_points, verbose);
+}
+
+
+//----------------------------------------------------------------------
+/// What on earth does this do?
+///
+/// Example: last true "cylinder" index was 15
+///          last plane index was 23
+/// 
+/// Then: _cylinder_index_of_plane_vertex.size() = 24 and 
+///       _mirror_info.size() = 16
+///
+/// IF cylinder_point's phi < pi then
+///   create:  _mirror_info[16] = (main_index = 24, mirror_index=25) 
+///            _cylinder_index_of_plane_vertex[24] = 16
+///            _cylinder_index_of_plane_vertex[25] = 16
+/// ELSE
+///   create:  _mirror_info[16] = (main_index = 24, mirror_index=INEXISTENT..) 
+///            _cylinder_index_of_plane_vertex[24] = 16
+///
+/// ADDITIONALLY push the cylinder_point (and if it exists the mirror
+/// copy) onto the vector plane_points.
+void Dnn3piCylinder::_RegisterCylinderPoint (const EtaPhi & cylinder_point,
+					     vector<EtaPhi> & plane_points) {
+  double phi = cylinder_point.second;
+  assert(phi >= 0.0 && phi < 2*pi);
+  
+  // do main point
+  MirrorVertexInfo mvi;
+  mvi.main_index = _cylinder_index_of_plane_vertex.size();
+  _cylinder_index_of_plane_vertex.push_back(_mirror_info.size());
+  plane_points.push_back(cylinder_point);
+  
+  // do mirror point if need be
+  if (phi < pi) {
+    mvi.mirror_index = _cylinder_index_of_plane_vertex.size();
+    _cylinder_index_of_plane_vertex.push_back(_mirror_info.size());
+    plane_points.push_back(_remap_phi(cylinder_point));
+  } else {
+    mvi.mirror_index = INEXISTENT_VERTEX;
+  }
+  
+  // 
+  _mirror_info.push_back(mvi);
+}
+
+
+//----------------------------------------------------------------------
+/// insertion and removal of points
+void Dnn3piCylinder::RemoveAndAddPoints(const vector<int> & indices_to_remove,
+				const vector<EtaPhi> & points_to_add,
+				vector<int> & indices_added,
+				vector<int> & indices_of_updated_neighbours) {
+
+  // translate from "cylinder" indices of points to remove to the
+  // plane indices of points to remove, bearing in mind that sometimes
+  // there are multple plane points to remove.
+  vector<int> plane_indices_to_remove;
+  for (unsigned int i=0; i < indices_to_remove.size(); i++) {
+    MirrorVertexInfo * mvi;
+    mvi = & _mirror_info[indices_to_remove[i]];
+    plane_indices_to_remove.push_back(mvi->main_index);
+    if (mvi->mirror_index != INEXISTENT_VERTEX) {
+      plane_indices_to_remove.push_back(mvi->mirror_index);
+    }
+  }
+
+  // given "cylinder" points to add get hold of the list of
+  // plane-points to add.
+  vector<EtaPhi> plane_points_to_add;
+  indices_added.clear();
+  for (unsigned int i=0; i < points_to_add.size(); i++) {
+    indices_added.push_back(_mirror_info.size());
+    _RegisterCylinderPoint(points_to_add[i], plane_points_to_add);
+  }
+
+  // now get the hard work done (note that we need to supply the
+  // plane_indices_added vector but that we will not actually check
+  // its contents in any way -- the indices_added that is actually
+  // returned has been calculated above).
+  vector<int> updated_plane_neighbours, plane_indices_added;
+  _DNN->RemoveAndAddPoints(plane_indices_to_remove, plane_points_to_add,
+			     plane_indices_added, updated_plane_neighbours);
+
+  // extract, from the updated_plane_neighbours, the set of cylinder
+  // neighbours that have changed
+  set<int> index_set;
+  unsigned int i;
+  for (i=0; i < updated_plane_neighbours.size(); i++) {
+    index_set.insert(
+       _cylinder_index_of_plane_vertex[updated_plane_neighbours[i]]);}
+
+  // decant the set into the vector that needs to be returned
+  indices_of_updated_neighbours.clear();
+  for (set<int>::iterator iter = index_set.begin(); 
+       iter != index_set.end(); iter++) {
+    indices_of_updated_neighbours.push_back(*iter);
+  }
+}
+
+
+FASTJET_END_NAMESPACE
+
+#endif //  DROP_CGAL 
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/Dnn4piCylinder.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/Dnn4piCylinder.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/Dnn4piCylinder.cc	(revision 5)
@@ -0,0 +1,93 @@
+//STARTHEADER
+// $Id: Dnn4piCylinder.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef DROP_CGAL // in case we do not have the code for CGAL
+#include <set>
+#include "fastjet/internal/Dnn4piCylinder.hh"
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+/// initialiser...
+Dnn4piCylinder::Dnn4piCylinder(
+	const vector<EtaPhi> & input_points, const bool & verbose) {
+  
+  _verbose = verbose;
+  vector<EtaPhi> copied_points(input_points.size());
+  for (unsigned int i=0; i < input_points.size(); i++) {
+    double phi = input_points[i].second;
+    assert(phi >= 0.0 && phi < 2*pi);
+    copied_points[i] = _remap_phi(input_points[i]);
+  }
+
+  if (_verbose) cout << "============== Preparing _DNN1" << endl;
+  _DNN1 = new DnnPlane(input_points, verbose);
+  if (_verbose) cout << "============== Preparing _DNN2" << endl;
+  _DNN2 = new DnnPlane(copied_points, verbose);
+}
+
+
+//----------------------------------------------------------------------
+/// insertion and removal of points
+void Dnn4piCylinder::RemoveAndAddPoints(const vector<int> & indices_to_remove,
+				const vector<EtaPhi> & points_to_add,
+				vector<int> & indices_added,
+				vector<int> & indices_of_updated_neighbours) {
+  
+  vector<int> indices1, indices2;
+  
+  _DNN1->RemoveAndAddPoints(indices_to_remove,points_to_add,
+				      indices_added,indices1);
+
+  // create a vector with the remapped points (pi..3pi)
+  vector<EtaPhi> remapped_points(points_to_add.size());
+  for (size_t i = 0; i < points_to_add.size(); i++) {
+    remapped_points[i] = _remap_phi(points_to_add[i]);
+  }
+  _DNN2->RemoveAndAddPoints(indices_to_remove, remapped_points, 
+				      indices_added,indices2);
+  
+  // merge the two sequences of updated vertices, avoiding double entries
+  // of vertices with the same index
+  set<int> index_set;
+  unsigned int i;
+  for (i=0; i < indices1.size(); i++) {index_set.insert(indices1[i]);}
+  for (i=0; i < indices2.size(); i++) {index_set.insert(indices2[i]);}
+
+  indices_of_updated_neighbours.clear();
+  for (set<int>::iterator iter = index_set.begin(); 
+       iter != index_set.end(); iter++) {
+    indices_of_updated_neighbours.push_back(*iter);
+  }
+}
+
+FASTJET_END_NAMESPACE
+
+#endif //  DROP_CGAL 
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/DnnPlane.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/DnnPlane.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/DnnPlane.cc	(revision 5)
@@ -0,0 +1,355 @@
+//STARTHEADER
+// $Id: DnnPlane.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef DROP_CGAL // in case we do not have the code for CGAL
+
+#include<set>
+#include<list>
+#include "fastjet/internal/DnnPlane.hh"
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+
+/// Initialiser from a set of points on an Eta-Phi plane, where both
+/// eta and phi can have arbitrary ranges
+DnnPlane::DnnPlane(const vector<EtaPhi> & input_points, 
+		   const bool & verbose ) {
+
+  _verbose = verbose;
+  int n = input_points.size();
+  
+  // construct Voronoi diagram in such a way as to get the vertex handles
+  // and remember to set CGAL info with the index of the vertex
+  SuperVertex sv;
+  for (int i = 0; i < n; i++) {
+    sv.vertex = 
+       _TR.insert(Point(input_points[i].first, input_points[i].second));
+
+    // we are not up to dealing with coincident vertices, so make 
+    // sure the user knows!
+    _CrashIfVertexPresent(sv.vertex, i);
+    
+    // we need to assicate an index to each vertex -- thus when we get
+    // a vertex (e.g. as a nearest neighbour) from CGAL, we will be
+    // able to figure out which particle it corresponded to.
+    sv.vertex->info() = i;
+    _supervertex.push_back(sv);    
+  }
+
+  // label infinite vertex info with negative index 
+  _TR.infinite_vertex()->info() = INFINITE_VERTEX;
+
+  // set up the structure that holds nearest distances and neighbours
+  for (int j = 0; j < n; j++) {_SetNearest(j);}
+
+}
+
+
+//----------------------------------------------------------------------
+/// Crashes if the given vertex handle already exists. Otherwise
+/// it does the bookkeeping for future such tests
+void DnnPlane::_CrashIfVertexPresent(
+	const Vertex_handle & vertex, const int & its_index) {
+  if (!_crash_on_coincidence) return;
+
+  // vertices that do not have the same geometric position as any
+  // other vertex so far added have info().val() == NEW_VERTEX -- this
+  // is ensured by the InitialisedInt class, which forms the "info"
+  // part of our
+  // CGAL::Triangulation_vertex_base_with_info_2<InitialisedInt,K>
+  //
+  // If the vertex coincides with one that already exists, then
+  // info().val() it's info().val() will have been updated (in
+  // DNN:DNN) to be equal to a vertex "index".
+  if (vertex->info().val() != NEW_VERTEX) {
+    ostringstream err;
+    err << "ERROR in DnnPlane::_CrashIfVertexPresent"
+	 <<endl << "Point "<<its_index<<" coincides with point "
+	 <<vertex->info().val() << endl;
+    throw DnnError(err.str());
+  } 
+}
+
+
+//----------------------------------------------------------------------
+/// remove the points labelled by the vector indices_to_remove, and
+/// add the points specified by the vector points_to_add
+/// (corresponding indices will be calculated automatically); the
+/// idea behind this routine is that the points to be added will
+/// somehow be close to the one or other of the points being removed
+/// and this can be used by the implementation to provide hints for
+/// inserting the new points in whatever structure it is using.  In a
+/// kt-algorithm the points being added will be a result of a
+/// combination of the points to be removed -- hence the proximity
+/// is (more or less) guaranteed.
+void DnnPlane::RemoveAndAddPoints(
+			  const vector<int> & indices_to_remove,
+			  const vector<EtaPhi> & points_to_add,
+			  vector<int> & indices_added,
+			  vector<int> & indices_of_updated_neighbours) {
+
+
+  // build set of UNION of Voronoi neighbours of a pair of nearest
+  // neighbours
+  set<int> NeighbourUnion;
+  // later on it will be convenient to have access to a set (rather
+  // than vector) of indices being removed
+  set<int> indices_removed;
+
+  // for each of the indices to be removed add the voronoi neighbourhood to
+  // the NeighbourUnion set.
+  for (size_t ir = 0; ir < indices_to_remove.size(); ir++) {
+    int index = indices_to_remove[ir];
+    indices_removed.insert(index);
+    if (_verbose) cout << " Starting  RemoveAndAddPoints" << endl; 
+    if (_verbose) cout << " point " << index << endl;			 
+    // have a circulators that will go round the Voronoi neighbours of
+    // _supervertex[index1].vertex
+    Vertex_circulator vc = _TR.incident_vertices(_supervertex[index].vertex);
+    Vertex_circulator done = vc;
+    do  {
+      // if a neighbouring vertex not the infinite vertex, then add it
+      // to our union of neighbouring vertices.
+      if (_verbose) cout << "examining " << vc->info().val() << endl;
+      if (vc->info().val() != INFINITE_VERTEX) {
+	// NB: from it=1 onwards occasionally it might already have
+	// been inserted -- but double insertion still leaves only one
+	// copy in the set, so there's no problem
+	NeighbourUnion.insert(vc->info().val());
+	if (_verbose) cout << "inserted " << vc->info().val() << endl;
+      } 
+    } while (++vc != done);
+  }
+  
+  if (_verbose) {
+    set<int>::iterator it = NeighbourUnion.begin();
+    cout << "Union of neighbours of combined points" << endl;
+    for ( ; it != NeighbourUnion.end(); ++it ) {
+      cout << *it << endl;
+    }
+  }
+
+  // update set, triangulation and supervertex info
+  for (size_t ir = 0; ir < indices_to_remove.size(); ir++) {
+    int index = indices_to_remove[ir];
+
+    // NeighbourUnion should not contain the points to be removed
+    // (because later we will assume they still exist).
+    NeighbourUnion.erase(indices_to_remove[ir]);
+    
+    // points to be removed should also be eliminated from the
+    // triangulation and the supervertex structure should be updated
+    // to reflect the fact that the points are no longer valid.
+    _TR.remove(_supervertex[index].vertex);
+    _supervertex[index].vertex = NULL;
+  }
+
+  // add new point: give a "hint" to the inserter that
+  // the new point should be added close to old points -- the easiest way 
+  // of getting this is to take a point from the NeighbourUnion AFTER we have
+  // removed point1, point2, and to get one of its incident faces.
+  // 
+  // This hinting improves speed by c. 25% for 10^4 points because it
+  // avoids the need for a costly (sqrt{N}) location step (at least
+  // with a non-hierarchical triangulation -- with a hierarchical one,
+  // this step could be done away with, though there will still be a
+  // cost of O(ln N) to pay.
+  // 
+  // For some reason inserting the point before the two removals
+  // slows things down by c. 25%. This importance of the order
+  // is not understood.
+  //
+  // At some point it might be worth trying to select the "nearest"
+  // of the various points in the neighbour union to avoid large 
+  // steps in cases where we have 0..2pi periodicity and the first member
+  // of the neighbour union happens to be on the wrong side.
+  Face_handle face;
+  if (indices_to_remove.size() > 0) {
+    // face can only be found if there were points to remove in first place
+    face = _TR.incident_faces(
+   	                   _supervertex[*NeighbourUnion.begin()].vertex);}
+  // make sure the output arrays are empty
+  indices_added.clear();
+  indices_of_updated_neighbours.clear();
+  for (size_t ia = 0; ia < points_to_add.size(); ia++) {
+    SuperVertex sv;
+    _supervertex.push_back(sv);
+    int index = _supervertex.size()-1;
+    indices_added.push_back(index);
+
+    if (indices_to_remove.size() > 0) {
+      // be careful of using face (for location hinting) only when it exists
+      _supervertex[index].vertex = _TR.insert(Point(points_to_add[ia].first, 
+				  points_to_add[ia].second),face);}
+    else { 
+      _supervertex[index].vertex = _TR.insert(Point(points_to_add[ia].first, 
+						    points_to_add[ia].second));
+    }
+    // we are not up to dealing with coincident vertices, so make 
+    // sure the user knows!
+    _CrashIfVertexPresent(_supervertex[index].vertex, index);
+    _supervertex[index].vertex->info() = index;
+    
+    // first find nearest neighbour of "newpoint" (shorthand for
+    // _supervertex[index].vertex); while we're at it, for each of the
+    // voronoi neighbours, "D", of newpoint, examine whether newpoint is
+    // closer to "D" than D's current nearest neighbour -- when this
+    // occurs, put D into indices_of_updated_neighbours.
+    // 
+    // manually put newpoint on indices_of_updated_neighbours
+    indices_of_updated_neighbours.push_back(index);
+    _SetAndUpdateNearest(index, indices_of_updated_neighbours);
+  }
+
+  // for Voronoi neighbours j of any of the removed points for which
+  // one of those removed points was the nearest neighbour,
+  // redetermine the nearest neighbour of j and add j onto the vector
+  // of indices_of_updated_neighbours.
+  set<int>::iterator it2 = NeighbourUnion.begin();
+  for ( ; it2 != NeighbourUnion.end(); ++it2 ) {
+    int j = *it2;
+    // the if avoids the vertex at infinity, which gets a negative index
+    if( j != INFINITE_VERTEX ) {
+      // this is where we check if the nearest neighbour of j was one
+      // of the removed points
+      if (indices_removed.count(_supervertex[j].NNindex)) {
+	if (_verbose) cout << "j " << j << endl;
+	_SetNearest(j);
+	indices_of_updated_neighbours.push_back(j);
+	if (_verbose) cout << "NN of " << j << " : " 
+			  << _supervertex[j].NNindex
+	                  << ", dist = " << _supervertex[j].NNdistance <<endl;
+      }
+    }
+  }
+
+}
+
+
+//----------------------------------------------------------------------
+/// Determines the index and distance of the nearest neighbour to 
+/// point j and puts the information into the _supervertex entry for j.
+void DnnPlane::_SetNearest (const int & j) {
+  Vertex_handle current = _supervertex[j].vertex;
+  Vertex_circulator vc = _TR.incident_vertices(current);
+  Vertex_circulator done = vc;
+  double dist;
+  double mindist = HUGE_DOUBLE; // change this to "HUGE" or max_double?
+  Vertex_handle nearest = _TR.infinite_vertex();
+
+  // when there is only one finite point left in the triangulation, 
+  // there are no triangles. Presumably this is why voronoi returns
+  // NULL for the incident vertex circulator. Check if this is
+  // happening before circulating over it... (Otherwise it crashes
+  // when looking for neighbours of last point)
+  if (vc != NULL) do { 
+    if ( vc->info().val() != INFINITE_VERTEX) {
+      // find distance between j and its Voronoi neighbour (vc)
+      if (_verbose) cout << current->info().val() << " " << vc->info().val() << endl;
+      dist = _euclid_distance(current->point(), vc->point());
+      // check if j is closer to vc than vc's currently registered
+      // nearest neighbour (and update things if it is)
+      if (dist < mindist) {
+	mindist = dist; nearest = vc; 
+	if (_verbose) cout << "nearer ";
+      } 
+      if (_verbose) cout << vc->point() << "; "<< dist << endl;
+    }
+  } while (++vc != done); // move on to next Voronoi neighbour
+  // set j's supervertex info about nearest neighbour
+  _supervertex[j].NNindex = nearest->info().val();
+  _supervertex[j].NNdistance = mindist;
+}
+
+//----------------------------------------------------------------------
+/// Determines and stores the nearest neighbour of j, and where
+/// necessary update the nearest-neighbour info of Voronoi neighbours
+/// of j;
+///
+/// For each voronoi neighbour D of j if the distance between j and D
+/// is less than D's own nearest neighbour, then update the
+/// nearest-neighbour info in D; push D's index onto 
+/// indices_of_updated_neighbours
+///
+/// Note that j is NOT pushed onto indices_of_updated_neighbours --
+/// if you want it there, put it there yourself.
+///
+/// NB: note that we have _SetAndUpdateNearest as a completely
+///     separate routine from _SetNearest because we want to
+///     use one single ciruclation over voronoi neighbours to find the
+///     nearest neighbour and to update the voronoi neighbours if need
+///     be.
+void DnnPlane::_SetAndUpdateNearest(
+			  const int & j, 
+			  vector<int> & indices_of_updated_neighbours) {
+
+  Vertex_handle current = _supervertex[j].vertex;
+  Vertex_circulator vc = _TR.incident_vertices(current);
+  Vertex_circulator done = vc;
+  double dist;
+  double mindist = HUGE_DOUBLE; // change this to "HUGE" or max_double?
+  Vertex_handle nearest = _TR.infinite_vertex();
+
+  // when there is only one finite point left in the triangulation, 
+  // there are no triangles. Presumably this is why voronoi returns
+  // NULL for the incident vertex circulator. Check if this is
+  // happening before circulating over it... (Otherwise it crashes
+  // when looking for neighbours of last point)
+  if (vc != NULL) do { 
+    if (vc->info().val() != INFINITE_VERTEX) {
+      if (_verbose) cout << current->info().val() << " " << vc->info().val() << endl;
+      // find distance between j and its Voronoi neighbour (vc)
+      dist = _euclid_distance(current->point(), vc->point());
+      // update the mindist if we are closer than anything found so far
+      if (dist < mindist) {
+	mindist = dist; nearest = vc; 
+	if (_verbose) cout << "nearer ";
+      } 
+      // find index corresponding to vc for easy manipulation
+      int vcindx = vc->info().val();
+      if (_verbose) cout << vc->point() << "; "<< dist << endl;
+      // check if j is closer to vc than vc's currently registered
+      // nearest neighbour (and update things if it is)
+      if (dist < _supervertex[vcindx].NNdistance) {
+	if (_verbose) cout << vcindx << "'s NN becomes " << current->info().val() << endl;
+	_supervertex[vcindx].NNdistance = dist;
+	_supervertex[vcindx].NNindex = j;
+	indices_of_updated_neighbours.push_back(vcindx);
+      }
+    }
+  } while (++vc != done); // move on to next Voronoi neighbour
+  // set j's supervertex info about nearest neighbour
+  _supervertex[j].NNindex = nearest->info().val();
+  _supervertex[j].NNdistance = mindist;
+}
+
+FASTJET_END_NAMESPACE
+
+#endif //  DROP_CGAL
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/Error.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/Error.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/Error.cc	(revision 5)
@@ -0,0 +1,86 @@
+//STARTHEADER
+// $Id: Error.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/Error.hh"
+#include "fastjet/config.h"
+#include <sstream>
+
+// printing the stack would need execinfo
+#ifdef FASTJET_HAVE_EXECINFO_H
+#include <execinfo.h>
+#include <cstdlib>
+#endif
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+
+bool Error::_print_errors = true;
+bool Error::_print_backtrace = false;
+ostream * Error::_default_ostr = & cerr;
+
+Error::Error(const std::string & message_in) {
+  _message = message_in; 
+  if (_print_errors && _default_ostr){
+    ostringstream oss;
+    oss << "fastjet::Error:  "<< message_in << endl;
+
+    // only print the stack if execinfo is available and stack enabled
+#ifdef FASTJET_HAVE_EXECINFO_H
+    if (_print_backtrace){
+      void * array[10];
+      char ** messages;
+ 
+      int size = backtrace(array, 10);
+      messages = backtrace_symbols(array, size);
+      
+      oss << "stack:" << endl;
+      for (int i = 1; i < size && messages != NULL; ++i){
+	oss << "  #" << i << ": " << messages[i] << endl;
+      }
+      free(messages);
+    }
+#endif
+
+    *_default_ostr << oss.str();
+    // get something written to file even 
+    // if the program aborts
+    _default_ostr->flush(); 
+
+    // // output error message either to cerr or to the user-set stream
+    // if (_default_ostr) { *_default_ostr << oss.str();
+    //                       // get something written to file even 
+    // 			  // if the program aborts
+    //                       _default_ostr->flush(); }
+    // else               { std::cerr << oss.str(); }
+    
+  }
+}
+
+FASTJET_END_NAMESPACE
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/Error.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/Error.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/Error.hh	(revision 5)
@@ -0,0 +1,83 @@
+#ifndef __FASTJET_ERROR_HH__
+#define __FASTJET_ERROR_HH__
+
+//STARTHEADER
+// $Id: Error.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include<iostream>
+#include<string>
+#include "fastjet/internal/base.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+/// @ingroup error_handling
+/// \class Error
+/// base class corresponding to errors that can be thrown by FastJet
+class Error {
+public:
+  /// default constructors
+  Error() {}
+
+  /// ctor from an error message
+  ///   \param message to be printed
+  /// Note: in addition to the error message, one can choose to print the
+  /// backtrace (showing the last few calls before the error) by 
+  /// using set_print_backtrace(true). The default is "false".
+  Error(const std::string & message);
+
+  /// virtual dummy dtor
+  virtual ~Error() {}
+
+  /// the error message
+  std::string message() const {return _message;}
+
+  /// controls whether the error message (and the backtrace, if its printing is enabled) 
+  /// is printed out or not
+  static void set_print_errors(bool print_errors) {_print_errors = print_errors;}
+
+  /// controls whether the backtrace is printed out with the error message or not.
+  /// The default is "false".
+  static void set_print_backtrace(bool enabled) {_print_backtrace = enabled;}
+
+  /// sets the default output stream for all errors; by default
+  /// cerr; if it's null then error output is suppressed.
+  static void set_default_stream(std::ostream * ostr) {
+    _default_ostr = ostr;
+  }
+
+private:
+  std::string _message;                ///< error message
+  static bool _print_errors;           ///< do we print anything?
+  static bool _print_backtrace;        ///< do we print the backtrace?
+  static std::ostream * _default_ostr; ///< the output stream (cerr if not set)
+};
+
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_ERROR_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/FunctionOfPseudoJet.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/FunctionOfPseudoJet.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/FunctionOfPseudoJet.cc	(revision 5)
@@ -0,0 +1,159 @@
+//STARTHEADER
+// $Id: FunctionOfPseudoJet.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include <fastjet/FunctionOfPseudoJet.hh>
+#include <string>
+#include <sstream>
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE
+
+// //----------------------------------------------------------------------
+// /// helper for the selector "FunctionOfPJ(jet) > ref"
+// class SW_FofPJ_larger : public SelectorWorker {
+// public:
+//   /// ctor with specification of the number of objects to keep
+//   SW_FofPJ_larger(const FunctionOfPseudoJet<double> & fn, const double &ref)
+//     : _fn(fn), _ref(ref){}
+// 
+//   /// return true if the jet is a pure-ghost jet
+//   virtual bool pass(const PseudoJet & jet) const { return _fn(jet) > _ref; }
+//   
+//   /// returns a description of the worker
+//   virtual string description() const { 
+//     ostringstream oss;
+//     oss << "(" << _fn.description() << " > " << _ref << ")";
+//     return oss.str();
+//   }
+// 
+// protected:
+//   const FunctionOfPseudoJet<double> & _fn;
+//   double _ref;
+// };
+// 
+// 
+// // select objects that are (or are only made of) ghosts
+// Selector operator >(const FunctionOfPseudoJet<double> & fn, const double & ref){
+//   return Selector(new SW_FofPJ_larger(fn, ref));
+// }
+// 
+// 
+// 
+// //----------------------------------------------------------------------
+// /// helper for the selector "FunctionOfPJ(jet) < ref"
+// class SW_FofPJ_smaller : public SelectorWorker {
+// public:
+//   /// ctor with specification of the number of objects to keep
+//   SW_FofPJ_smaller(const FunctionOfPseudoJet<double> & fn, const double &ref)
+//     : _fn(fn), _ref(ref){}
+// 
+//   /// return true if the jet is a pure-ghost jet
+//   virtual bool pass(const PseudoJet & jet) const { return _fn(jet) < _ref; }
+//   
+//   /// returns a description of the worker
+//   virtual string description() const { 
+//     ostringstream oss;
+//     oss << "(" << _fn.description() << " < " << _ref << ")";
+//     return oss.str();
+//   }
+// 
+// protected:
+//   const FunctionOfPseudoJet<double> & _fn;
+//   double _ref;
+// };
+// 
+// 
+// // select objects that are (or are only made of) ghosts
+// Selector operator <(const FunctionOfPseudoJet<double> & fn, const double & ref){
+//   return Selector(new SW_FofPJ_smaller(fn, ref));
+// }
+// 
+// 
+// //----------------------------------------------------------------------
+// /// helper for the selector "FunctionOfPJ(jet) >= ref"
+// class SW_FofPJ_larger_equal : public SelectorWorker {
+// public:
+//   /// ctor with specification of the number of objects to keep
+//   SW_FofPJ_larger_equal(const FunctionOfPseudoJet<double> & fn, const double &ref)
+//     : _fn(fn), _ref(ref){}
+// 
+//   /// return true if the jet is a pure-ghost jet
+//   virtual bool pass(const PseudoJet & jet) const { return _fn(jet) >= _ref; }
+//   
+//   /// returns a description of the worker
+//   virtual string description() const { 
+//     ostringstream oss;
+//     oss << "(" << _fn.description() << " >= " << _ref << ")";
+//     return oss.str();
+//   }
+// 
+// protected:
+//   const FunctionOfPseudoJet<double> & _fn;
+//   double _ref;
+// };
+// 
+// 
+// // select objects that are (or are only made of) ghosts
+// Selector operator >=(const FunctionOfPseudoJet<double> & fn, const double & ref){
+//   return Selector(new SW_FofPJ_larger_equal(fn, ref));
+// }
+// 
+// 
+// 
+// //----------------------------------------------------------------------
+// /// helper for the selector "FunctionOfPJ(jet) <= ref"
+// class SW_FofPJ_smaller_equal : public SelectorWorker {
+// public:
+//   /// ctor with specification of the number of objects to keep
+//   SW_FofPJ_smaller_equal(const FunctionOfPseudoJet<double> & fn, const double &ref)
+//     : _fn(fn), _ref(ref){}
+// 
+//   /// return true if the jet is a pure-ghost jet
+//   virtual bool pass(const PseudoJet & jet) const { return _fn(jet) <= _ref; }
+//   
+//   /// returns a description of the worker
+//   virtual string description() const { 
+//     ostringstream oss;
+//     oss << "(" << _fn.description() << " <= " << _ref << ")";
+//     return oss.str();
+//   }
+// 
+// protected:
+//   const FunctionOfPseudoJet<double> & _fn;
+//   double _ref;
+// };
+// 
+// 
+// // select objects that are (or are only made of) ghosts
+// Selector operator <=(const FunctionOfPseudoJet<double> & fn, const double & ref){
+//   return Selector(new SW_FofPJ_smaller_equal(fn, ref));
+// }
+// 
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/FunctionOfPseudoJet.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/FunctionOfPseudoJet.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/FunctionOfPseudoJet.hh	(revision 5)
@@ -0,0 +1,122 @@
+#ifndef __FASTJET_FUNCTION_OF_PSEUDOJET_HH__
+#define __FASTJET_FUNCTION_OF_PSEUDOJET_HH__
+
+//STARTHEADER
+// $Id: FunctionOfPseudoJet.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include <fastjet/PseudoJet.hh>
+#include <fastjet/Selector.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+/// \class FunctionOfPseudoJet
+/// base class providing interface for a generic function of a PseudoJet
+///
+/// This class serves as a base class to provide a standard interface
+/// for a function that returns an object of a given (templated) type
+/// that depends on a PseudoJet argument. The rationale for using a
+/// class (rather than a pointer to a function) is that a class can be
+/// constructed with (and store) additional arguments.
+template<typename TOut>
+class FunctionOfPseudoJet{
+public:
+  /// default ctor
+  FunctionOfPseudoJet(){}
+
+  /// ctor that creates a constant function
+  FunctionOfPseudoJet(const TOut &constant_value);
+
+  /// default dtor (virtual to allow safe polymorphism)
+  virtual ~FunctionOfPseudoJet(){}
+
+  /// returns a description of the function (an empty string by
+  /// default)
+  virtual std::string description() const{ return "";}
+
+  /// the action of the function
+  /// this _has_ to be overloaded in derived classes
+  ///  \param pj   the PseudoJet input to the function
+  virtual TOut result(const PseudoJet &pj) const = 0;
+
+  /// apply the function using the "traditional" () operator.
+  /// By default, this just calls the apply(...) method above.
+  ///  \param pj   the PseudoJet input to the function
+  TOut operator()(const PseudoJet &pj) const { return result(pj);}
+
+  /// apply the function on a vector of PseudoJet, returning a vector
+  /// of the results.
+  /// This just calls apply on every PseudoJet in the vector.
+  ///  \param pjs  the vector of PseudoJet inputs to the function
+  std::vector<TOut> operator()(const std::vector<PseudoJet> &pjs) const {
+    std::vector<TOut> res(pjs.size());
+    for (unsigned int i=0; i<pjs.size(); i++)
+      res[i] = result(pjs[i]);
+    return res;
+  }
+};
+
+// The following functions will not be for FJ3.0, because passing a
+// reference does not work when the argument is a temporary, which can
+// lead to hard-to-diagnose run-time errors. A workaround is to to
+// have a pointer rather than a reference as argument, since this
+// provides a clearer signal to the user that the object must remain
+// in scope.
+//
+//
+// // Selectors created from the ordering between a FunctionOfPseudoJet
+// // and a constant
+// //----------------------------------------------------------------------
+// 
+// /// 'larger than' operator
+// ///
+// /// Select jets for which the given function returns a result larger
+// /// than the specified constant
+// Selector operator >(const FunctionOfPseudoJet<double> & fn, const double & cut);
+// 
+// /// 'smaller than' operator
+// ///
+// /// Select jets for which the given function returns a result smaller
+// /// than the specified constant
+// Selector operator <(const FunctionOfPseudoJet<double> & fn, const double & cut);
+// 
+// /// 'larger or equal' operator
+// ///
+// /// Select jets for which the given function returns a result larger or equal 
+// /// to the specified constant
+// Selector operator >=(const FunctionOfPseudoJet<double> & fn, const double & cut);
+// 
+// /// 'smaller or equal' operator
+// ///
+// /// Select jets for which the given function returns a result smaller or equal
+// /// to the specified constant
+// Selector operator <=(const FunctionOfPseudoJet<double> & fn, const double & cut);
+
+
+FASTJET_END_NAMESPACE
+
+#endif  // __FASTJET_FUNCTION_OF_PSEUDOJET_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/GhostedAreaSpec.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/GhostedAreaSpec.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/GhostedAreaSpec.cc	(revision 5)
@@ -0,0 +1,178 @@
+//STARTHEADER
+// $Id: GhostedAreaSpec.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/GhostedAreaSpec.hh"
+#include "fastjet/Error.hh"
+#include<iostream>
+#include<sstream>
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+BasicRandom<double> GhostedAreaSpec::_random_generator;
+LimitedWarning GhostedAreaSpec::_warn_fj2_placement_deprecated;
+
+/// explicit constructor
+GhostedAreaSpec::GhostedAreaSpec(
+                           const Selector & selector,
+                           int    repeat_in        ,
+                           double ghost_area_in    ,   
+                           double grid_scatter_in  , 
+                           double pt_scatter_in    ,   
+                           double mean_ghost_pt_in 
+                          ): 
+    _repeat(repeat_in), 
+    _ghost_area(ghost_area_in), 
+    _grid_scatter(grid_scatter_in),  
+    _pt_scatter(pt_scatter_in), 
+    _mean_ghost_pt(mean_ghost_pt_in),
+    _fj2_placement(false),
+    _selector(selector),
+    _actual_ghost_area(-1.0)
+  {
+    // check the selector has the properties needed -- an area and
+    // applicability jet-by-jet (the latter follows automatically from
+    // the former?)
+    if (!_selector.has_finite_area()) throw Error("To construct a GhostedAreaSpec with a Selector, the selector must have a finite area");
+    if (!_selector.applies_jet_by_jet()) throw Error("To construct a GhostedAreaSpec with a Selector, the selector must apply jet-by-jet");
+    // get the internal rapidity extent from the selector
+    double ghost_maxrap_local, ghost_minrap_local;
+    _selector.get_rapidity_extent(ghost_minrap_local, ghost_maxrap_local);
+    _ghost_maxrap     = 0.5*(ghost_maxrap_local - ghost_minrap_local); 
+    _ghost_rap_offset = 0.5*(ghost_maxrap_local + ghost_minrap_local);
+    
+    _initialize();
+  
+}
+
+//======================================================================
+// sets fj2 ghost placement
+void GhostedAreaSpec::set_fj2_placement(bool val) {
+  _fj2_placement  = val; _initialize();
+  if (val) _warn_fj2_placement_deprecated.warn("FJ2 placement of ghosts can lead to systematic edge effects in area evaluation and is deprecated. Prefer new (default) FJ3 placement.");
+}
+
+//======================================================================
+/// sets the detailed parameters for the ghosts (which may not be quite
+/// the same as those requested -- this is in order for things to fit
+/// in nicely into 2pi etc...
+void GhostedAreaSpec::_initialize() {
+  // add on area-measuring dummy particles
+  _drap = sqrt(_ghost_area);
+  _dphi = _drap;
+  if (_fj2_placement) {
+    _nphi = int(ceil(twopi/_dphi)); _dphi = twopi/_nphi;
+    _nrap = int(ceil(_ghost_maxrap/_drap)); _drap = _ghost_maxrap / _nrap;
+    _actual_ghost_area = _dphi * _drap;
+    _n_ghosts   = (2*_nrap+1)*_nphi;
+  } else {
+    // for FJ3, update the ghost placement as follows
+    // - use nearest int rather than ceiling in determining number of
+    //   phi and rapidity locations, because this is more stable when
+    //   the user is trying to get an exact number based on the area
+    // - rather than placing ghosts up to maximum rapidity
+    _nphi = int(twopi/_dphi + 0.5); _dphi = twopi/_nphi;
+    _nrap = int(_ghost_maxrap/_drap + 0.5); _drap = _ghost_maxrap / _nrap;
+    _actual_ghost_area = _dphi * _drap;
+    _n_ghosts   = (2*_nrap)*_nphi;
+  }
+  // checkpoint the status of the random number generator.
+  checkpoint_random();
+  //_random_generator.info(cerr);
+}
+
+//----------------------------------------------------------------------
+/// adds the ghost 4-momenta to the vector of PseudoJet's
+void GhostedAreaSpec::add_ghosts(vector<PseudoJet> & event) const {
+
+  double rap_offset;
+  int nrap_upper;
+  if (_fj2_placement) {
+    rap_offset  = 0.0;
+    nrap_upper  = _nrap;
+  } else {
+    rap_offset  = 0.5;
+    nrap_upper  = _nrap-1;
+  }
+
+  // add momenta for ghosts
+  for (int irap = -_nrap; irap <= nrap_upper; irap++) {
+    for (int iphi = 0; iphi < _nphi; iphi++) {
+     
+      // include random offsets for all quantities
+      //----------------------------------------------
+      // NB: in FJ2 we'd exchanged the px and py components relative to a
+      // standard definition of phi; to preserve the same areas as fj2
+      // we now generate a "phi_fj2", and then convert to a standard phi
+      double phi_fj2 = (iphi+0.5) * _dphi + _dphi*(_our_rand()-0.5)*_grid_scatter;
+      double phi;
+      if (_fj2_placement) phi = 0.5*pi - phi_fj2;
+      else                phi = phi_fj2;
+      double rap = (irap+rap_offset) * _drap + _drap*(_our_rand()-0.5)*_grid_scatter
+	                                                 + _ghost_rap_offset ;
+      double pt = _mean_ghost_pt*(1+(_our_rand()-0.5)*_pt_scatter);
+
+      double exprap = exp(+rap);
+      double pminus = pt/exprap;
+      double pplus  = pt*exprap;
+      double px = pt*cos(phi);
+      double py = pt*sin(phi);
+      PseudoJet mom(px,py,0.5*(pplus-pminus),0.5*(pplus+pminus));
+      // this call fills in the PseudoJet's cached rap,phi information,
+      // based on pre-existing knowledge. Watch out: if you get the hint
+      // wrong nobody will tell you, but you will certainly mess up
+      // your results.
+      mom.set_cached_rap_phi(rap,phi);
+
+      // if we have an active selector and the particle does not pass the 
+      // selection condition, move on to the next momentum
+      if (_selector.worker().get() && !_selector.pass(mom)) continue;
+      event.push_back(mom);
+    }
+  }
+}
+
+string GhostedAreaSpec::description() const {
+
+  ostringstream ostr;
+  ostr << "ghosts of area " << actual_ghost_area() 
+       << " (had requested " << ghost_area() << ")";
+  if (_selector.worker().get()) 
+    ostr << ", placed according to selector (" << _selector.description() << ")";
+  else
+    ostr << ", placed up to y = " << ghost_maxrap() ;
+  ostr << ", scattered wrt to perfect grid by (rel) " << grid_scatter() 
+       << ", mean_ghost_pt = " << mean_ghost_pt()
+       << ", rel pt_scatter =  " << pt_scatter()
+       << ", n repetitions of ghost distributions =  " << repeat();
+  return ostr.str();
+}
+
+FASTJET_END_NAMESPACE
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/GhostedAreaSpec.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/GhostedAreaSpec.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/GhostedAreaSpec.hh	(revision 5)
@@ -0,0 +1,245 @@
+//STARTHEADER
+// $Id: GhostedAreaSpec.hh 2728 2011-11-20 14:18:59Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_GHOSTEDAREASPEC_HH__
+#define __FASTJET_GHOSTEDAREASPEC_HH__
+
+#include<vector>
+#include<string>
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/internal/BasicRandom.hh"
+#include "fastjet/Selector.hh"
+#include "fastjet/LimitedWarning.hh"
+
+// 
+#define STATIC_GENERATOR 1
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+/// namespace to hold default parameters for the active area spec
+namespace gas {
+  const double def_ghost_maxrap  = 6.0;
+  const int    def_repeat        = 1;
+  const double def_ghost_area    = 0.01;
+  const double def_grid_scatter  = 1.0;
+  const double def_pt_scatter    = 0.1;
+  const double def_mean_ghost_pt = 1e-100;
+}
+
+//----------------------------------------------------------------------
+/// @ingroup area_classes
+/// \class GhostedAreaSpec
+/// Parameters to configure the computation of jet areas using ghosts
+///
+/// Class that defines the parameters that go into the measurement
+/// of active jet areas.
+class GhostedAreaSpec {
+public:
+  /// default constructor
+  GhostedAreaSpec(): _ghost_maxrap (gas::def_ghost_maxrap), 
+		     _ghost_rap_offset(0.0),
+                    _repeat       (gas::def_repeat), 
+                    _ghost_area   (gas::def_ghost_area), 
+                    _grid_scatter (gas::def_grid_scatter), 
+                    _pt_scatter   (gas::def_pt_scatter), 
+                    _mean_ghost_pt(gas::def_mean_ghost_pt),
+                    _fj2_placement(false) {_initialize();}
+  
+  /// explicit constructor
+  explicit GhostedAreaSpec(double ghost_maxrap_in, 
+                          int    repeat_in        = gas::def_repeat,
+                          double ghost_area_in    = gas::def_ghost_area,   
+                          double grid_scatter_in  = gas::def_grid_scatter, 
+                          double pt_scatter_in    = gas::def_pt_scatter,   
+                          double mean_ghost_pt_in = gas::def_mean_ghost_pt
+                          ): 
+    _ghost_maxrap(ghost_maxrap_in), 
+    _ghost_rap_offset(0.0),
+    _repeat(repeat_in), 
+    _ghost_area(ghost_area_in), 
+    _grid_scatter(grid_scatter_in),  
+    _pt_scatter(pt_scatter_in), 
+    _mean_ghost_pt(mean_ghost_pt_in),
+    _fj2_placement(false) {_initialize();}
+
+  /// explicit constructor
+  explicit GhostedAreaSpec(double ghost_minrap_in, 
+			   double ghost_maxrap_in, 
+                           int    repeat_in        = gas::def_repeat,
+                           double ghost_area_in    = gas::def_ghost_area,   
+                           double grid_scatter_in  = gas::def_grid_scatter, 
+                           double pt_scatter_in    = gas::def_pt_scatter,   
+                           double mean_ghost_pt_in = gas::def_mean_ghost_pt
+                          ): 
+    _ghost_maxrap    (0.5*(ghost_maxrap_in - ghost_minrap_in)), 
+    _ghost_rap_offset(0.5*(ghost_maxrap_in + ghost_minrap_in)),
+    _repeat(repeat_in), 
+    _ghost_area(ghost_area_in), 
+    _grid_scatter(grid_scatter_in),  
+    _pt_scatter(pt_scatter_in), 
+    _mean_ghost_pt(mean_ghost_pt_in),
+    _fj2_placement(false) {_initialize();}
+
+
+  /// constructor based on a Selector
+  explicit GhostedAreaSpec(const Selector & selector,
+                           int    repeat_in        = gas::def_repeat,
+                           double ghost_area_in    = gas::def_ghost_area,   
+                           double grid_scatter_in  = gas::def_grid_scatter, 
+                           double pt_scatter_in    = gas::def_pt_scatter,   
+                           double mean_ghost_pt_in = gas::def_mean_ghost_pt
+			   );
+
+
+  /// does the initialization of actual ghost parameters
+  void _initialize();
+
+  // for accessing values set by the user
+  inline double ghost_etamax () const {return _ghost_maxrap;}
+  inline double ghost_maxrap () const {return _ghost_maxrap;}
+  inline double ghost_area   () const {return _ghost_area   ;}
+  inline double grid_scatter () const {return _grid_scatter;}
+  inline double pt_scatter   () const {return _pt_scatter  ;}
+  inline double mean_ghost_pt() const {return _mean_ghost_pt  ;}
+  inline int    repeat       () const {return _repeat      ;}
+  inline bool   fj2_placement() const {return _fj2_placement;}
+
+  inline double kt_scatter   () const {return _pt_scatter  ;}
+  inline double mean_ghost_kt() const {return _mean_ghost_pt  ;}
+
+  // for accessing values 
+  inline double actual_ghost_area() const {return _actual_ghost_area;}
+  inline int    n_ghosts()          const {return _n_ghosts;}
+
+  // when explicitly modifying values, sometimes call the initializer
+  inline void set_ghost_area   (double val) {_ghost_area    = val; _initialize();}
+  inline void set_ghost_etamax (double val) {_ghost_maxrap = val; _initialize();}
+  inline void set_ghost_maxrap (double val) {_ghost_maxrap = val; _initialize();}
+  inline void set_grid_scatter (double val) {_grid_scatter   = val; }
+  inline void set_pt_scatter   (double val) {_pt_scatter     = val; }
+  inline void set_mean_ghost_pt(double val) {_mean_ghost_pt  = val; }
+  inline void set_repeat       (int    val) {_repeat         = val; }
+
+  inline void set_kt_scatter   (double val) {_pt_scatter     = val; }
+  inline void set_mean_ghost_kt(double val) {_mean_ghost_pt  = val; }
+
+  /// if val is true, set ghost placement as it was in FastJet 2.X. The
+  /// main differences between FJ2 and FJ3 ghost placement are
+  ///
+  ///  - in FJ2 the rapidity spacing was
+  ///    ceil((maxrap-minrap)/sqrt(area)), while in FJ3 it is
+  ///    int((maxrap-minrap)/sqrt(area) + 0.5) [similarly for phi].
+  ///    The FJ3 option offers more stability when trying to specify a
+  ///    spacing that exactly fits the extent.
+  ///
+  /// - in FJ2, the ghosts are placed at the corners of grid cells
+  ///   (i.e. extending up to maxrap), while in FJ3 they are placed at
+  ///   the centres of grid cells (i.e. extending roughly up to
+  ///   maxrap-sqrt(area)). The FJ2 behaviour effectively skews the
+  ///   total area coverage when maxrap is small, by an amount
+  ///   sqrt(area)/(2*maxrap).
+  ///
+  /// FJ2 placement is now deprecated.
+  void set_fj2_placement(bool  val);
+
+  /// return nphi (ghosts layed out (-nrap, 0..nphi-1), (-nrap+1,0..nphi-1),
+  /// ... (nrap,0..nphi-1)
+  inline int nphi() const {return _nphi;}
+  inline int nrap() const {return _nrap;}
+
+  /// get all relevant information about the status of the 
+  /// random number generator, so that it can be reset subsequently
+  /// with set_random_status.
+  inline void get_random_status(std::vector<int> & __iseed) const {
+    _random_generator.get_status(__iseed);}
+
+  /// set the status of the random number generator, as obtained
+  /// previously with get_random_status. Note that the random
+  /// generator is a static member of the class, i.e. common to all
+  /// instances of the class --- so if you modify the random for this
+  /// instance, you modify it for all instances.
+  inline void set_random_status(const std::vector<int> & __iseed) {
+    _random_generator.set_status(__iseed);}
+  
+  inline void checkpoint_random() {get_random_status(_random_checkpoint);}
+  inline void restore_checkpoint_random() {set_random_status(_random_checkpoint);}
+
+  /// for a summary
+  std::string description() const;
+
+  /// push a set of ghost 4-momenta onto the back of the vector of
+  /// PseudoJets
+  void add_ghosts(std::vector<PseudoJet> & ) const;
+
+  /// very deprecated public access to a random number 
+  /// from the internal generator
+  inline double random_at_own_risk() const {return _our_rand();}
+  /// very deprecated public access to the generator itself
+  inline BasicRandom<double> & generator_at_own_risk() const {
+    return _random_generator;}
+
+private:
+  
+  // quantities that determine nature and distribution of ghosts
+  double _ghost_maxrap;
+  double _ghost_rap_offset;
+  int    _repeat      ;
+  double _ghost_area   ;  
+  double _grid_scatter;
+  double _pt_scatter  ;
+  double _mean_ghost_pt;
+  bool   _fj2_placement;
+
+  Selector _selector;
+
+  // derived quantities
+  double _actual_ghost_area, _dphi, _drap;
+  int    _n_ghosts, _nphi, _nrap;
+
+
+  std::vector<int> _random_checkpoint;
+  static BasicRandom<double> _random_generator;
+  //mutable BasicRandom<double> _random_generator;
+
+  static LimitedWarning _warn_fj2_placement_deprecated;
+
+  inline double _our_rand() const {return _random_generator();}
+  
+};
+
+/// just provide a typedef for backwards compatibility with programs
+/// based on versions 2.0 and 2.1 of fastjet. Since there is no
+/// easy way of telling people this is deprecated at compile or run
+/// time, we should be careful before removing this in the future.
+typedef GhostedAreaSpec ActiveAreaSpec;
+
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_GHOSTEDAREASPEC_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/JetDefinition.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/JetDefinition.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/JetDefinition.cc	(revision 5)
@@ -0,0 +1,392 @@
+//STARTHEADER
+// $Id: JetDefinition.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/JetDefinition.hh"
+#include "fastjet/Error.hh"
+#include "fastjet/CompositeJetStructure.hh"
+#include<sstream>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+
+const double JetDefinition::max_allowable_R = 1000.0;
+
+//----------------------------------------------------------------------
+// [NB: implementation was getting complex, so in 2.4-devel moved it
+//  from .hh to .cc]
+JetDefinition::JetDefinition(JetAlgorithm jet_algorithm_in, 
+			     double R_in, 
+			     Strategy strategy_in,
+			     RecombinationScheme recomb_scheme_in,
+                             int nparameters) :
+  _jet_algorithm(jet_algorithm_in), _Rparam(R_in), _strategy(strategy_in) {
+
+  // set R parameter or ensure its sensibleness, as appropriate
+  if (_jet_algorithm == ee_kt_algorithm) {
+    _Rparam = 4.0; // introduce a fictional R that ensures that
+                   // our clustering sequence will not produce
+                   // "beam" jets except when only a single particle remains.
+                   // Any value > 2 would have done here
+  } else {
+    // We maintain some limit on R because particles with pt=0, m=0
+    // can have rapidities O(100000) and one doesn't want the
+    // clustering to start including them as if their rapidities were
+    // physical.
+    if (R_in > max_allowable_R) {
+      ostringstream oss;
+      oss << "Requested R = " << R_in << " for jet definition is larger than max_allowable_R = " << max_allowable_R;
+      throw Error(oss.str());
+    }
+  }
+
+  // cross-check the number of parameters that were declared in setting up the
+  // algorithm (passed internally from the public constructors)
+  switch (jet_algorithm_in) {
+  case ee_kt_algorithm:
+    if (nparameters != 0) {
+      ostringstream oss;
+      oss << "ee_kt_algorithm should be constructed with 0 parameters but was called with " 
+          << nparameters << " parameter(s)\n";
+      throw Error(oss.str()); 
+    }
+    break;
+  case genkt_algorithm: 
+  case ee_genkt_algorithm: 
+    if (nparameters != 2) {
+      ostringstream oss;
+      oss << "(ee_)genkt_algorithm should be constructed with 2 parameters but was called with " 
+          << nparameters << " parameter(s)\n";
+      throw Error(oss.str()); 
+    }
+    break;
+  default:
+    if (nparameters != 1) {
+      ostringstream oss;
+      oss << "The jet algorithm you requested ("
+          << jet_algorithm_in << ") should be constructed with 1 parameter but was called with " 
+          << nparameters << " parameter(s)\n";
+      throw Error(oss.str()); 
+    }
+  }
+
+  // make sure the strategy requested is sensible
+  assert (_strategy  != plugin_strategy);
+
+  _plugin = NULL;
+  set_recombination_scheme(recomb_scheme_in);
+  set_extra_param(0.0); // make sure it's defined
+}
+
+
+//----------------------------------------------------------------------
+string JetDefinition::description() const {
+  ostringstream name;
+  if (jet_algorithm() == plugin_algorithm) {
+    return plugin()->description();
+  } else if (jet_algorithm() == kt_algorithm) {
+    name << "Longitudinally invariant kt algorithm with R = " << R();
+    name << " and " << recombiner()->description();
+  } else if (jet_algorithm() == cambridge_algorithm) {
+    name << "Longitudinally invariant Cambridge/Aachen algorithm with R = " 
+	 << R() ;
+    name << " and " << recombiner()->description();
+  } else if (jet_algorithm() == antikt_algorithm) {
+    name << "Longitudinally invariant anti-kt algorithm with R = " 
+	 << R() ;
+    name << " and " << recombiner()->description();
+  } else if (jet_algorithm() == genkt_algorithm) {
+    name << "Longitudinally invariant generalised kt algorithm with R = " 
+	 << R() << ", p = " << extra_param();
+    name << " and " << recombiner()->description();
+  } else if (jet_algorithm() == cambridge_for_passive_algorithm) {
+    name << "Longitudinally invariant Cambridge/Aachen algorithm with R = " 
+	 << R() << "and a special hack whereby particles with kt < " 
+         << extra_param() << "are treated as passive ghosts";
+  } else if (jet_algorithm() == ee_kt_algorithm) {
+    name << "e+e- kt (Durham) algorithm (NB: no R)";
+    name << " with " << recombiner()->description();
+  } else if (jet_algorithm() == ee_genkt_algorithm) {
+    name << "e+e- generalised kt algorithm with R = " 
+	 << R() << ", p = " << extra_param();
+    name << " and " << recombiner()->description();
+  } else if (jet_algorithm() == undefined_jet_algorithm) {
+    name << "uninitialised JetDefinition (jet_algorithm=undefined_jet_algorithm)" ;
+  } else {
+    throw Error("JetDefinition::description(): unrecognized jet_algorithm");
+  }
+  return name.str();
+}
+
+
+void JetDefinition::set_recombination_scheme(
+                               RecombinationScheme recomb_scheme) {
+  _default_recombiner = JetDefinition::DefaultRecombiner(recomb_scheme);
+
+  // do not forget to delete the existing recombiner if needed
+  if (_recombiner_shared()) _recombiner_shared.reset();
+
+  _recombiner = 0;
+}
+
+
+// returns true if the current jet definitions shares the same
+// recombiner as teh one passed as an argument
+bool JetDefinition::has_same_recombiner(const JetDefinition &other_jd) const{
+  // first make sure that they have the same recombination scheme
+  const RecombinationScheme & scheme = recombination_scheme();
+  if (other_jd.recombination_scheme() != scheme) return false;
+
+  // if the scheme is "external", also check that they ahve the same
+  // recombiner
+  return (scheme != external_scheme) 
+    || (recombiner() == other_jd.recombiner());
+}
+
+/// allows to let the JetDefinition handle the deletion of the
+/// recombiner when it is no longer used
+void JetDefinition::delete_recombiner_when_unused(){
+  if (_recombiner == 0){
+    throw Error("tried to call JetDefinition::delete_recombiner_when_unused() for a JetDefinition without a user-defined recombination scheme");
+  }
+
+  _recombiner_shared.reset(_recombiner);
+}
+
+/// allows to let the JetDefinition handle the deletion of the
+/// plugin when it is no longer used
+void JetDefinition::delete_plugin_when_unused(){
+  if (_plugin == 0){
+    throw Error("tried to call JetDefinition::delete_plugin_when_unused() for a JetDefinition without a plugin");
+  }
+
+  _plugin_shared.reset(_plugin);
+}
+
+
+
+string JetDefinition::DefaultRecombiner::description() const {
+  switch(_recomb_scheme) {
+  case E_scheme:
+    return "E scheme recombination";
+  case pt_scheme:
+    return "pt scheme recombination";
+  case pt2_scheme:
+    return "pt2 scheme recombination";
+  case Et_scheme:
+    return "Et scheme recombination";
+  case Et2_scheme:
+    return "Et2 scheme recombination";
+  case BIpt_scheme:
+    return "boost-invariant pt scheme recombination";
+  case BIpt2_scheme:
+    return "boost-invariant pt2 scheme recombination";
+  default:
+    ostringstream err;
+    err << "DefaultRecombiner: unrecognized recombination scheme " 
+        << _recomb_scheme;
+    throw Error(err.str());
+  }
+}
+
+
+void JetDefinition::DefaultRecombiner::recombine(
+           const PseudoJet & pa, const PseudoJet & pb,
+           PseudoJet & pab) const {
+  
+  double weighta, weightb;
+
+  switch(_recomb_scheme) {
+  case E_scheme:
+    // a call to reset turns out to be somewhat more efficient
+    // than a sum and assignment
+    //pab = pa + pb; 
+    pab.reset(pa.px()+pb.px(),
+    	      pa.py()+pb.py(),
+    	      pa.pz()+pb.pz(),
+    	      pa.E ()+pb.E ());
+    return;
+  // all remaining schemes are massless recombinations and locally
+  // we just set weights, while the hard work is done below...
+  case pt_scheme:
+  case Et_scheme:
+  case BIpt_scheme:
+    weighta = pa.perp(); 
+    weightb = pb.perp();
+    break;
+  case pt2_scheme:
+  case Et2_scheme:
+  case BIpt2_scheme:
+    weighta = pa.perp2(); 
+    weightb = pb.perp2();
+    break;
+  default:
+    ostringstream err;
+    err << "DefaultRecombiner: unrecognized recombination scheme " 
+        << _recomb_scheme;
+    throw Error(err.str());
+  }
+
+  double perp_ab = pa.perp() + pb.perp();
+  if (perp_ab != 0.0) { // weights also non-zero...
+    double y_ab    = (weighta * pa.rap() + weightb * pb.rap())/(weighta+weightb);
+    
+    // take care with periodicity in phi...
+    double phi_a = pa.phi(), phi_b = pb.phi();
+    if (phi_a - phi_b > pi)  phi_b += twopi;
+    if (phi_a - phi_b < -pi) phi_b -= twopi;
+    double phi_ab = (weighta * phi_a + weightb * phi_b)/(weighta+weightb);
+
+    // this is much more efficient...
+    pab.reset_PtYPhiM(perp_ab,y_ab,phi_ab);
+    // pab = PseudoJet(perp_ab*cos(phi_ab),
+    // 		    perp_ab*sin(phi_ab),
+    // 		    perp_ab*sinh(y_ab),
+    // 		    perp_ab*cosh(y_ab));
+  } else { // weights are zero
+    //pab = PseudoJet(0.0,0.0,0.0,0.0);
+    pab.reset(0.0, 0.0, 0.0, 0.0);
+  }
+}
+
+
+void JetDefinition::DefaultRecombiner::preprocess(PseudoJet & p) const {
+  switch(_recomb_scheme) {
+  case E_scheme:
+  case BIpt_scheme:
+  case BIpt2_scheme:
+    break;
+  case pt_scheme:
+  case pt2_scheme:
+    {
+      // these schemes (as in the ktjet implementation) need massless
+      // initial 4-vectors with essentially E=|p|.
+      double newE = sqrt(p.perp2()+p.pz()*p.pz());
+      p.reset_momentum(p.px(), p.py(), p.pz(), newE);
+      // FJ2.x version
+      // int    user_index = p.user_index();
+      // p = PseudoJet(p.px(), p.py(), p.pz(), newE);
+      // p.set_user_index(user_index);
+    }
+    break;
+  case Et_scheme:
+  case Et2_scheme:
+    {
+      // these schemes (as in the ktjet implementation) need massless
+      // initial 4-vectors with essentially E=|p|.
+      double rescale = p.E()/sqrt(p.perp2()+p.pz()*p.pz());
+      p.reset_momentum(rescale*p.px(), rescale*p.py(), rescale*p.pz(), p.E());
+      // FJ2.x version
+      // int    user_index = p.user_index();
+      // p = PseudoJet(rescale*p.px(), rescale*p.py(), rescale*p.pz(), p.E());
+      // p.set_user_index(user_index);
+    }
+    break;
+  default:
+    ostringstream err;
+    err << "DefaultRecombiner: unrecognized recombination scheme " 
+        << _recomb_scheme;
+    throw Error(err.str());
+  }
+}
+
+void JetDefinition::Plugin::set_ghost_separation_scale(double /*scale*/) const {
+  throw Error("set_ghost_separation_scale not supported");
+}
+
+
+
+//-------------------------------------------------------------------------------
+// helper functions to build a jet made of pieces
+//
+// This is the extended version with support for a user-defined
+// recombination-scheme
+// -------------------------------------------------------------------------------
+
+// build a "CompositeJet" from the vector of its pieces
+//
+// the user passes the reciombination scheme used to "sum" the pieces.
+PseudoJet join(const vector<PseudoJet> & pieces, const JetDefinition::Recombiner & recombiner){
+  // compute the total momentum
+  //--------------------------------------------------
+  PseudoJet result;  // automatically initialised to 0
+  if (pieces.size()>0){
+    result = pieces[0];
+    for (unsigned int i=1; i<pieces.size(); i++)
+      recombiner.plus_equal(result, pieces[i]);
+  }
+
+  // attach a CompositeJetStructure to the result
+  //--------------------------------------------------
+  CompositeJetStructure *cj_struct = new CompositeJetStructure(pieces, &recombiner);
+
+  result.set_structure_shared_ptr(SharedPtr<PseudoJetStructureBase>(cj_struct));
+
+  return result;
+}
+
+// build a "CompositeJet" from a single PseudoJet
+PseudoJet join(const PseudoJet & j1, 
+	       const JetDefinition::Recombiner & recombiner){
+  return join(vector<PseudoJet>(1,j1), recombiner);
+}
+
+// build a "CompositeJet" from two PseudoJet
+PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, 
+	       const JetDefinition::Recombiner & recombiner){
+  vector<PseudoJet> pieces;
+  pieces.push_back(j1);
+  pieces.push_back(j2);
+  return join(pieces, recombiner);
+}
+
+// build a "CompositeJet" from 3 PseudoJet
+PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3, 
+	       const JetDefinition::Recombiner & recombiner){
+  vector<PseudoJet> pieces;
+  pieces.push_back(j1);
+  pieces.push_back(j2);
+  pieces.push_back(j3);
+  return join(pieces, recombiner);
+}
+
+// build a "CompositeJet" from 4 PseudoJet
+PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3, const PseudoJet & j4,
+	       const JetDefinition::Recombiner & recombiner){
+  vector<PseudoJet> pieces;
+  pieces.push_back(j1);
+  pieces.push_back(j2);
+  pieces.push_back(j3);
+  pieces.push_back(j4);
+  return join(pieces, recombiner);
+}
+
+
+ 
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/JetDefinition.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/JetDefinition.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/JetDefinition.hh	(revision 5)
@@ -0,0 +1,523 @@
+//STARTHEADER
+// $Id: JetDefinition.hh 2687 2011-11-14 11:17:51Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_JETDEFINITION_HH__
+#define __FASTJET_JETDEFINITION_HH__
+
+#include<cassert>
+#include "fastjet/internal/numconsts.hh"
+#include "fastjet/PseudoJet.hh"
+#include<string>
+#include<memory>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+/// return a string containing information about the release
+//  NB: (implemented in ClusterSequence.cc but defined here because
+//  this is a visible location)
+std::string fastjet_version_string();
+
+//======================================================================
+/// the various options for the algorithmic strategy to adopt in
+/// clustering events with kt and cambridge style algorithms.
+enum Strategy {
+  /// fastest form about 500..10^4
+  N2MinHeapTiled   = -4, 
+  /// fastest from about 50..500
+  N2Tiled     = -3, 
+  /// legacy
+  N2PoorTiled = -2, 
+  /// fastest below 50
+  N2Plain     = -1, 
+  /// worse even than the usual N^3 algorithms
+  N3Dumb      =  0, 
+  /// automatic selection of the best (based on N)
+  Best        =  1, 
+  /// best of the NlnN variants -- best overall for N>10^4.
+  /// (Does not work for R>=2pi)
+  NlnN        =  2, 
+  /// legacy N ln N using 3pi coverage of cylinder.
+  /// (Does not work for R>=2pi)
+  NlnN3pi     =  3, 
+  /// legacy N ln N using 4pi coverage of cylinder
+  NlnN4pi     =  4,
+  /// Chan's closest pair method (in a variant with 4pi coverage),
+  /// for use exclusively with the Cambridge algorithm.
+  /// (Does not work for R>=2pi)
+  NlnNCam4pi   = 14,
+  /// Chan's closest pair method (in a variant with 2pi+2R coverage),
+  /// for use exclusively with the Cambridge algorithm.
+  /// (Does not work for R>=2pi)
+  NlnNCam2pi2R = 13,
+  /// Chan's closest pair method (in a variant with 2pi+minimal extra
+  /// variant), for use exclusively with the Cambridge algorithm. 
+  /// (Does not work for R>=2pi)
+  NlnNCam      = 12, // 2piMultD
+  /// the plugin has been used...
+  plugin_strategy = 999
+};
+
+
+//======================================================================
+/// \enum JetAlgorithm
+/// the various families of jet-clustering algorithm
+enum JetAlgorithm {
+  /// the longitudinally invariant kt algorithm
+  kt_algorithm=0,
+  /// the longitudinally invariant variant of the cambridge algorithm
+  /// (aka Aachen algoithm).
+  cambridge_algorithm=1,
+  /// like the k_t but with distance measures 
+  ///       dij = min(1/kti^2,1/ktj^2) Delta R_{ij}^2 / R^2
+  ///       diB = 1/kti^2
+  antikt_algorithm=2, 
+  /// like the k_t but with distance measures 
+  ///       dij = min(kti^{2p},ktj^{2p}) Delta R_{ij}^2 / R^2
+  ///       diB = 1/kti^{2p}
+  /// where p = extra_param()
+  genkt_algorithm=3, 
+  /// a version of cambridge with a special distance measure for particles
+  /// whose pt is < extra_param()
+  cambridge_for_passive_algorithm=11,
+  /// a version of genkt with a special distance measure for particles
+  /// whose pt is < extra_param() [relevant for passive areas when p<=0]
+  genkt_for_passive_algorithm=13, 
+  //.................................................................
+  /// the e+e- kt algorithm
+  ee_kt_algorithm=50,
+  /// the e+e- genkt algorithm  (R > 2 and p=1 gives ee_kt)
+  ee_genkt_algorithm=53,
+  //.................................................................
+  /// any plugin algorithm supplied by the user
+  plugin_algorithm = 99,
+  //.................................................................
+  /// the value for the jet algorithm in a JetDefinition for which
+  /// no algorithm has yet been defined
+  undefined_jet_algorithm = 999
+};
+
+/// make standard Les Houches nomenclature JetAlgorithm (algorithm is general
+/// recipe without the parameters) backward-compatible with old JetFinder
+typedef JetAlgorithm JetFinder;
+
+/// provide other possible names for the Cambridge/Aachen algorithm
+const JetAlgorithm aachen_algorithm = cambridge_algorithm;
+const JetAlgorithm cambridge_aachen_algorithm = cambridge_algorithm;
+
+//======================================================================
+/// the various recombination schemes
+enum RecombinationScheme {
+  /// summing the 4-momenta
+  E_scheme=0,
+  /// pt weighted recombination of y,phi (and summing of pt's)
+  /// with preprocessing to make things massless by rescaling E=|\vec p|
+  pt_scheme=1,
+  /// pt^2 weighted recombination of y,phi (and summing of pt's)
+  /// with preprocessing to make things massless by rescaling E=|\vec p|
+  pt2_scheme=2,
+  /// pt weighted recombination of y,phi (and summing of pt's)
+  /// with preprocessing to make things massless by rescaling |\vec p|->=E
+  Et_scheme=3,
+  /// pt^2 weighted recombination of y,phi (and summing of pt's)
+  /// with preprocessing to make things massless by rescaling |\vec p|->=E
+  Et2_scheme=4,
+  /// pt weighted recombination of y,phi (and summing of pt's), with 
+  /// no preprocessing
+  BIpt_scheme=5,
+  /// pt^2 weighted recombination of y,phi (and summing of pt's)
+  /// no preprocessing
+  BIpt2_scheme=6,
+  /// for the user's external scheme
+  external_scheme = 99
+};
+
+
+
+// forward declaration, needed in order to specify interface for the
+// plugin.
+class ClusterSequence;
+
+
+
+
+//======================================================================
+/// @ingroup basic_classes
+/// \class JetDefinition
+/// class that is intended to hold a full definition of the jet
+/// clusterer
+class JetDefinition {
+  
+public:
+
+  /// forward declaration of a class that allows the user to introduce
+  /// their own plugin 
+  class Plugin;
+
+  // forward declaration of a class that will provide the
+  // recombination scheme facilities and/or allow a user to
+  // extend these facilities
+  class Recombiner;
+
+
+  /// constructor with alternative ordering or arguments -- note that
+  /// we have not provided a default jet finder, to avoid ambiguous
+  /// JetDefinition() constructor.
+  JetDefinition(JetAlgorithm jet_algorithm_in, 
+                double R_in, 
+                RecombinationScheme recomb_scheme_in = E_scheme,
+                Strategy strategy_in = Best) {
+    *this = JetDefinition(jet_algorithm_in, R_in, strategy_in, recomb_scheme_in, 1);
+  }
+
+  /// constructor for algorithms that have no free parameters
+  /// (e.g. ee_kt_algorithm)
+  JetDefinition(JetAlgorithm jet_algorithm_in, 
+                RecombinationScheme recomb_scheme_in = E_scheme,
+                Strategy strategy_in = Best) {
+    double dummyR = 0.0;
+    *this = JetDefinition(jet_algorithm_in, dummyR, strategy_in, recomb_scheme_in, 0);
+  }
+
+  /// constructor for algorithms that require R + one extra parameter to be set 
+  /// (the gen-kt series for example)
+  JetDefinition(JetAlgorithm jet_algorithm_in, 
+                double R_in, 
+                double xtra_param_in,
+                RecombinationScheme recomb_scheme_in = E_scheme,
+                Strategy strategy_in = Best) {
+    *this = JetDefinition(jet_algorithm_in, R_in, strategy_in, recomb_scheme_in, 2);
+    set_extra_param(xtra_param_in);
+  }
+
+
+  /// constructor in a form that allows the user to provide a pointer
+  /// to an external recombiner class (which must remain valid for the
+  /// life of the JetDefinition object).
+  JetDefinition(JetAlgorithm jet_algorithm_in, 
+                double R_in, 
+                const Recombiner * recombiner_in,
+                Strategy strategy_in = Best) {
+    *this = JetDefinition(jet_algorithm_in, R_in, external_scheme, strategy_in);
+    _recombiner = recombiner_in;
+  }
+
+
+  /// constructor for case with 0 parameters (ee_kt_algorithm) and
+  /// and external recombiner
+  JetDefinition(JetAlgorithm jet_algorithm_in, 
+                const Recombiner * recombiner_in,
+                Strategy strategy_in = Best) {
+    *this = JetDefinition(jet_algorithm_in, external_scheme, strategy_in);
+    _recombiner = recombiner_in;
+  }
+
+  /// constructor allowing the extra parameter to be set and a pointer to
+  /// a recombiner
+  JetDefinition(JetAlgorithm jet_algorithm_in, 
+                double R_in, 
+                double xtra_param_in,
+                const Recombiner * recombiner_in,
+                Strategy strategy_in = Best) {
+    *this = JetDefinition(jet_algorithm_in, R_in, external_scheme, strategy_in);
+    _recombiner = recombiner_in;
+    set_extra_param(xtra_param_in);
+  }
+
+  /// a default constructor which creates a jet definition that is in
+  /// a well-defined internal state, but not actually usable for jet
+  /// clustering.
+  JetDefinition()  {
+    *this = JetDefinition(undefined_jet_algorithm, 1.0);
+  }
+  
+
+  // /// a default constructor
+  // JetDefinition() {
+  //   *this = JetDefinition(kt_algorithm, 1.0);
+  // }
+
+  /// constructor based on a pointer to a user's plugin; the object
+  /// pointed to must remain valid for the whole duration of existence
+  /// of the JetDefinition and any related ClusterSequences
+  JetDefinition(const Plugin * plugin_in) {
+    _plugin = plugin_in;
+    _strategy = plugin_strategy;
+    _Rparam = _plugin->R();
+    _jet_algorithm = plugin_algorithm;
+    set_recombination_scheme(E_scheme);
+  }
+
+
+  /// constructor to fully specify a jet-definition (together with
+  /// information about how algorithically to run it).
+  ///
+  /// the ordering of arguments here is old and deprecated (except
+  /// as the common constructor for internal use)
+  JetDefinition(JetAlgorithm jet_algorithm_in, 
+                double R_in, 
+                Strategy strategy_in,
+                RecombinationScheme recomb_scheme_in = E_scheme,
+                int nparameters_in = 1);
+  
+  /// R values larger than max_allowable_R are not allowed.
+  ///
+  /// We use a value of 1000, substantially smaller than
+  /// numeric_limits<double>::max(), to leave room for the convention
+  /// within PseudoJet of setting unphysical (infinite) rapidities to
+  /// +-(MaxRap + abs(pz())), where MaxRap is 10^5.
+  static const double max_allowable_R; //= 1000.0;
+
+  /// set the recombination scheme to the one provided
+  void set_recombination_scheme(RecombinationScheme);
+
+  /// set the recombiner class to the one provided
+  void set_recombiner(const Recombiner * recomb) {
+    if (_recombiner_shared()) _recombiner_shared.reset(recomb);
+    _recombiner = recomb;
+    _default_recombiner = DefaultRecombiner(external_scheme);
+  }
+
+  /// calling this tells the JetDefinition to handle the deletion of
+  /// the recombiner when it is no longer used
+  void delete_recombiner_when_unused();
+
+  /// return a pointer to the plugin 
+  const Plugin * plugin() const {return _plugin;};
+
+  /// allows to let the JetDefinition handle the deletion of the
+  /// plugin when it is no longer used
+  void delete_plugin_when_unused();
+
+  /// return information about the definition...
+  JetAlgorithm jet_algorithm  () const {return _jet_algorithm  ;}
+  /// same as above for backward compatibility
+  JetAlgorithm jet_finder     () const {return _jet_algorithm  ;}
+  double    R           () const {return _Rparam      ;}
+  // a general purpose extra parameter, whose meaning depends on
+  // the algorithm, and may often be unused.
+  double    extra_param () const {return _extra_param ;}
+  Strategy  strategy    () const {return _strategy    ;}
+  RecombinationScheme recombination_scheme() const {
+    return _default_recombiner.scheme();}
+
+  /// (re)set the jet finder
+  void set_jet_algorithm(JetAlgorithm njf) {_jet_algorithm = njf;}
+  /// same as above for backward compatibility
+  void set_jet_finder(JetAlgorithm njf)    {_jet_algorithm = njf;}
+  /// (re)set the general purpose extra parameter
+  void set_extra_param(double xtra_param) {_extra_param = xtra_param;}
+
+  /// return a pointer to the currently defined recombiner. 
+  ///
+  /// Warning: the pointer may be to an internal recombiner (for
+  /// default recombination schemes), in which case if the
+  /// JetDefinition becomes invalid (e.g. is deleted), the pointer
+  /// will then point to an object that no longer exists.
+  /// 
+  /// Note also that if you copy a JetDefinition with a default
+  /// recombination scheme, then the two copies will have distinct
+  /// recombiners, and return different recombiner() pointers.
+  const Recombiner * recombiner() const {
+    return _recombiner == 0 ? & _default_recombiner : _recombiner;}
+
+  /// returns true if the current jet definitions shares the same
+  /// recombiner as teh one passed as an argument
+  bool has_same_recombiner(const JetDefinition &other_jd) const;
+
+  /// return a textual description of the current jet definition 
+  std::string description() const;
+
+
+public:
+  //======================================================================
+  /// @ingroup advanced_usage
+  /// \class Recombiner
+  /// An abstract base class that will provide the recombination scheme
+  /// facilities and/or allow a user to extend these facilities
+  class Recombiner {
+  public:
+    /// return a textual description of the recombination scheme
+    /// implemented here
+    virtual std::string description() const = 0;
+    
+    /// recombine pa and pb and put result into pab
+    virtual void recombine(const PseudoJet & pa, const PseudoJet & pb, 
+                           PseudoJet & pab) const = 0;
+
+    /// routine called to preprocess each input jet (to make all input
+    /// jets compatible with the scheme requirements (e.g. massless).
+    virtual void preprocess(PseudoJet & ) const {};
+    
+    /// a destructor to be replaced if necessary in derived classes...
+    virtual ~Recombiner() {};
+
+    /// pa += pb in the given recombination scheme. Not virtual -- the
+    /// user should have no reason to want to redefine this!
+    inline void plus_equal(PseudoJet & pa, const PseudoJet & pb) const {
+      // put result in a temporary location in case the recombiner
+      // does something funny (ours doesn't, but who knows about the
+      // user's)
+      PseudoJet pres; 
+      recombine(pa,pb,pres);
+      pa = pres;
+    }
+
+  };
+  
+  
+  //======================================================================
+  /// @ingroup advanced_usage
+  /// \class DefaultRecombiner
+  /// A class that will provide the recombination scheme facilities and/or
+  /// allow a user to extend these facilities
+  ///
+  /// This class is derived from the (abstract) class Recombiner. It
+  /// simply "sums" PseudoJets using a specified recombination scheme
+  /// (E-scheme by default)
+  class DefaultRecombiner : public Recombiner {
+  public:
+    DefaultRecombiner(RecombinationScheme recomb_scheme = E_scheme) : 
+      _recomb_scheme(recomb_scheme) {}
+    
+    virtual std::string description() const;
+    
+    /// recombine pa and pb and put result into pab
+    virtual void recombine(const PseudoJet & pa, const PseudoJet & pb, 
+                           PseudoJet & pab) const;
+
+    virtual void preprocess(PseudoJet & p) const;
+
+    /// return the index of the recombination scheme
+    RecombinationScheme scheme() const {return _recomb_scheme;}
+    
+  private:
+    RecombinationScheme _recomb_scheme;
+  };
+
+
+  //======================================================================
+  /// @ingroup advanced_usage
+  /// \class Plugin
+  /// a class that allows a user to introduce their own "plugin" jet
+  /// finder
+  ///
+  /// Note that all the plugins provided with FastJet are derived from
+  /// this class
+  class Plugin{
+  public:
+    /// return a textual description of the jet-definition implemented
+    /// in this plugin
+    virtual std::string description() const = 0;
+    
+    /// given a ClusterSequence that has been filled up with initial
+    /// particles, the following function should fill up the rest of the
+    /// ClusterSequence, using the following member functions of
+    /// ClusterSequence:
+    ///   - plugin_do_ij_recombination(...)
+    ///   - plugin_do_iB_recombination(...)
+    virtual void run_clustering(ClusterSequence &) const = 0;
+    
+    virtual double R() const = 0;
+    
+    /// return true if there is specific support for the measurement
+    /// of passive areas, in the sense that areas determined from all
+    /// particles below the ghost separation scale will be a passive
+    /// area. [If you don't understand this, ignore it!]
+    virtual bool supports_ghosted_passive_areas() const {return false;}
+
+    /// set the ghost separation scale for passive area determinations
+    /// in future runs (strictly speaking that makes the routine
+    /// a non const, so related internal info must be stored as a mutable)
+    virtual void set_ghost_separation_scale(double scale) const;
+    virtual double ghost_separation_scale() const {return 0.0;}
+
+    /// if this returns false then a warning will be given
+    /// whenever the user requests "exclusive" jets from the
+    /// cluster sequence
+    virtual bool exclusive_sequence_meaningful() const {return false;}
+
+    /// a destructor to be replaced if necessary in derived classes...
+    virtual ~Plugin() {};
+  };
+
+private:
+
+
+  JetAlgorithm _jet_algorithm;
+  double    _Rparam;
+  double    _extra_param ; ///< parameter whose meaning varies according to context
+  Strategy  _strategy  ;
+
+  const Plugin * _plugin;
+  SharedPtr<const Plugin> _plugin_shared;
+
+  // when we use our own recombiner it's useful to point to it here
+  // so that we don't have to worry about deleting it etc...
+  DefaultRecombiner _default_recombiner;
+  const Recombiner * _recombiner;
+  SharedPtr<const Recombiner> _recombiner_shared;
+
+};
+
+
+//-------------------------------------------------------------------------------
+// helper functions to build a jet made of pieces
+//
+// These functions include an options recombiner used to compute the
+// total composite jet momentum
+// -------------------------------------------------------------------------------
+
+/// build a "CompositeJet" from the vector of its pieces
+///
+/// In this case, E-scheme recombination is assumed to compute the
+/// total momentum
+PseudoJet join(const std::vector<PseudoJet> & pieces, const JetDefinition::Recombiner & recombiner);
+
+/// build a MergedJet from a single PseudoJet
+PseudoJet join(const PseudoJet & j1, 
+	       const JetDefinition::Recombiner & recombiner);
+
+/// build a MergedJet from 2 PseudoJet
+PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, 
+	       const JetDefinition::Recombiner & recombiner);
+
+/// build a MergedJet from 3 PseudoJet
+PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3, 
+	       const JetDefinition::Recombiner & recombiner);
+
+/// build a MergedJet from 4 PseudoJet
+PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3, const PseudoJet & j4, 
+	       const JetDefinition::Recombiner & recombiner);
+
+
+
+
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_JETDEFINITION_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/LimitedWarning.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/LimitedWarning.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/LimitedWarning.cc	(revision 5)
@@ -0,0 +1,86 @@
+//STARTHEADER
+// $Id: LimitedWarning.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/LimitedWarning.hh"
+#include <sstream>
+#include <limits>
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE
+
+ostream * LimitedWarning::_default_ostr = &cerr;
+std::list< LimitedWarning::Summary > LimitedWarning::_global_warnings_summary;
+int LimitedWarning::_max_warn_default = 5;
+
+
+/// output a warning to ostr
+void LimitedWarning::warn(const std::string & warning) {
+  warn(warning, _default_ostr);
+}
+
+void LimitedWarning::warn(const std::string & warning, std::ostream * ostr) {
+  if (_this_warning_summary == 0) {
+    // prepare the information for the summary
+    _global_warnings_summary.push_back(Summary(warning, 0));
+    _this_warning_summary = & (_global_warnings_summary.back());
+  }
+  if (_n_warn_so_far < _max_warn) {
+    // prepare the warning within a string stream
+    ostringstream warnstr;
+    warnstr << "WARNING: ";
+    warnstr << warning;
+    _n_warn_so_far++;
+    if (_n_warn_so_far == _max_warn) warnstr << " (LAST SUCH WARNING)";
+    warnstr << std::endl;
+    // arrange for the whole warning to be output in one go (that way
+    // user can easily insert their own printout, e.g. event number
+    // before the warning string).
+    if (ostr) {
+      (*ostr) << warnstr.str();
+      ostr->flush(); // get something written to file even if the program aborts
+    }
+  }
+
+  // maintain the count, but do not allow overflow
+  if (_this_warning_summary->second < numeric_limits<unsigned>::max()) {
+    _this_warning_summary->second++;
+  }
+}
+
+//----------------------------------------------------------------------
+string LimitedWarning::summary() {
+  ostringstream str;
+  for (list<Summary>::const_iterator it = _global_warnings_summary.begin();
+       it != _global_warnings_summary.end(); it++) {
+    str << it->second << " times: " << it->first << endl;
+  }
+  return str.str();
+}
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/LimitedWarning.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/LimitedWarning.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/LimitedWarning.hh	(revision 5)
@@ -0,0 +1,89 @@
+#ifndef __FASTJET_LIMITEDWARNING_HH__
+#define __FASTJET_LIMITEDWARNING_HH__
+
+//STARTHEADER
+// $Id: LimitedWarning.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#include "fastjet/internal/base.hh"
+#include <iostream>
+#include <string>
+#include <list>
+
+FASTJET_BEGIN_NAMESPACE
+
+/// @ingroup error_handling
+/// \class LimitedWarning
+/// class to provide facilities for giving warnings up to some maximum
+/// number of times and to provide global summaries of warnings that have
+/// been issued.
+class LimitedWarning {
+public:
+  
+  /// constructor that provides a default maximum number of warnings
+  LimitedWarning() : _max_warn(_max_warn_default), _n_warn_so_far(0), _this_warning_summary(0) {}
+
+  /// constructor that provides a user-set max number of warnings
+  LimitedWarning(int max_warn) : _max_warn(max_warn), _n_warn_so_far(0), _this_warning_summary(0) {}
+
+  /// outputs a warning to standard error (or the user's default
+  /// warning stream if set)
+  void warn(const std::string & warning);
+
+  /// outputs a warning to the specified stream
+  void warn(const std::string & warning, std::ostream * ostr);
+
+  /// sets the default output stream for all warnings (by default
+  /// cerr; passing a null pointer prevents warnings from being output)
+  static void set_default_stream(std::ostream * ostr) {
+    _default_ostr = ostr;
+  }
+
+  /// sets the default maximum number of warnings of a given kind
+  /// before warning messages are silenced.
+  static void set_default_max_warn(int max_warn) {
+    _max_warn_default = max_warn;
+  }
+
+  /// returns a summary of all the warnings that came through the
+  /// LimiteWarning class
+  static std::string summary();
+
+private:
+  int _max_warn, _n_warn_so_far;
+  static int _max_warn_default;
+  static std::ostream * _default_ostr;
+  typedef std::pair<std::string, unsigned int> Summary;
+  static std::list< Summary > _global_warnings_summary;
+  Summary * _this_warning_summary;
+  
+};
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_LIMITEDWARNING_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/MinHeap.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/MinHeap.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/MinHeap.cc	(revision 5)
@@ -0,0 +1,127 @@
+//STARTHEADER
+// $Id: MinHeap.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/internal/MinHeap.hh"
+#include<iostream>
+#include<cmath>
+#include<limits>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+
+//----------------------------------------------------------------------
+/// construct the MinHeap; structure will be as follows:
+///   . _heap[0].minloc points to globally smallest entry
+///     _heap[1].minloc points to smallest entry in one half of heap
+///     _heap[2].minloc points to smallest entry in other half of heap
+///
+///   . for _heap[i], the "parent" is to be found at (i-1)/2
+void MinHeap::_initialise(const std::vector<double> & values){
+  
+  // fill the high-range of the heap with the largest possible value
+  // (minloc of each entry is itself)
+  for (unsigned i = values.size(); i < _heap.size(); i++) {
+    _heap[i].value = std::numeric_limits<double>::max();
+    _heap[i].minloc = &(_heap[i]);
+  }
+
+  // fill the rest of the heap with the actual values
+  // (minloc of each entry is itself)
+  for (unsigned i = 0; i < values.size(); i++) {
+    _heap[i].value = values[i];
+    _heap[i].minloc = &(_heap[i]);
+  }
+  
+  // now adjust the minlocs so that everything is OK...
+  for (unsigned i = _heap.size()-1; i > 0; i--) {
+    ValueLoc * parent = &(_heap[(i-1)/2]);
+    ValueLoc * here   = &(_heap[i]);
+    if (here->minloc->value < parent->minloc->value) {
+      parent->minloc = here->minloc;
+    }
+  }
+  //cout << minloc() << " "<<sqrt(minval())<<endl;
+  //cout << sqrt(_heap[47].value)<<endl;
+  //cout << sqrt(_heap[48].value)<<endl;
+  //cout << sqrt(_heap[25].value)<<endl;
+}
+
+
+//----------------------------------------------------------------------
+void MinHeap::update(unsigned int loc, double new_value) {
+  
+
+  assert(loc < _heap.size());
+  ValueLoc * start = &(_heap[loc]);
+
+  // if the minloc is somewhere below us and our value is no smaller
+  // than the previous value, we can't possibly change the minloc
+  if (start->minloc != start && !(new_value < start->minloc->value)) {
+    start->value = new_value;
+    //std::cout << "                     had easy exit\n";
+    return;
+  }
+
+  // update the value and put a temporary location
+  start->value = new_value;
+  start->minloc = start;
+  // warn that a change has been made at this place
+  bool change_made = true;
+  // to make sure we don't go off edge...
+  ValueLoc * heap_end = (&(_heap[0])) + _heap.size();
+
+  // now work our way up the heap
+  while(change_made) {
+    ValueLoc * here = &(_heap[loc]);
+    change_made     = false;
+
+    // if we were pointing to start, then we must re-initialise things
+    if (here->minloc == start) {
+      here->minloc = here; change_made = true;
+    }
+
+    // now compare current location to children (at 2*loc+1, 2*loc+2)
+    ValueLoc * child = &(_heap[2*loc+1]);
+    if (child < heap_end && child->minloc->value < here->minloc->value ) {
+      here->minloc = child->minloc;
+      change_made = true;}
+    child++;
+    if (child < heap_end && child->minloc->value < here->minloc->value ) {
+      here->minloc = child->minloc;
+      change_made = true;}
+    
+    // then we move up (loc ->(loc-1)/2) if there's anywhere to go 
+    if (loc == 0) {break;}
+    loc = (loc-1)/2;
+  }
+
+}
+
+FASTJET_END_NAMESPACE
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/NNH.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/NNH.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/NNH.hh	(revision 5)
@@ -0,0 +1,381 @@
+#ifndef __NNH_HH__
+#define __NNH_HH__
+
+//STARTHEADER
+// $Id: NNH.hh 2891 2012-06-15 12:47:59Z soyez $
+//
+// Copyright (c) 2009, Matteo Cacciari, Gavin Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include<fastjet/ClusterSequence.hh>
+
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+/// @ingroup advanced_usage
+/// \class _NoInfo
+/// dummy class, used as a default template argument
+class _NoInfo {};
+
+/// @ingroup advanced_usage
+/// \class NNHInfo
+/// template that will help initialise a BJ with a PseudoJet and extra information
+template<class I> class NNHInfo {
+public:
+  NNHInfo()         : _info(NULL) {}
+  NNHInfo(I * info) : _info(info) {}
+  template<class NNBJ> void init_jet(NNBJ * briefjet, const fastjet::PseudoJet & jet, int index) { briefjet->init(jet, index, _info);}
+private:
+  I * _info;
+};
+
+/// @ingroup advanced_usage
+/// Specialisation of NNHInfo for cases where there is no extra info
+template<> class NNHInfo<_NoInfo>  {
+public:
+  NNHInfo()           {}
+  NNHInfo(_NoInfo * ) {}
+  template<class NNBJ> void init_jet(NNBJ * briefjet, const fastjet::PseudoJet & jet, int index) { briefjet->init(jet, index);}
+};
+
+
+//----------------------------------------------------------------------
+/// @ingroup advanced_usage
+/// \class NNH
+/// Help solve closest pair problems with generic interparticle and
+/// beam distance.
+///
+/// Class to help solve closest pair problems with generic interparticle
+/// distances and a beam distance, using Anderberg's Nearest Neighbour
+/// Heuristic.
+///
+/// It is templated with a BJ (brief jet) class --- BJ should
+/// basically cache the minimal amount of information that is needed
+/// to efficiently calculate interparticle distances and particle-beam
+/// distances.
+///
+/// This class can be used with or without an extra "Information" template, 
+/// i.e. NNB<BJ> or NNH<BJ,I>
+/// 
+/// For the NNH<BJ> version of the class to function, BJ must provide 
+/// three member functions
+///  
+///  - void   BJ::init(const PseudoJet & jet);       // initialise with a PseudoJet
+///  - double BJ::distance(const BJ * other_bj_jet); // distance between this and other_bj_jet
+///  - double BJ::beam_distance()                  ; // distance to the beam
+///
+/// For the NNH<BJ,I> version to function, the BJ::init(...) member
+/// must accept an extra argument
+///
+///  - void   BJ::init(const PseudoJet & jet, I * info);   // initialise with a PseudoJet + info
+///
+/// where info might be a pointer to a class that contains, e.g., information
+/// about R, or other parameters of the jet algorithm 
+///
+/// For an example of how the NNH<BJ> class is used, see the Jade (and
+/// EECambridge) plugins
+///
+/// NB: the NNH algorithm is expected N^2, but has a worst case of
+/// N^3. Many QCD problems tend to place one closer to the N^3 end of
+/// the spectrum than one would like. There is scope for further
+/// progress (cf Eppstein, Cardinal & Eppstein), nevertheless the
+/// current class is already significantly faster than standard N^3
+/// implementations.
+///
+///
+/// Implementation note: this class derives from NNHInfo, which deals
+/// with storing any global information that is needed during the clustering
+
+template<class BJ, class I = _NoInfo> class NNH : public NNHInfo<I> {
+public:
+
+  /// constructor with an initial set of jets (which will be assigned indices
+  /// 0 ... jets.size()-1
+  NNH(const std::vector<PseudoJet> & jets) {start(jets);}
+  NNH(const std::vector<PseudoJet> & jets, I * info) : NNHInfo<I>(info) {start(jets);}
+  
+  void start(const std::vector<PseudoJet> & jets);
+
+  /// return the dij_min and indices iA, iB, for the corresponding jets.
+  /// If iB < 0 then iA recombines with the beam
+  double dij_min(int & iA, int & iB);
+
+  /// remove the jet pointed to by index iA
+  void remove_jet(int iA);
+
+  /// merge the jets pointed to by indices A and B and replace them with
+  /// jet, assigning it an index jet_index.
+  void merge_jets(int iA, int iB, const PseudoJet & jet, int jet_index);
+
+  /// a destructor
+  ~NNH() {
+    delete[] briefjets;
+  }
+    
+private:
+  class NNBJ; // forward declaration
+  
+  /// establish the nearest neighbour for jet, and cross check constistency
+  /// of distances for the other jets that are encountered. Assumes
+  /// jet not contained within begin...end
+  void set_NN_crosscheck(NNBJ * jet, NNBJ * begin, NNBJ * end);
+
+  /// establish the nearest neighbour for jet; don't cross check other jets'
+  /// distances and allow jet to be contained within begin...end
+  void set_NN_nocross   (NNBJ * jet, NNBJ * begin, NNBJ * end);
+
+  /// contains the briefjets
+  NNBJ * briefjets;
+
+  /// semaphores for the current extent of our structure
+  NNBJ * head, * tail;
+
+  /// currently active number of jets
+  int n;
+
+  /// where_is[i] contains a pointer to the jet with index i
+  std::vector<NNBJ *> where_is;
+
+  /// a class that wraps around the BJ, supplementing it with extra information
+  /// such as pointers to neighbours, etc.
+  class NNBJ : public BJ {
+  public:
+    void init(const PseudoJet & jet, int index_in) {
+      BJ::init(jet);
+      other_init(index_in);
+    }
+    void init(const PseudoJet & jet, int index_in, I * info) {
+      BJ::init(jet, info);
+      other_init(index_in);
+    }
+    void other_init(int index_in) {
+      _index = index_in;
+      NN_dist = BJ::beam_distance();
+      NN = NULL;
+    }
+    int index() const {return _index;}
+    
+    double NN_dist;
+    NNBJ * NN;
+    
+  private:
+    int _index;
+  };
+
+};
+
+
+
+//----------------------------------------------------------------------
+template<class BJ, class I> void NNH<BJ,I>::start(const std::vector<PseudoJet> & jets) {
+  n = jets.size();
+  briefjets = new NNBJ[n];
+  where_is.resize(2*n);
+
+  NNBJ * jetA = briefjets;
+  
+  // initialise the basic jet info 
+  for (int i = 0; i< n; i++) {
+    //jetA->init(jets[i], i);
+    this->init_jet(jetA, jets[i], i);
+    where_is[i] = jetA;
+    jetA++; // move on to next entry of briefjets
+  }
+  tail = jetA; // a semaphore for the end of briefjets
+  head = briefjets; // a nicer way of naming start
+
+  // now initialise the NN distances: jetA will run from 1..n-1; and
+  // jetB from 0..jetA-1
+  for (jetA = head + 1; jetA != tail; jetA++) {
+    // set NN info for jetA based on jets running from head..jetA-1,
+    // checking in the process whether jetA itself is an undiscovered
+    // NN of one of those jets.
+    set_NN_crosscheck(jetA, head, jetA);
+  }
+  //std::cout << "OOOO "  << briefjets[1].NN_dist << " " << briefjets[1].NN - briefjets << std::endl;
+}
+
+
+//----------------------------------------------------------------------
+template<class BJ, class I> double NNH<BJ,I>::dij_min(int & iA, int & iB) {
+  // find the minimum of the diJ on this round
+  double diJ_min = briefjets[0].NN_dist;
+  int diJ_min_jet = 0;
+  for (int i = 1; i < n; i++) {
+    if (briefjets[i].NN_dist < diJ_min) {
+      diJ_min_jet = i; 
+      diJ_min  = briefjets[i].NN_dist;
+    }
+  }
+  
+  // return information to user about recombination
+  NNBJ * jetA = & briefjets[diJ_min_jet];
+  //std::cout << jetA - briefjets << std::endl; 
+  iA = jetA->index();
+  iB = jetA->NN ? jetA->NN->index() : -1;
+  return diJ_min;
+}
+
+
+//----------------------------------------------------------------------
+// remove jetA from the list
+template<class BJ, class I> void NNH<BJ,I>::remove_jet(int iA) {
+  NNBJ * jetA = where_is[iA];
+  // now update our nearest neighbour info and diJ table
+  // first reduce size of table
+  tail--; n--;
+  // Copy last jet contents and diJ info into position of jetA
+  *jetA = *tail;
+  // update the info on where the given index is stored
+  where_is[jetA->index()] = jetA;
+
+  for (NNBJ * jetI = head; jetI != tail; jetI++) {
+    // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
+    if (jetI->NN == jetA) set_NN_nocross(jetI, head, tail);
+
+    // if jetI's NN is the new tail then relabel it so that it becomes jetA
+    if (jetI->NN == tail) {jetI->NN = jetA;}
+  }
+}
+
+
+//----------------------------------------------------------------------
+template<class BJ, class I> void NNH<BJ,I>::merge_jets(int iA, int iB, 
+					const PseudoJet & jet, int index) {
+
+  NNBJ * jetA = where_is[iA];
+  NNBJ * jetB = where_is[iB];
+
+  // If necessary relabel A & B to ensure jetB < jetA, that way if
+  // the larger of them == newtail then that ends up being jetA and 
+  // the new jet that is added as jetB is inserted in a position that
+  // has a future!
+  if (jetA < jetB) std::swap(jetA,jetB);
+
+  // initialise jetB based on the new jet
+  //jetB->init(jet, index);
+  this->init_jet(jetB, jet, index);
+  // and record its position (making sure we have the space)
+  if (index >= int(where_is.size())) where_is.resize(2*index);
+  where_is[jetB->index()] = jetB;
+
+  // now update our nearest neighbour info
+  // first reduce size of table
+  tail--; n--;
+  // Copy last jet contents into position of jetA
+  *jetA = *tail;
+  // update the info on where the tail's index is stored
+  where_is[jetA->index()] = jetA;
+
+  for (NNBJ * jetI = head; jetI != tail; jetI++) {
+    // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
+    if (jetI->NN == jetA || jetI->NN == jetB) {
+      set_NN_nocross(jetI, head, tail);
+    } 
+
+    // check whether new jetB is closer than jetI's current NN and
+    // if need be update things
+    double dist = jetI->distance(jetB);
+    if (dist < jetI->NN_dist) {
+      if (jetI != jetB) {
+	jetI->NN_dist = dist;
+	jetI->NN = jetB;
+      }
+    }
+    if (dist < jetB->NN_dist) {
+      if (jetI != jetB) {
+	jetB->NN_dist = dist;
+	jetB->NN      = jetI;
+      }
+    }
+
+    // if jetI's NN is the new tail then relabel it so that it becomes jetA
+    if (jetI->NN == tail) {jetI->NN = jetA;}
+  }
+}
+
+
+//----------------------------------------------------------------------
+// this function assumes that jet is not contained within begin...end
+template <class BJ, class I> void NNH<BJ,I>::set_NN_crosscheck(NNBJ * jet, 
+		    NNBJ * begin, NNBJ * end) {
+  double NN_dist = jet->beam_distance();
+  NNBJ * NN      = NULL;
+  for (NNBJ * jetB = begin; jetB != end; jetB++) {
+    double dist = jet->distance(jetB);
+    if (dist < NN_dist) {
+      NN_dist = dist;
+      NN = jetB;
+    }
+    if (dist < jetB->NN_dist) {
+      jetB->NN_dist = dist;
+      jetB->NN = jet;
+    }
+  }
+  jet->NN = NN;
+  jet->NN_dist = NN_dist;
+}
+
+
+//----------------------------------------------------------------------
+// set the NN for jet without checking whether in the process you might
+// have discovered a new nearest neighbour for another jet
+template <class BJ, class I>  void NNH<BJ,I>::set_NN_nocross(
+                 NNBJ * jet, NNBJ * begin, NNBJ * end) {
+  double NN_dist = jet->beam_distance();
+  NNBJ * NN      = NULL;
+  // if (head < jet) {
+  //   for (NNBJ * jetB = head; jetB != jet; jetB++) {
+  if (begin < jet) {
+    for (NNBJ * jetB = begin; jetB != jet; jetB++) {
+      double dist = jet->distance(jetB);
+      if (dist < NN_dist) {
+	NN_dist = dist;
+	NN = jetB;
+      }
+    }
+  }
+  // if (tail > jet) {
+  //   for (NNBJ * jetB = jet+1; jetB != tail; jetB++) {
+  if (end > jet) {
+    for (NNBJ * jetB = jet+1; jetB != end; jetB++) {
+      double dist = jet->distance (jetB);
+      if (dist < NN_dist) {
+	NN_dist = dist;
+	NN = jetB;
+      }
+    }
+  }
+  jet->NN = NN;
+  jet->NN_dist = NN_dist;
+}
+
+
+
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
+
+
+#endif // __NNH_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/PseudoJet.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/PseudoJet.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/PseudoJet.cc	(revision 5)
@@ -0,0 +1,864 @@
+//STARTHEADER
+// $Id: PseudoJet.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#include "fastjet/Error.hh"
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/ClusterSequenceAreaBase.hh"
+#include "fastjet/CompositeJetStructure.hh"
+#include<valarray>
+#include<iostream>
+#include<sstream>
+#include<cmath>
+#include<algorithm>
+#include <cstdarg>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+
+
+//----------------------------------------------------------------------
+// another constructor...
+PseudoJet::PseudoJet(const double px_in, const double py_in, const double pz_in, const double E_in) {
+  
+  _E  = E_in ;
+  _px = px_in;
+  _py = py_in;
+  _pz = pz_in;
+
+  this->_finish_init();
+
+  // some default values for the history and user indices
+  _reset_indices();
+
+}
+
+
+//----------------------------------------------------------------------
+/// do standard end of initialisation
+void PseudoJet::_finish_init () {
+  _kt2 = this->px()*this->px() + this->py()*this->py();
+  _phi = pseudojet_invalid_phi;
+}
+
+//----------------------------------------------------------------------
+void PseudoJet::_set_rap_phi() const {
+
+  if (_kt2 == 0.0) {
+    _phi = 0.0; } 
+  else {
+    _phi = atan2(this->py(),this->px());
+  }
+  if (_phi < 0.0) {_phi += twopi;}
+  if (_phi >= twopi) {_phi -= twopi;} // can happen if phi=-|eps<1e-15|?
+  if (this->E() == abs(this->pz()) && _kt2 == 0) {
+    // Point has infinite rapidity -- convert that into a very large
+    // number, but in such a way that different 0-pt momenta will have
+    // different rapidities (so as to lift the degeneracy between
+    // them) [this can be relevant at parton-level]
+    double MaxRapHere = MaxRap + abs(this->pz());
+    if (this->pz() >= 0.0) {_rap = MaxRapHere;} else {_rap = -MaxRapHere;}
+  } else {
+    // get the rapidity in a way that's modestly insensitive to roundoff
+    // error when things pz,E are large (actually the best we can do without
+    // explicit knowledge of mass)
+    double effective_m2 = max(0.0,m2()); // force non tachyonic mass
+    double E_plus_pz    = _E + abs(_pz); // the safer of p+, p-
+    // p+/p- = (p+ p-) / (p-)^2 = (kt^2+m^2)/(p-)^2
+    _rap = 0.5*log((_kt2 + effective_m2)/(E_plus_pz*E_plus_pz));
+    if (_pz > 0) {_rap = - _rap;}
+  }
+
+}
+
+
+//----------------------------------------------------------------------
+// return a valarray four-momentum
+valarray<double> PseudoJet::four_mom() const {
+  valarray<double> mom(4);
+  mom[0] = _px;
+  mom[1] = _py;
+  mom[2] = _pz;
+  mom[3] = _E ;
+  return mom;
+}
+
+//----------------------------------------------------------------------
+// Return the component corresponding to the specified index.
+// taken from CLHEP
+double PseudoJet::operator () (int i) const {
+  switch(i) {
+  case X:
+    return px();
+  case Y:
+    return py();
+  case Z:
+    return pz();
+  case T:
+    return e();
+  default:
+    ostringstream err;
+    err << "PseudoJet subscripting: bad index (" << i << ")";
+    throw Error(err.str());
+  }
+  return 0.;
+}  
+
+//----------------------------------------------------------------------
+// return the pseudorapidity
+double PseudoJet::pseudorapidity() const {
+  if (px() == 0.0 && py() ==0.0) return MaxRap;
+  if (pz() == 0.0) return 0.0;
+
+  double theta = atan(perp()/pz());
+  if (theta < 0) theta += pi;
+  return -log(tan(theta/2));
+}
+
+//----------------------------------------------------------------------
+// return "sum" of two pseudojets
+PseudoJet operator+ (const PseudoJet & jet1, const PseudoJet & jet2) {
+  //return PseudoJet(jet1.four_mom()+jet2.four_mom());
+  return PseudoJet(jet1.px()+jet2.px(),
+		   jet1.py()+jet2.py(),
+		   jet1.pz()+jet2.pz(),
+		   jet1.E() +jet2.E()  );
+} 
+
+//----------------------------------------------------------------------
+// return difference of two pseudojets
+PseudoJet operator- (const PseudoJet & jet1, const PseudoJet & jet2) {
+  //return PseudoJet(jet1.four_mom()-jet2.four_mom());
+  return PseudoJet(jet1.px()-jet2.px(),
+		   jet1.py()-jet2.py(),
+		   jet1.pz()-jet2.pz(),
+		   jet1.E() -jet2.E()  );
+} 
+
+//----------------------------------------------------------------------
+// return the product, coeff * jet
+PseudoJet operator* (double coeff, const PseudoJet & jet) {
+  //return PseudoJet(coeff*jet.four_mom());
+  // the following code is hopefully more efficient
+  PseudoJet coeff_times_jet(jet);
+  coeff_times_jet *= coeff;
+  return coeff_times_jet;
+} 
+
+//----------------------------------------------------------------------
+// return the product, coeff * jet
+PseudoJet operator* (const PseudoJet & jet, double coeff) {
+  return coeff*jet;
+} 
+
+//----------------------------------------------------------------------
+// return the ratio, jet / coeff
+PseudoJet operator/ (const PseudoJet & jet, double coeff) {
+  return (1.0/coeff)*jet;
+} 
+
+//----------------------------------------------------------------------
+/// multiply the jet's momentum by the coefficient
+void PseudoJet::operator*=(double coeff) {
+  _px *= coeff;
+  _py *= coeff;
+  _pz *= coeff;
+  _E  *= coeff;
+  _kt2*= coeff*coeff;
+  // phi and rap are unchanged
+}
+
+//----------------------------------------------------------------------
+/// divide the jet's momentum by the coefficient
+void PseudoJet::operator/=(double coeff) {
+  (*this) *= 1.0/coeff;
+}
+
+
+//----------------------------------------------------------------------
+/// add the other jet's momentum to this jet
+void PseudoJet::operator+=(const PseudoJet & other_jet) {
+  _px += other_jet._px;
+  _py += other_jet._py;
+  _pz += other_jet._pz;
+  _E  += other_jet._E ;
+  _finish_init(); // we need to recalculate phi,rap,kt2
+}
+
+
+//----------------------------------------------------------------------
+/// subtract the other jet's momentum from this jet
+void PseudoJet::operator-=(const PseudoJet & other_jet) {
+  _px -= other_jet._px;
+  _py -= other_jet._py;
+  _pz -= other_jet._pz;
+  _E  -= other_jet._E ;
+  _finish_init(); // we need to recalculate phi,rap,kt2
+}
+
+//----------------------------------------------------------------------
+bool operator==(const PseudoJet & a, const PseudoJet & b) {
+  if (a.px() != b.px()) return false;
+  if (a.py() != b.py()) return false;
+  if (a.pz() != b.pz()) return false;
+  if (a.E () != b.E ()) return false;
+  
+  if (a.user_index()    != b.user_index()) return false;
+  if (a.cluster_hist_index() != b.cluster_hist_index()) return false;
+  if (a.user_info_ptr() != b.user_info_ptr()) return false;
+  if (a.structure_ptr() != b.structure_ptr()) return false;
+
+  return true;
+}
+
+//----------------------------------------------------------------------
+// check if the jet has zero momentum
+bool operator==(const PseudoJet & jet, const double val) {
+  if (val != 0) 
+    throw Error("comparing a PseudoJet with a non-zero constant (double) is not allowed.");
+  return (jet.px() == 0 && jet.py() == 0 && 
+	  jet.pz() == 0 && jet.E() == 0);
+}
+
+
+
+//----------------------------------------------------------------------
+/// transform this jet (given in lab) into a jet in the rest
+/// frame of prest
+//
+// NB: code adapted from that in herwig f77 (checked how it worked
+// long ago)
+PseudoJet & PseudoJet::boost(const PseudoJet & prest) {
+  
+  if (prest.px() == 0.0 && prest.py() == 0.0 && prest.pz() == 0.0) 
+    return *this;
+
+  double m_local = prest.m();
+  assert(m_local != 0);
+
+  double pf4  = (  px()*prest.px() + py()*prest.py()
+                 + pz()*prest.pz() + E()*prest.E() )/m_local;
+  double fn   = (pf4 + E()) / (prest.E() + m_local);
+  _px +=  fn*prest.px();
+  _py +=  fn*prest.py();
+  _pz +=  fn*prest.pz();
+  _E = pf4;
+
+  _finish_init(); // we need to recalculate phi,rap,kt2
+  return *this;
+}
+
+
+//----------------------------------------------------------------------
+/// transform this jet (given in the rest frame of prest) into a jet
+/// in the lab frame;
+//
+// NB: code adapted from that in herwig f77 (checked how it worked
+// long ago)
+PseudoJet & PseudoJet::unboost(const PseudoJet & prest) {
+  
+  if (prest.px() == 0.0 && prest.py() == 0.0 && prest.pz() == 0.0) 
+    return *this;
+
+  double m_local = prest.m();
+  assert(m_local != 0);
+
+  double pf4  = ( -px()*prest.px() - py()*prest.py()
+                 - pz()*prest.pz() + E()*prest.E() )/m_local;
+  double fn   = (pf4 + E()) / (prest.E() + m_local);
+  _px -=  fn*prest.px();
+  _py -=  fn*prest.py();
+  _pz -=  fn*prest.pz();
+  _E = pf4;
+
+  _finish_init(); // we need to recalculate phi,rap,kt2
+  return *this;
+}
+
+
+//----------------------------------------------------------------------
+/// returns true if the momenta of the two input jets are identical
+bool have_same_momentum(const PseudoJet & jeta, const PseudoJet & jetb) {
+  return jeta.px() == jetb.px()
+    &&   jeta.py() == jetb.py()
+    &&   jeta.pz() == jetb.pz()
+    &&   jeta.E()  == jetb.E();
+}
+
+//----------------------------------------------------------------------
+void PseudoJet::set_cached_rap_phi(double rap_in, double phi_in) {
+  _rap = rap_in; _phi = phi_in;
+  if (_phi >= twopi) _phi -= twopi;
+  if (_phi < 0)      _phi += twopi;
+}
+
+//----------------------------------------------------------------------
+void PseudoJet::reset_momentum_PtYPhiM(double pt_in, double y_in, double phi_in, double m_in) {
+  assert(phi_in < 2*twopi && phi_in > -twopi);
+  double ptm = (m_in == 0) ? pt_in : sqrt(pt_in*pt_in+m_in*m_in);
+  double exprap = exp(y_in);
+  double pminus = ptm/exprap;
+  double pplus  = ptm*exprap;
+  double px_local = pt_in*cos(phi_in);
+  double py_local = pt_in*sin(phi_in);
+  reset_momentum(px_local,py_local,0.5*(pplus-pminus),0.5*(pplus+pminus));
+  set_cached_rap_phi(y_in,phi_in);
+}
+
+//----------------------------------------------------------------------
+/// return a pseudojet with the given pt, y, phi and mass
+PseudoJet PtYPhiM(double pt, double y, double phi, double m) {
+  assert(phi < 2*twopi && phi > -twopi);
+  double ptm = (m == 0) ? pt : sqrt(pt*pt+m*m);
+  double exprap = exp(y);
+  double pminus = ptm/exprap;
+  double pplus  = ptm*exprap;
+  double px = pt*cos(phi);
+  double py = pt*sin(phi);
+  PseudoJet mom(px,py,0.5*(pplus-pminus),0.5*(pplus+pminus));
+  mom.set_cached_rap_phi(y,phi);
+  return mom;
+  //return PseudoJet(pt*cos(phi), pt*sin(phi), ptm*sinh(y), ptm*cosh(y));
+}
+
+
+//----------------------------------------------------------------------
+// return kt-distance between this jet and another one
+double PseudoJet::kt_distance(const PseudoJet & other) const {
+  //double distance = min(this->kt2(), other.kt2());
+  double distance = min(_kt2, other._kt2);
+  double dphi = abs(phi() - other.phi());
+  if (dphi > pi) {dphi = twopi - dphi;}
+  double drap = rap() - other.rap();
+  distance = distance * (dphi*dphi + drap*drap);
+  return distance;
+}
+
+
+//----------------------------------------------------------------------
+// return squared cylinder (eta-phi) distance between this jet and another one
+double PseudoJet::plain_distance(const PseudoJet & other) const {
+  double dphi = abs(phi() - other.phi());
+  if (dphi > pi) {dphi = twopi - dphi;}
+  double drap = rap() - other.rap();
+  return (dphi*dphi + drap*drap);
+}
+
+//----------------------------------------------------------------------
+/// returns other.phi() - this.phi(), i.e. the phi distance to
+/// other, constrained to be in range -pi .. pi
+double PseudoJet::delta_phi_to(const PseudoJet & other) const {
+  double dphi = other.phi() - phi();
+  if (dphi >  pi) dphi -= twopi;
+  if (dphi < -pi) dphi += twopi;
+  return dphi;
+}
+
+
+string PseudoJet::description() const{
+  // the "default" case of a PJ which does not belong to any cluster sequence
+  if (!_structure())
+    return "standard PseudoJet (with no associated clustering information)";
+  
+  // for all the other cases, the description comes from the structure
+  return _structure()->description();
+}
+
+
+
+//----------------------------------------------------------------------
+//
+// The following methods access the associated jet structure (if any)
+//
+//----------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------
+// check whether this PseudoJet has an associated parent
+// ClusterSequence
+bool PseudoJet::has_associated_cluster_sequence() const{
+  return (_structure()) && (_structure->has_associated_cluster_sequence());
+}
+
+//----------------------------------------------------------------------
+// get a (const) pointer to the associated ClusterSequence (NULL if
+// inexistent)
+const ClusterSequence* PseudoJet::associated_cluster_sequence() const{
+  if (! has_associated_cluster_sequence()) return NULL;
+
+  return _structure->associated_cluster_sequence();
+}
+
+
+//----------------------------------------------------------------------
+// check whether this PseudoJet has an associated parent
+// ClusterSequence that is still valid
+bool PseudoJet::has_valid_cluster_sequence() const{
+  return (_structure()) && (_structure->has_valid_cluster_sequence());
+}
+
+//----------------------------------------------------------------------
+// If there is a valid cluster sequence associated with this jet,
+// returns a pointer to it; otherwise throws an Error.
+//
+// Open question: should these errors be upgraded to classes of their
+// own so that they can be caught? [Maybe, but later]
+const ClusterSequence * PseudoJet::validated_cs() const {
+  return validated_structure_ptr()->validated_cs();
+}
+
+
+//----------------------------------------------------------------------
+// set the associated structure
+void PseudoJet::set_structure_shared_ptr(const SharedPtr<PseudoJetStructureBase> &structure_in){
+  _structure = structure_in;
+}
+
+//----------------------------------------------------------------------
+// return true if there is some strusture associated with this PseudoJet
+bool PseudoJet::has_structure() const{
+  return _structure();
+}
+
+//----------------------------------------------------------------------
+// return a pointer to the structure (of type
+// PseudoJetStructureBase*) associated with this PseudoJet.
+//
+// return NULL if there is no associated structure
+const PseudoJetStructureBase* PseudoJet::structure_ptr() const {
+  if (!_structure()) return NULL;
+  return _structure();
+}
+  
+//----------------------------------------------------------------------
+// return a non-const pointer to the structure (of type
+// PseudoJetStructureBase*) associated with this PseudoJet.
+//
+// return NULL if there is no associated structure
+//
+// Only use this if you know what you are doing. In any case,
+// prefer the 'structure_ptr()' (the const version) to this method,
+// unless you really need a write access to the PseudoJet's
+// underlying structure.
+PseudoJetStructureBase* PseudoJet::structure_non_const_ptr(){
+  if (!_structure()) return NULL;
+  return _structure();
+}
+  
+//----------------------------------------------------------------------
+// return a pointer to the structure (of type
+// PseudoJetStructureBase*) associated with this PseudoJet.
+//
+// throw an error if there is no associated structure
+const PseudoJetStructureBase* PseudoJet::validated_structure_ptr() const {
+  if (!_structure()) 
+    throw Error("Trying to access the structure of a PseudoJet which has no associated structure");
+  return _structure();
+}
+  
+//----------------------------------------------------------------------
+// return a reference to the shared pointer to the
+// PseudoJetStructureBase associated with this PseudoJet
+const SharedPtr<PseudoJetStructureBase> & PseudoJet::structure_shared_ptr() const {
+  return _structure;
+}
+
+
+//----------------------------------------------------------------------
+// check if it has been recombined with another PseudoJet in which
+// case, return its partner through the argument. Otherwise,
+// 'partner' is set to 0.
+//
+// false is also returned if this PseudoJet has no associated
+// ClusterSequence
+bool PseudoJet::has_partner(PseudoJet &partner) const{
+  return validated_structure_ptr()->has_partner(*this, partner);
+}
+
+//----------------------------------------------------------------------
+// check if it has been recombined with another PseudoJet in which
+// case, return its child through the argument. Otherwise, 'child'
+// is set to 0.
+// 
+// false is also returned if this PseudoJet has no associated
+// ClusterSequence, with the child set to 0
+bool PseudoJet::has_child(PseudoJet &child) const{
+  return validated_structure_ptr()->has_child(*this, child);
+}
+
+//----------------------------------------------------------------------
+// check if it is the product of a recombination, in which case
+// return the 2 parents through the 'parent1' and 'parent2'
+// arguments. Otherwise, set these to 0.
+//
+// false is also returned if this PseudoJet has no parent
+// ClusterSequence
+bool PseudoJet::has_parents(PseudoJet &parent1, PseudoJet &parent2) const{
+  return validated_structure_ptr()->has_parents(*this, parent1, parent2);
+}
+
+//----------------------------------------------------------------------
+// check if the current PseudoJet contains the one passed as
+// argument
+//
+// false is also returned if this PseudoJet has no associated
+// ClusterSequence.
+bool PseudoJet::contains(const PseudoJet &constituent) const{
+  return validated_structure_ptr()->object_in_jet(constituent, *this);
+}
+
+//----------------------------------------------------------------------
+// check if the current PseudoJet is contained the one passed as
+// argument
+//
+// false is also returned if this PseudoJet has no associated
+// ClusterSequence
+bool PseudoJet::is_inside(const PseudoJet &jet) const{
+  return validated_structure_ptr()->object_in_jet(*this, jet);
+}
+
+
+//----------------------------------------------------------------------
+// returns true if the PseudoJet has constituents
+bool PseudoJet::has_constituents() const{
+  return (_structure()) && (_structure->has_constituents());
+}
+
+//----------------------------------------------------------------------
+// retrieve the constituents.
+vector<PseudoJet> PseudoJet::constituents() const{
+  return validated_structure_ptr()->constituents(*this);
+}
+
+
+//----------------------------------------------------------------------
+// returns true if the PseudoJet has support for exclusive subjets
+bool PseudoJet::has_exclusive_subjets() const{
+  return (_structure()) && (_structure->has_exclusive_subjets());
+}
+
+//----------------------------------------------------------------------
+// return a vector of all subjets of the current jet (in the sense
+// of the exclusive algorithm) that would be obtained when running
+// the algorithm with the given dcut. 
+//
+// Time taken is O(m ln m), where m is the number of subjets that
+// are found. If m gets to be of order of the total number of
+// constituents in the jet, this could be substantially slower than
+// just getting that list of constituents.
+//
+// an Error is thrown if this PseudoJet has no currently valid
+// associated ClusterSequence
+std::vector<PseudoJet> PseudoJet::exclusive_subjets (const double & dcut) const {
+  return validated_structure_ptr()->exclusive_subjets(*this, dcut);
+}
+
+//----------------------------------------------------------------------
+// return the size of exclusive_subjets(...); still n ln n with same
+// coefficient, but marginally more efficient than manually taking
+// exclusive_subjets.size()
+//
+// an Error is thrown if this PseudoJet has no currently valid
+// associated ClusterSequence
+int PseudoJet::n_exclusive_subjets(const double & dcut) const {
+  return validated_structure_ptr()->n_exclusive_subjets(*this, dcut);
+}
+
+//----------------------------------------------------------------------
+// return the list of subjets obtained by unclustering the supplied
+// jet down to n subjets (or all constituents if there are fewer
+// than n).
+//
+// requires n ln n time
+//
+// an Error is thrown if this PseudoJet has no currently valid
+// associated ClusterSequence
+std::vector<PseudoJet> PseudoJet::exclusive_subjets_up_to (int nsub) const {
+  return validated_structure_ptr()->exclusive_subjets_up_to(*this, nsub);
+}
+
+//----------------------------------------------------------------------
+// Same as exclusive_subjets_up_to but throws an error if there are
+// fewer than nsub particles in the jet
+std::vector<PseudoJet> PseudoJet::exclusive_subjets (int nsub) const {
+  vector<PseudoJet> subjets = exclusive_subjets_up_to(nsub);
+  if (int(subjets.size()) < nsub) {
+    ostringstream err;
+    err << "Requested " << nsub << " exclusive subjets, but there were only " 
+	<< subjets.size() << " particles in the jet";
+    throw Error(err.str());
+  }
+  return subjets;
+}
+
+//----------------------------------------------------------------------
+// return the dij that was present in the merging nsub+1 -> nsub 
+// subjets inside this jet.
+//
+// an Error is thrown if this PseudoJet has no currently valid
+// associated ClusterSequence
+double PseudoJet::exclusive_subdmerge(int nsub) const {
+  return validated_structure_ptr()->exclusive_subdmerge(*this, nsub);
+}
+
+//----------------------------------------------------------------------
+// return the maximum dij that occurred in the whole event at the
+// stage that the nsub+1 -> nsub merge of subjets occurred inside 
+// this jet.
+//
+// an Error is thrown if this PseudoJet has no currently valid
+// associated ClusterSequence
+double PseudoJet::exclusive_subdmerge_max(int nsub) const {
+  return validated_structure_ptr()->exclusive_subdmerge_max(*this, nsub);
+}
+
+
+// returns true if a jet has pieces
+//
+// By default a single particle or a jet coming from a
+// ClusterSequence have no pieces and this methos will return false.
+bool PseudoJet::has_pieces() const{
+  return ((_structure()) && (_structure->has_pieces(*this)));
+}
+
+// retrieve the pieces that make up the jet. 
+//
+// By default a jet does not have pieces.
+// If the underlying interface supports "pieces" retrieve the
+// pieces from there.
+std::vector<PseudoJet> PseudoJet::pieces() const{
+  return validated_structure_ptr()->pieces(*this);
+  // if (!has_pieces())
+  //   throw Error("Trying to retrieve the pieces of a PseudoJet that has no support for pieces.");
+  //
+  // return _structure->pieces(*this);
+}
+
+
+//----------------------------------------------------------------------
+// the following ones require a computation of the area in the
+// associated ClusterSequence (See ClusterSequenceAreaBase for details)
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+// if possible, return a valid ClusterSequenceAreaBase pointer; otherwise
+// throw an error
+const ClusterSequenceAreaBase * PseudoJet::validated_csab() const {
+  const ClusterSequenceAreaBase *csab = dynamic_cast<const ClusterSequenceAreaBase*>(validated_cs());
+  if (csab == NULL) throw Error("you requested jet-area related information, but the PseudoJet does not have associated area information.");
+  return csab;
+}
+
+
+//----------------------------------------------------------------------
+// check if it has a defined area
+bool PseudoJet::has_area() const{
+  //if (! has_associated_cluster_sequence()) return false;
+  if (! has_structure()) return false;
+  return (validated_structure_ptr()->has_area() != 0);
+}
+
+//----------------------------------------------------------------------
+// return the jet (scalar) area.
+// throw an Error if there is no support for area in the associated CS
+double PseudoJet::area() const{
+  return validated_structure_ptr()->area(*this);
+}
+
+//----------------------------------------------------------------------
+// return the error (uncertainty) associated with the determination
+// of the area of this jet.
+// throws an Error if there is no support for area in the associated CS
+double PseudoJet::area_error() const{
+  return validated_structure_ptr()->area_error(*this);
+}
+
+//----------------------------------------------------------------------
+// return the jet 4-vector area
+// throws an Error if there is no support for area in the associated CS
+PseudoJet PseudoJet::area_4vector() const{
+  return validated_structure_ptr()->area_4vector(*this);
+}
+
+//----------------------------------------------------------------------
+// true if this jet is made exclusively of ghosts
+// throws an Error if there is no support for area in the associated CS
+bool PseudoJet::is_pure_ghost() const{
+  return validated_structure_ptr()->is_pure_ghost(*this);
+}
+
+
+//----------------------------------------------------------------------
+//
+// end of the methods accessing the information in the associated
+// Cluster Sequence
+//
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+/// provide a meaningful error message for InexistentUserInfo
+PseudoJet::InexistentUserInfo::InexistentUserInfo() : Error("you attempted to perform a dynamic cast of a PseudoJet's extra info, but the extra info pointer was null")
+{}
+
+
+//----------------------------------------------------------------------
+// sort the indices so that values[indices[0..n-1]] is sorted
+// into increasing order 
+void sort_indices(vector<int> & indices, 
+			 const vector<double> & values) {
+  IndexedSortHelper index_sort_helper(&values);
+  sort(indices.begin(), indices.end(), index_sort_helper);
+}
+
+
+
+//----------------------------------------------------------------------
+/// given a vector of values with a one-to-one correspondence with the
+/// vector of objects, sort objects into an order such that the
+/// associated values would be in increasing order
+template<class T> vector<T>  objects_sorted_by_values(
+                       const vector<T> & objects, 
+		       const vector<double> & values) {
+
+  assert(objects.size() == values.size());
+
+  // get a vector of indices
+  vector<int> indices(values.size());
+  for (size_t i = 0; i < indices.size(); i++) {indices[i] = i;}
+  
+  // sort the indices
+  sort_indices(indices, values);
+  
+  // copy the objects 
+  vector<T> objects_sorted(objects.size());
+  
+  // place the objects in the correct order
+  for (size_t i = 0; i < indices.size(); i++) {
+    objects_sorted[i] = objects[indices[i]];
+  }
+
+  return objects_sorted;
+}
+
+//----------------------------------------------------------------------
+/// return a vector of jets sorted into decreasing kt2
+vector<PseudoJet> sorted_by_pt(const vector<PseudoJet> & jets) {
+  vector<double> minus_kt2(jets.size());
+  for (size_t i = 0; i < jets.size(); i++) {minus_kt2[i] = -jets[i].kt2();}
+  return objects_sorted_by_values(jets, minus_kt2);
+}
+
+//----------------------------------------------------------------------
+/// return a vector of jets sorted into increasing rapidity
+vector<PseudoJet> sorted_by_rapidity(const vector<PseudoJet> & jets) {
+  vector<double> rapidities(jets.size());
+  for (size_t i = 0; i < jets.size(); i++) {rapidities[i] = jets[i].rap();}
+  return objects_sorted_by_values(jets, rapidities);
+}
+
+//----------------------------------------------------------------------
+/// return a vector of jets sorted into decreasing energy
+vector<PseudoJet> sorted_by_E(const vector<PseudoJet> & jets) {
+  vector<double> energies(jets.size());
+  for (size_t i = 0; i < jets.size(); i++) {energies[i] = -jets[i].E();}
+  return objects_sorted_by_values(jets, energies);
+}
+
+//----------------------------------------------------------------------
+/// return a vector of jets sorted into increasing pz
+vector<PseudoJet> sorted_by_pz(const vector<PseudoJet> & jets) {
+  vector<double> pz(jets.size());
+  for (size_t i = 0; i < jets.size(); i++) {pz[i] = jets[i].pz();}
+  return objects_sorted_by_values(jets, pz);
+}
+
+
+
+//-------------------------------------------------------------------------------
+// helper functions to build a jet made of pieces
+//-------------------------------------------------------------------------------
+
+// build a "CompositeJet" from the vector of its pieces
+//
+// In this case, E-scheme recombination is assumed to compute the
+// total momentum
+PseudoJet join(const vector<PseudoJet> & pieces){
+  // compute the total momentum
+  //--------------------------------------------------
+  PseudoJet result;  // automatically initialised to 0
+  for (unsigned int i=0; i<pieces.size(); i++)
+    result += pieces[i];
+
+  // attach a CompositeJetStructure to the result
+  //--------------------------------------------------
+  CompositeJetStructure *cj_struct = new CompositeJetStructure(pieces);
+
+  result.set_structure_shared_ptr(SharedPtr<PseudoJetStructureBase>(cj_struct));
+
+  return result;
+}
+
+// build a "CompositeJet" from a single PseudoJet
+PseudoJet join(const PseudoJet & j1){
+  return join(vector<PseudoJet>(1,j1));
+}
+
+// build a "CompositeJet" from two PseudoJet
+PseudoJet join(const PseudoJet & j1, const PseudoJet & j2){
+  vector<PseudoJet> pieces;
+  pieces.push_back(j1);
+  pieces.push_back(j2);
+  return join(pieces);
+}
+
+// build a "CompositeJet" from 3 PseudoJet
+PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3){
+  vector<PseudoJet> pieces;
+  pieces.push_back(j1);
+  pieces.push_back(j2);
+  pieces.push_back(j3);
+  return join(pieces);
+}
+
+// build a "CompositeJet" from 4 PseudoJet
+PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3, const PseudoJet & j4){
+  vector<PseudoJet> pieces;
+  pieces.push_back(j1);
+  pieces.push_back(j2);
+  pieces.push_back(j3);
+  pieces.push_back(j4);
+  return join(pieces);
+}
+
+
+
+
+FASTJET_END_NAMESPACE
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/PseudoJet.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/PseudoJet.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/PseudoJet.hh	(revision 5)
@@ -0,0 +1,996 @@
+//STARTHEADER
+// $Id: PseudoJet.hh 2728 2011-11-20 14:18:59Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_PSEUDOJET_HH__
+#define __FASTJET_PSEUDOJET_HH__
+
+#include<valarray>
+#include<vector>
+#include<cassert>
+#include<cmath>
+#include<iostream>
+#include "fastjet/internal/numconsts.hh"
+#include "fastjet/internal/IsBase.hh"
+#include "fastjet/SharedPtr.hh"
+#include "fastjet/Error.hh"
+#include "fastjet/PseudoJetStructureBase.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//using namespace std;
+
+/// Used to protect against parton-level events where pt can be zero
+/// for some partons, giving rapidity=infinity. KtJet fails in those cases.
+const double MaxRap = 1e5;
+
+/// default value for phi, meaning it (and rapidity) have yet to be calculated) 
+const double pseudojet_invalid_phi = -100.0;
+
+// forward definition
+class ClusterSequenceAreaBase;
+
+/// @ingroup basic_classes
+/// \class PseudoJet
+/// Class to contain pseudojets, including minimal information of use to
+/// jet-clustering routines.
+class PseudoJet {
+
+ public:
+  //----------------------------------------------------------------------
+  /// @name Constructors and destructor
+  //\{
+  /// default constructor, which as of FJ3.0 provides an object for
+  /// which all operations are now valid and which has zero momentum
+  ///
+  // (cf. this is actually OK from a timing point of view and in some
+  // cases better than just having the default constructor for the
+  // internal shared pointer: see PJtiming.cc and the notes therein)
+  PseudoJet() : _px(0), _py(0), _pz(0), _E(0) {_finish_init(); _reset_indices();}
+  /// construct a pseudojet from explicit components
+  PseudoJet(const double px, const double py, const double pz, const double E);
+
+  /// constructor from any object that has px,py,pz,E = some_four_vector[0--3],
+  template <class L> PseudoJet(const L & some_four_vector);
+
+  // Constructor that performs minimal initialisation (only that of
+  // the shared pointers), of use in certain speed-critical contexts
+  //
+  // NB: "dummy" is commented to avoid unused-variable compiler warnings
+  PseudoJet(bool /* dummy */) {}
+
+  /// default (virtual) destructor
+  virtual ~PseudoJet(){};
+  //\} ---- end of constructors and destructors --------------------------
+
+  //----------------------------------------------------------------------
+  /// @name Kinematic access functions
+  //\{
+  //----------------------------------------------------------------------
+  inline double E()   const {return _E;}
+  inline double e()   const {return _E;} // like CLHEP
+  inline double px()  const {return _px;}
+  inline double py()  const {return _py;}
+  inline double pz()  const {return _pz;}
+
+  /// returns phi (in the range 0..2pi)
+  inline double phi() const {return phi_02pi();}
+
+  /// returns phi in the range -pi..pi
+  inline double phi_std()  const {
+    _ensure_valid_rap_phi();
+    return _phi > pi ? _phi-twopi : _phi;}
+
+  /// returns phi in the range 0..2pi
+  inline double phi_02pi() const {
+    _ensure_valid_rap_phi();
+    return _phi;
+  }
+
+  /// returns the rapidity or some large value when the rapidity
+  /// is infinite
+  inline double rap() const {
+    _ensure_valid_rap_phi();
+    return _rap;
+  }
+
+  /// the same as rap()
+  inline double rapidity() const {return rap();} // like CLHEP
+
+  /// returns the pseudo-rapidity or some large value when the
+  /// rapidity is infinite
+  double pseudorapidity() const;
+  double eta() const {return pseudorapidity();}
+
+  /// returns the squared transverse momentum
+  inline double pt2() const {return _kt2;}
+  /// returns the scalar transverse momentum
+  inline double  pt() const {return sqrt(_kt2);} 
+  /// returns the squared transverse momentum
+  inline double perp2() const {return _kt2;}  // like CLHEP
+  /// returns the scalar transverse momentum
+  inline double  perp() const {return sqrt(_kt2);}    // like CLHEP
+  /// returns the squared transverse momentum
+  inline double kt2() const {return _kt2;} // for bkwds compatibility
+
+  /// returns the squared invariant mass // like CLHEP
+  inline double  m2() const {return (_E+_pz)*(_E-_pz)-_kt2;}    
+  /// returns the invariant mass 
+  /// (If m2() is negative then -sqrt(-m2()) is returned, as in CLHEP)
+  inline double  m() const;    
+
+  /// returns the squared transverse mass = kt^2+m^2
+  inline double mperp2() const {return (_E+_pz)*(_E-_pz);}
+  /// returns the transverse mass = sqrt(kt^2+m^2)
+  inline double mperp() const {return sqrt(std::abs(mperp2()));}
+  /// returns the squared transverse mass = kt^2+m^2
+  inline double mt2() const {return (_E+_pz)*(_E-_pz);}
+  /// returns the transverse mass = sqrt(kt^2+m^2)
+  inline double mt() const {return sqrt(std::abs(mperp2()));}
+
+  /// return the squared 3-vector modulus = px^2+py^2+pz^2
+  inline double modp2() const {return _kt2+_pz*_pz;}
+  /// return the 3-vector modulus = sqrt(px^2+py^2+pz^2)
+  inline double modp() const {return sqrt(_kt2+_pz*_pz);}
+
+  /// return the transverse energy
+  inline double Et() const {return (_kt2==0) ? 0.0 : _E/sqrt(1.0+_pz*_pz/_kt2);}
+  /// return the transverse energy squared
+  inline double Et2() const {return (_kt2==0) ? 0.0 : _E*_E/(1.0+_pz*_pz/_kt2);}
+
+  /// returns component i, where X==0, Y==1, Z==2, E==3
+  double operator () (int i) const ; 
+  /// returns component i, where X==0, Y==1, Z==2, E==3
+  inline double operator [] (int i) const { return (*this)(i); }; // this too
+
+
+
+  /// returns kt distance (R=1) between this jet and another
+  double kt_distance(const PseudoJet & other) const;
+
+  /// returns squared cylinder (rap-phi) distance between this jet and another
+  double plain_distance(const PseudoJet & other) const;
+  /// returns squared cylinder (rap-phi) distance between this jet and
+  /// another
+  inline double squared_distance(const PseudoJet & other) const {
+    return plain_distance(other);}
+
+  /// return the cylinder (rap-phi) distance between this jet and another,
+  /// \f$\Delta_R = \sqrt{\Delta y^2 + \Delta \phi^2}\f$.
+  inline double delta_R(const PseudoJet & other) const {
+    return sqrt(squared_distance(other));
+  }
+
+  /// returns other.phi() - this.phi(), constrained to be in 
+  /// range -pi .. pi
+  double delta_phi_to(const PseudoJet & other) const;
+
+  //// this seemed to compile except if it was used
+  //friend inline double 
+  //  kt_distance(const PseudoJet & jet1, const PseudoJet & jet2) { 
+  //                                      return jet1.kt_distance(jet2);}
+
+  /// returns distance between this jet and the beam
+  inline double beam_distance() const {return _kt2;}
+
+  /// return a valarray containing the four-momentum (components 0-2
+  /// are 3-mom, component 3 is energy).
+  std::valarray<double> four_mom() const;
+
+  //\}  ------- end of kinematic access functions
+
+  // taken from CLHEP
+  enum { X=0, Y=1, Z=2, T=3, NUM_COORDINATES=4, SIZE=NUM_COORDINATES };
+
+
+  //----------------------------------------------------------------------
+  /// @name Kinematic modification functions
+  //\{
+  //----------------------------------------------------------------------
+  /// transform this jet (given in the rest frame of prest) into a jet
+  /// in the lab frame [NOT FULLY TESTED]
+  PseudoJet & boost(const PseudoJet & prest);
+  /// transform this jet (given in lab) into a jet in the rest
+  /// frame of prest  [NOT FULLY TESTED]
+  PseudoJet & unboost(const PseudoJet & prest);
+
+  void operator*=(double);
+  void operator/=(double);
+  void operator+=(const PseudoJet &);
+  void operator-=(const PseudoJet &);
+
+  /// reset the 4-momentum according to the supplied components and
+  /// put the user and history indices back to their default values
+  inline void reset(double px, double py, double pz, double E);
+
+  /// reset the PseudoJet to be equal to psjet (including its
+  /// indices); NB if the argument is derived from a PseudoJet then
+  /// the "reset" used will be the templated version
+  ///
+  /// Note: this is included on top of the templated version because
+  /// PseudoJet is not "derived" from PseudoJet, so the templated
+  /// reset would not handle this case properly.
+  inline void reset(const PseudoJet & psjet) {
+    (*this) = psjet;
+  }
+
+  /// reset the 4-momentum according to the supplied generic 4-vector
+  /// (accessible via indexing, [0]==px,...[3]==E) and put the user
+  /// and history indices back to their default values.
+  template <class L> inline void reset(const L & some_four_vector) {
+    // check if some_four_vector can be cast to a PseudoJet
+    //
+    // Note that a regular dynamic_cast would not work here because
+    // there is no guarantee that L is polymorphic. We use a more
+    // complex construct here that works also in such a case. As for
+    // dynamic_cast, NULL is returned if L is not derived from
+    // PseudoJet
+    const PseudoJet * pj = cast_if_derived<const PseudoJet>(&some_four_vector);
+
+    if (pj){
+      (*this) = *pj;
+    } else {
+      reset(some_four_vector[0], some_four_vector[1],
+	    some_four_vector[2], some_four_vector[3]);
+    }
+  }
+
+  /// reset the PseudoJet according to the specified pt, rapidity,
+  /// azimuth and mass (also resetting indices, etc.)
+  /// (phi should satisfy -2pi<phi<4pi)
+  inline void reset_PtYPhiM(double pt_in, double y_in, double phi_in, double m_in=0.0) {
+    reset_momentum_PtYPhiM(pt_in, y_in, phi_in, m_in);
+    _reset_indices();
+  }
+
+  /// reset the 4-momentum according to the supplied components 
+  /// but leave all other information (indices, user info, etc.)
+  /// untouched
+  inline void reset_momentum(double px, double py, double pz, double E);
+
+  /// reset the 4-momentum according to the components of the supplied
+  /// PseudoJet, including cached components; note that the template
+  /// version (below) will be called for classes derived from PJ.
+  inline void reset_momentum(const PseudoJet & pj);
+
+  /// reset the 4-momentum according to the specified pt, rapidity,
+  /// azimuth and mass (phi should satisfy -2pi<phi<4pi)
+  void reset_momentum_PtYPhiM(double pt, double y, double phi, double m=0.0);
+
+  /// reset the 4-momentum according to the supplied generic 4-vector
+  /// (accessible via indexing, [0]==px,...[3]==E), but leave all
+  /// other information (indices, user info, etc.)  untouched
+  template <class L> inline void reset_momentum(const L & some_four_vector) {
+    reset_momentum(some_four_vector[0], some_four_vector[1],
+		   some_four_vector[2], some_four_vector[3]);
+  }
+
+  /// in some cases when setting a 4-momentum, the user/program knows
+  /// what rapidity and azimuth are associated with that 4-momentum;
+  /// by calling this routine the user can provide the information
+  /// directly to the PseudoJet and avoid expensive rap-phi
+  /// recalculations.
+  ///
+  /// - \param rap  rapidity
+  /// - \param phi  (in range -twopi...4*pi)
+  ///
+  /// USE WITH CAUTION: there are no checks that the rapidity and
+  /// azimuth supplied are sensible, nor does this reset the
+  /// 4-momentum components if things don't match.
+  void set_cached_rap_phi(double rap, double phi);
+
+
+  //\} --- end of kin mod functions ------------------------------------
+
+  //----------------------------------------------------------------------
+  /// @name User index functions
+  ///
+  /// To allow the user to set and access an integer index which can
+  /// be exploited by the user to associate extra information with a
+  /// particle/jet (for example pdg id, or an indication of a
+  /// particle's origin within the user's analysis)
+  //
+  //\{
+
+  /// return the user_index, 
+  inline int user_index() const {return _user_index;}
+  /// set the user_index, intended to allow the user to add simple
+  /// identifying information to a particle/jet
+  inline void set_user_index(const int index) {_user_index = index;}
+
+  //\} ----- end of use index functions ---------------------------------
+
+  //----------------------------------------------------------------------
+  /// @name User information types and functions
+  ///
+  /// Allows PseudoJet to carry extra user info (as an object derived from
+  /// UserInfoBase).
+  //\{
+
+  /// @ingroup user_info
+  /// \class UserInfoBase
+  /// a base class to hold extra user information in a PseudoJet
+  ///
+  /// This is a base class to help associate extra user information
+  /// with a jet. The user should store their information in a class
+  /// derived from this. This allows information of arbitrary
+  /// complexity to be easily associated with a PseudoJet (in contrast
+  /// to the user index). For example, in a Monte Carlo simulation,
+  /// the user information might include the PDG ID, and the position
+  /// of the production vertex for the particle.
+  ///
+  /// The PseudoJet is able to store a shared pointer to any object
+  /// derived from UserInfo. The use of a shared pointer frees the
+  /// user of the need to handle the memory management associated with
+  /// the information.
+  ///
+  /// Having the user information derive from a common base class also
+  /// facilitates dynamic casting, etc.
+  ///
+  class UserInfoBase{
+  public:
+    // dummy ctor
+    UserInfoBase(){};
+
+    // dummy virtual dtor
+    // makes it polymorphic to allow for dynamic_cast
+    virtual ~UserInfoBase(){}; 
+  };
+
+  /// error class to be thrown if accessing user info when it doesn't
+  /// exist
+  class InexistentUserInfo : public Error {
+  public:
+    InexistentUserInfo();
+  };
+
+  /// sets the internal shared pointer to the user information.
+  ///
+  /// Note that the PseudoJet will now _own_ the pointer, and delete
+  /// the corresponding object when it (the jet, and any copies of the jet)
+  /// goes out of scope. 
+  void set_user_info(UserInfoBase * user_info_in) {
+    _user_info.reset(user_info_in);
+  }
+
+  /// returns a reference to the dynamic cast conversion of user_info
+  /// to type L.
+  ///
+  /// Usage: suppose you have previously set the user info with a pointer
+  /// to an object of type MyInfo, 
+  ///
+  ///   class MyInfo: public PseudoJet::UserInfoBase {
+  ///      MyInfo(int id) : _pdg_id(id);
+  ///      int pdg_id() const {return _pdg_id;}
+  ///      int _pdg_id;
+  ///   };
+  ///
+  ///   PseudoJet particle(...);
+  ///   particle.set_user_info(new MyInfo(its_pdg_id));
+  ///
+  /// Then you would access that pdg_id() as
+  ///
+  ///   particle.user_info<MyInfo>().pdg_id();
+  ///
+  /// It's overkill for just a single integer, but scales easily to
+  /// more extensive information.
+  ///
+  /// Note that user_info() throws an InexistentUserInfo() error if
+  /// there is no user info; throws a std::bad_cast if the conversion
+  /// doesn't work
+  ///
+  /// If this behaviour does not fit your needs, use instead the the
+  /// user_info_ptr() or user_info_shared_ptr() member functions.
+  template<class L>
+  const L & user_info() const{
+    if (_user_info.get() == 0) throw InexistentUserInfo();
+    return dynamic_cast<const L &>(* _user_info.get());
+  }
+
+  /// returns true if the PseudoJet has user information
+  bool has_user_info() const{
+    return _user_info.get();
+  }
+
+  /// returns true if the PseudoJet has user information than can be
+  /// cast to the template argument type.
+  template<class L>
+  bool has_user_info() const{
+    return _user_info.get() && dynamic_cast<const L *>(_user_info.get());
+  }
+
+  /// retrieve a pointer to the (const) user information
+  const UserInfoBase * user_info_ptr() const{
+    if (!_user_info()) return NULL;
+    return _user_info.get();
+  }
+
+
+  /// retrieve a (const) shared pointer to the user information
+  const SharedPtr<UserInfoBase> & user_info_shared_ptr() const{
+    return _user_info;
+  }
+
+  /// retrieve a (non-const) shared pointer to the user information;
+  /// you can use this, for example, to set the shared pointer, eg
+  ///
+  /// \code
+  ///   p2.user_info_shared_ptr() = p1.user_info_shared_ptr();
+  /// \endcode
+  ///
+  /// or 
+  ///
+  /// \code
+  ///   SharedPtr<PseudoJet::UserInfoBase> info_shared(new MyInfo(...));
+  ///   p2.user_info_shared_ptr() = info_shared;
+  /// \endcode
+  SharedPtr<UserInfoBase> & user_info_shared_ptr(){
+    return _user_info;
+  }
+
+  // \} --- end of extra info functions ---------------------------------
+
+  //----------------------------------------------------------------------
+  /// @name Description
+  ///
+  /// Since a PseudoJet can have a structure that contains a variety
+  /// of information, we provide a description that allows one to check
+  /// exactly what kind of PseudoJet we are dealing with
+  //
+  //\{
+
+  /// return a string describing what kind of PseudoJet we are dealing with 
+  std::string description() const;
+
+  //\} ----- end of description functions ---------------------------------
+
+  //-------------------------------------------------------------
+  /// @name Access to the associated ClusterSequence object.
+  ///
+  /// In addition to having kinematic information, jets may contain a
+  /// reference to an associated ClusterSequence (this is the case,
+  /// for example, if the jet has been returned by a ClusterSequence
+  /// member function).
+  //\{
+  //-------------------------------------------------------------
+  /// returns true if this PseudoJet has an associated ClusterSequence.
+  bool has_associated_cluster_sequence() const;
+  /// shorthand for has_associated_cluster_sequence()
+  bool has_associated_cs() const {return has_associated_cluster_sequence();}
+
+  /// returns true if this PseudoJet has an associated and still
+  /// valid(ated) ClusterSequence.
+  bool has_valid_cluster_sequence() const;
+  /// shorthand for has_valid_cluster_sequence()
+  bool has_valid_cs() const {return has_valid_cluster_sequence();}
+
+  /// get a (const) pointer to the parent ClusterSequence (NULL if
+  /// inexistent)
+  const ClusterSequence* associated_cluster_sequence() const;
+  // shorthand for associated_cluster_sequence()
+  const ClusterSequence* associated_cs() const {return associated_cluster_sequence();}
+
+  /// if the jet has a valid associated cluster sequence then return a
+  /// pointer to it; otherwise throw an error
+  inline const ClusterSequence * validated_cluster_sequence() const {
+    return validated_cs();
+  }
+  /// shorthand for validated_cluster_sequence()
+  const ClusterSequence * validated_cs() const;
+
+  /// if the jet has valid area information then return a pointer to
+  /// the associated ClusterSequenceAreaBase object; otherwise throw an error
+  inline const ClusterSequenceAreaBase * validated_cluster_sequence_area_base() const {
+    return validated_csab();
+  }
+
+  /// shorthand for validated_cluster_sequence_area_base()
+  const ClusterSequenceAreaBase * validated_csab() const;
+  //\}
+
+  //-------------------------------------------------------------
+  /// @name Access to the associated PseudoJetStructureBase object.
+  ///
+  /// In addition to having kinematic information, jets may contain a
+  /// reference to an associated ClusterSequence (this is the case,
+  /// for example, if the jet has been returned by a ClusterSequence
+  /// member function).
+  //\{
+  //-------------------------------------------------------------
+
+  /// set the associated structure
+  void set_structure_shared_ptr(const SharedPtr<PseudoJetStructureBase> &structure);
+
+  /// return true if there is some structure associated with this PseudoJet
+  bool has_structure() const;
+
+  /// return a pointer to the structure (of type
+  /// PseudoJetStructureBase*) associated with this PseudoJet.
+  ///
+  /// return NULL if there is no associated structure
+  const PseudoJetStructureBase* structure_ptr() const;
+  
+  /// return a non-const pointer to the structure (of type
+  /// PseudoJetStructureBase*) associated with this PseudoJet.
+  ///
+  /// return NULL if there is no associated structure
+  ///
+  /// Only use this if you know what you are doing. In any case,
+  /// prefer the 'structure_ptr()' (the const version) to this method,
+  /// unless you really need a write access to the PseudoJet's
+  /// underlying structure.
+  PseudoJetStructureBase* structure_non_const_ptr();
+  
+  /// return a pointer to the structure (of type
+  /// PseudoJetStructureBase*) associated with this PseudoJet.
+  ///
+  /// throw an error if there is no associated structure
+  const PseudoJetStructureBase* validated_structure_ptr() const;
+  
+  /// return a reference to the shared pointer to the
+  /// PseudoJetStructureBase associated with this PseudoJet
+  const SharedPtr<PseudoJetStructureBase> & structure_shared_ptr() const;
+
+  /// returns a reference to the structure casted to the requested
+  /// structure type
+  ///
+  /// If there is no sructure associated, an Error is thrown.
+  /// If the type is not met, a std::bad_cast error is thrown.
+  template<typename StructureType>
+  const StructureType & structure() const;
+
+  /// check if the PseudoJet has the structure resulting from a Transformer 
+  /// (that is, its structure is compatible with a Transformer::StructureType).
+  /// If there is no structure, false is returned.
+  template<typename TransformerType>
+  bool has_structure_of() const;
+
+  /// this is a helper to access any structure created by a Transformer 
+  /// (that is, of type Transformer::StructureType).
+  ///
+  /// If there is no structure, or if the structure is not compatible
+  /// with TransformerType, an error is thrown.
+  template<typename TransformerType>
+  const typename TransformerType::StructureType & structure_of() const;
+
+  //\}
+
+  //-------------------------------------------------------------
+  /// @name Methods for access to information about jet structure
+  ///
+  /// These allow access to jet constituents, and other jet
+  /// subtructure information. They only work if the jet is associated
+  /// with a ClusterSequence.
+  //-------------------------------------------------------------
+  //\{
+
+  /// check if it has been recombined with another PseudoJet in which
+  /// case, return its partner through the argument. Otherwise,
+  /// 'partner' is set to 0.
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  virtual bool has_partner(PseudoJet &partner) const;
+
+  /// check if it has been recombined with another PseudoJet in which
+  /// case, return its child through the argument. Otherwise, 'child'
+  /// is set to 0.
+  /// 
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  virtual bool has_child(PseudoJet &child) const;
+
+  /// check if it is the product of a recombination, in which case
+  /// return the 2 parents through the 'parent1' and 'parent2'
+  /// arguments. Otherwise, set these to 0.
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  virtual bool has_parents(PseudoJet &parent1, PseudoJet &parent2) const;
+
+  /// check if the current PseudoJet contains the one passed as
+  /// argument.
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  virtual bool contains(const PseudoJet &constituent) const;
+
+  /// check if the current PseudoJet is contained the one passed as
+  /// argument.
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  virtual bool is_inside(const PseudoJet &jet) const;
+
+
+  /// returns true if the PseudoJet has constituents
+  virtual bool has_constituents() const;
+
+  /// retrieve the constituents. 
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence or other substructure information
+  virtual std::vector<PseudoJet> constituents() const;
+
+
+  /// returns true if the PseudoJet has support for exclusive subjets
+  virtual bool has_exclusive_subjets() const;
+
+  /// return a vector of all subjets of the current jet (in the sense
+  /// of the exclusive algorithm) that would be obtained when running
+  /// the algorithm with the given dcut. 
+  ///
+  /// Time taken is O(m ln m), where m is the number of subjets that
+  /// are found. If m gets to be of order of the total number of
+  /// constituents in the jet, this could be substantially slower than
+  /// just getting that list of constituents.
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  std::vector<PseudoJet> exclusive_subjets (const double & dcut) const;
+
+  /// return the size of exclusive_subjets(...); still n ln n with same
+  /// coefficient, but marginally more efficient than manually taking
+  /// exclusive_subjets.size()
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  int n_exclusive_subjets(const double & dcut) const;
+
+  /// return the list of subjets obtained by unclustering the supplied
+  /// jet down to nsub subjets. Throws an error if there are fewer than
+  /// nsub particles in the jet.
+  ///
+  /// For ClusterSequence type jets, requires nsub ln nsub time
+  ///
+  /// An Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  std::vector<PseudoJet> exclusive_subjets (int nsub) const;
+
+  /// return the list of subjets obtained by unclustering the supplied
+  /// jet down to nsub subjets (or all constituents if there are fewer
+  /// than nsub).
+  ///
+  /// For ClusterSequence type jets, requires nsub ln nsub time
+  ///
+  /// An Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  std::vector<PseudoJet> exclusive_subjets_up_to (int nsub) const;
+
+  /// return the dij that was present in the merging nsub+1 -> nsub 
+  /// subjets inside this jet.
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  double exclusive_subdmerge(int nsub) const;
+
+  /// return the maximum dij that occurred in the whole event at the
+  /// stage that the nsub+1 -> nsub merge of subjets occurred inside 
+  /// this jet.
+  ///
+  /// an Error is thrown if this PseudoJet has no currently valid
+  /// associated ClusterSequence
+  double exclusive_subdmerge_max(int nsub) const;
+
+
+  /// returns true if a jet has pieces
+  ///
+  /// By default a single particle or a jet coming from a
+  /// ClusterSequence have no pieces and this methos will return false.
+  ///
+  /// In practice, this is equivalent to have an structure of type
+  /// CompositeJetStructure.
+  virtual bool has_pieces() const;
+
+
+  /// retrieve the pieces that make up the jet. 
+  ///
+  /// If the jet does not support pieces, an error is throw
+  virtual std::vector<PseudoJet> pieces() const;
+
+
+  // the following ones require a computation of the area in the
+  // parent ClusterSequence (See ClusterSequenceAreaBase for details)
+  //------------------------------------------------------------------
+
+  /// check if it has a defined area
+  virtual bool has_area() const;
+
+  /// return the jet (scalar) area.
+  /// throws an Error if there is no support for area in the parent CS
+  virtual double area() const;
+
+  /// return the error (uncertainty) associated with the determination
+  /// of the area of this jet.
+  /// throws an Error if there is no support for area in the parent CS
+  virtual double area_error() const;
+
+  /// return the jet 4-vector area.
+  /// throws an Error if there is no support for area in the parent CS
+  virtual PseudoJet area_4vector() const;
+
+  /// true if this jet is made exclusively of ghosts.
+  /// throws an Error if there is no support for area in the parent CS
+  virtual bool is_pure_ghost() const;
+
+  //\} --- end of jet structure -------------------------------------
+
+
+
+  //----------------------------------------------------------------------
+  /// @name Members mainly intended for internal use
+  //----------------------------------------------------------------------
+  //\{
+  /// return the cluster_hist_index, intended to be used by clustering
+  /// routines.
+  inline int cluster_hist_index() const {return _cluster_hist_index;}
+  /// set the cluster_hist_index, intended to be used by clustering routines.
+  inline void set_cluster_hist_index(const int index) {_cluster_hist_index = index;}
+
+  /// alternative name for cluster_hist_index() [perhaps more meaningful]
+  inline int cluster_sequence_history_index() const {
+    return cluster_hist_index();}
+  /// alternative name for set_cluster_hist_index(...) [perhaps more
+  /// meaningful]
+  inline void set_cluster_sequence_history_index(const int index) {
+    set_cluster_hist_index(index);}
+
+  //\} ---- end of internal use functions ---------------------------
+
+ protected:  
+
+  SharedPtr<PseudoJetStructureBase> _structure;
+  SharedPtr<UserInfoBase> _user_info;
+
+
+ private: 
+  // NB: following order must be kept for things to behave sensibly...
+  double _px,_py,_pz,_E;
+  mutable double _phi, _rap;
+  double _kt2; 
+  int    _cluster_hist_index, _user_index;
+
+  /// calculate phi, rap, kt2 based on the 4-momentum components
+  void _finish_init();
+  /// set the indices to default values
+  void _reset_indices();
+
+  /// ensure that the internal values for rapidity and phi 
+  /// correspond to 4-momentum structure
+  inline void _ensure_valid_rap_phi() const {
+    if (_phi == pseudojet_invalid_phi) _set_rap_phi();
+  }
+
+  /// set cached rapidity and phi values
+  void _set_rap_phi() const;
+};
+
+
+//----------------------------------------------------------------------
+// routines for basic binary operations
+
+PseudoJet operator+(const PseudoJet &, const PseudoJet &);
+PseudoJet operator-(const PseudoJet &, const PseudoJet &);
+PseudoJet operator*(double, const PseudoJet &);
+PseudoJet operator*(const PseudoJet &, double);
+PseudoJet operator/(const PseudoJet &, double);
+
+/// returns true if the 4 momentum components of the two PseudoJets
+/// are identical and all the internal indices (user, cluster_history)
+/// + structure and user-info shared pointers are too
+bool operator==(const PseudoJet &, const PseudoJet &);
+
+/// inequality test which is exact opposite of operator==
+inline bool operator!=(const PseudoJet & a, const PseudoJet & b) {return !(a==b);}
+
+/// Can only be used with val=0 and tests whether all four
+/// momentum components are equal to val (=0.0)
+bool operator==(const PseudoJet & jet, const double val);
+
+/// Can only be used with val=0 and tests whether at least one of the
+/// four momentum components is different from val (=0.0)
+inline bool operator!=(const PseudoJet & a, const double & val) {return !(a==val);}
+
+inline double dot_product(const PseudoJet & a, const PseudoJet & b) {
+  return a.E()*b.E() - a.px()*b.px() - a.py()*b.py() - a.pz()*b.pz();
+}
+
+/// returns true if the momenta of the two input jets are identical
+bool have_same_momentum(const PseudoJet &, const PseudoJet &);
+
+/// return a pseudojet with the given pt, y, phi and mass
+/// (phi should satisfy -2pi<phi<4pi)
+PseudoJet PtYPhiM(double pt, double y, double phi, double m = 0.0);
+
+//----------------------------------------------------------------------
+// Routines to do with providing sorted arrays of vectors.
+
+/// return a vector of jets sorted into decreasing transverse momentum
+std::vector<PseudoJet> sorted_by_pt(const std::vector<PseudoJet> & jets);
+
+/// return a vector of jets sorted into increasing rapidity
+std::vector<PseudoJet> sorted_by_rapidity(const std::vector<PseudoJet> & jets);
+
+/// return a vector of jets sorted into decreasing energy
+std::vector<PseudoJet> sorted_by_E(const std::vector<PseudoJet> & jets);
+
+/// return a vector of jets sorted into increasing pz
+std::vector<PseudoJet> sorted_by_pz(const std::vector<PseudoJet> & jets);
+
+//----------------------------------------------------------------------
+// some code to help sorting
+
+/// sort the indices so that values[indices[0->n-1]] is sorted
+/// into increasing order 
+void sort_indices(std::vector<int> & indices, 
+		  const std::vector<double> & values);
+
+/// given a vector of values with a one-to-one correspondence with the
+/// vector of objects, sort objects into an order such that the
+/// associated values would be in increasing order (but don't actually
+/// touch the values vector in the process).
+template<class T> std::vector<T> objects_sorted_by_values(const std::vector<T> & objects, 
+					      const std::vector<double> & values);
+
+/// \if internal_doc
+/// @ingroup internal
+/// \class IndexedSortHelper
+/// a class that helps us carry out indexed sorting.
+/// \endif
+class IndexedSortHelper {
+public:
+  inline IndexedSortHelper (const std::vector<double> * reference_values) {
+    _ref_values = reference_values;
+  };
+  inline int operator() (const int & i1, const int & i2) const {
+    return  (*_ref_values)[i1] < (*_ref_values)[i2];
+  };
+private:
+  const std::vector<double> * _ref_values;
+};
+
+
+//----------------------------------------------------------------------
+/// constructor from any object that has px,py,pz,E = some_four_vector[0--3],
+// NB: do not know if it really needs to be inline, but when it wasn't
+//     linking failed with g++ (who knows what was wrong...)
+template <class L> inline  PseudoJet::PseudoJet(const L & some_four_vector) {
+  reset(some_four_vector);
+}
+
+//----------------------------------------------------------------------
+inline void PseudoJet::_reset_indices() { 
+  set_cluster_hist_index(-1);
+  set_user_index(-1);
+  _structure.reset();
+  _user_info.reset();
+}
+
+
+// taken literally from CLHEP
+inline double PseudoJet::m() const {
+  double mm = m2();
+  return mm < 0.0 ? -std::sqrt(-mm) : std::sqrt(mm);
+}
+
+
+inline void PseudoJet::reset(double px_in, double py_in, double pz_in, double E_in) {
+  _px = px_in;
+  _py = py_in;
+  _pz = pz_in;
+  _E  = E_in;
+  _finish_init();
+  _reset_indices();
+}
+
+inline void PseudoJet::reset_momentum(double px_in, double py_in, double pz_in, double E_in) {
+  _px = px_in;
+  _py = py_in;
+  _pz = pz_in;
+  _E  = E_in;
+  _finish_init();
+}
+
+inline void PseudoJet::reset_momentum(const PseudoJet & pj) {
+  _px  = pj._px ;
+  _py  = pj._py ;
+  _pz  = pj._pz ;
+  _E   = pj._E  ;
+  _phi = pj._phi;
+  _rap = pj._rap;
+  _kt2 = pj._kt2;
+}
+
+//-------------------------------------------------------------------------------
+// implementation of the templated accesses to the underlying structyre
+//-------------------------------------------------------------------------------
+
+// returns a reference to the structure casted to the requested
+// structure type
+//
+// If there is no sructure associated, an Error is thrown.
+// If the type is not met, a std::bad_cast error is thrown.
+template<typename StructureType>
+const StructureType & PseudoJet::structure() const{
+  return dynamic_cast<const StructureType &>(* validated_structure_ptr());
+  
+}
+
+// check if the PseudoJet has the structure resulting from a Transformer 
+// (that is, its structure is compatible with a Transformer::StructureType)
+template<typename TransformerType>
+bool PseudoJet::has_structure_of() const{
+  if (!_structure()) return false;
+
+  return dynamic_cast<const typename TransformerType::StructureType *>(_structure.get()) != 0;
+}
+
+// this is a helper to access a structure created by a Transformer 
+// (that is, of type Transformer::StructureType)
+// NULL is returned if the corresponding type is not met
+template<typename TransformerType>
+const typename TransformerType::StructureType & PseudoJet::structure_of() const{
+  if (!_structure()) 
+    throw Error("Trying to access the structure of a PseudoJet without an associated structure");
+
+  return dynamic_cast<const typename TransformerType::StructureType &>(*_structure);
+}
+
+
+
+//-------------------------------------------------------------------------------
+// helper functions to build a jet made of pieces
+//
+// Note that there are more complete versions of these functions, with
+// an additional argument for a recombination scheme, in
+// JetDefinition.hh
+// -------------------------------------------------------------------------------
+
+/// build a "CompositeJet" from the vector of its pieces
+///
+/// In this case, E-scheme recombination is assumed to compute the
+/// total momentum
+PseudoJet join(const std::vector<PseudoJet> & pieces);
+
+/// build a MergedJet from a single PseudoJet
+PseudoJet join(const PseudoJet & j1);
+
+/// build a MergedJet from 2 PseudoJet
+PseudoJet join(const PseudoJet & j1, const PseudoJet & j2);
+
+/// build a MergedJet from 3 PseudoJet
+PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3);
+
+/// build a MergedJet from 4 PseudoJet
+PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3, const PseudoJet & j4);
+
+
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_PSEUDOJET_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/PseudoJetStructureBase.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/PseudoJetStructureBase.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/PseudoJetStructureBase.cc	(revision 5)
@@ -0,0 +1,225 @@
+//STARTHEADER
+// $Id: PseudoJetStructureBase.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#include "fastjet/PseudoJetStructureBase.hh"
+#include "fastjet/Error.hh"
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/ClusterSequenceAreaBase.hh"
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+// PseudoJetStructureBase implementation
+//
+// Contains any information related to the clustering that should be
+// directly accessible to PseudoJet.
+//
+// By default, this class implements basic access to the
+// ClusterSequence related to a PseudoJet (like its constituents or
+// its area). But it can be overloaded in order e.g. to give access
+// to the jet substructure.
+//
+// Note that it accesses the underlying ClusterSequence through a
+// ClusterSequenceWrapper object so it can check when the former goes
+// out of scope.
+//
+
+
+//-------------------------------------------------------------
+// Direct access to the associated ClusterSequence object.
+//
+// Get access to the associated ClusterSequence (if any)
+//-------------------------------------------------------------
+
+// get a (const) pointer to the parent ClusterSequence (NULL if
+// inexistent)
+const ClusterSequence* PseudoJetStructureBase::associated_cluster_sequence() const{
+  return NULL;
+}
+  
+// if the jet has a valid associated cluster sequence then return a
+// pointer to it; otherwise throw an error
+//
+// by default, an Error is thrown
+const ClusterSequence * PseudoJetStructureBase::validated_cs() const{
+  throw Error("This PseudoJet structure is not associated with a valid ClusterSequence");
+}
+
+// if the jet has valid area information then return a pointer to
+// the associated ClusterSequenceAreaBase object; otherwise throw an error
+//
+// by default, an Error is thrown
+const ClusterSequenceAreaBase * PseudoJetStructureBase::validated_csab() const{
+  throw Error("This PseudoJet structure is not associated with a valid cluster sequence with area");
+}
+
+
+//-------------------------------------------------------------
+// Methods for access to information about jet structure
+//
+// These allow access to jet constituents, and other jet
+// subtructure information. They only work if the jet is associated
+// with a ClusterSequence.
+//-------------------------------------------------------------
+
+// check if it has been recombined with another PseudoJet in which
+// case, return its partner through the argument. Otherwise,
+// 'partner' is set to 0.
+//
+// by default, an Error is thrown
+bool PseudoJetStructureBase::has_partner(const PseudoJet & /*reference */, PseudoJet & /*partner*/) const{
+  throw Error("This PseudoJet structure has no implementation for has_partner");
+}
+
+// check if it has been recombined with another PseudoJet in which
+// case, return its child through the argument. Otherwise, 'child'
+// is set to 0.
+// 
+// by default, an Error is thrown
+bool PseudoJetStructureBase::has_child(const PseudoJet & /*reference*/, PseudoJet & /*child*/) const{
+  throw Error("This PseudoJet structure has no implementation for has_child");
+}
+
+// check if it is the product of a recombination, in which case
+// return the 2 parents through the 'parent1' and 'parent2'
+// arguments. Otherwise, set these to 0.
+//
+// by default, an Error is thrown
+bool PseudoJetStructureBase::has_parents(const PseudoJet & /*reference*/, PseudoJet &/*parent1*/, PseudoJet &/*parent2*/) const{
+  throw Error("This PseudoJet structure has no implementation for has_parents");
+}
+
+// check if the reference PseudoJet is contained in the second one
+// passed as argument.
+//
+// by default, an Error is thrown
+bool PseudoJetStructureBase::object_in_jet(const PseudoJet & /*reference*/, const PseudoJet & /*jet*/) const{
+  throw Error("This PseudoJet structure has no implementation for is_inside");
+}
+
+// retrieve the constituents. 
+//
+// by default, an Error is thrown
+vector<PseudoJet> PseudoJetStructureBase::constituents(const PseudoJet &/*reference*/) const{
+  throw Error("This PseudoJet structure has no implementation for constituents");
+}
+
+// return a vector of all subjets of the current jet (in the sense
+// of the exclusive algorithm) that would be obtained when running
+// the algorithm with the given dcut. 
+//
+// Time taken is O(m ln m), where m is the number of subjets that
+// are found. If m gets to be of order of the total number of
+// constituents in the jet, this could be substantially slower than
+// just getting that list of constituents.
+//
+// by default, an Error is thrown
+vector<PseudoJet> PseudoJetStructureBase::exclusive_subjets (const PseudoJet & /*reference*/, const double & /*dcut*/) const{
+  throw Error("This PseudoJet structure has no implementation for exclusive_subjets");
+}
+
+// return the size of exclusive_subjets(...); still n ln n with same
+// coefficient, but marginally more efficient than manually taking
+// exclusive_subjets.size()
+//
+// by default, an Error is thrown
+int PseudoJetStructureBase::n_exclusive_subjets(const PseudoJet & /*reference*/, const double & /*dcut*/) const{
+  throw Error("This PseudoJet structure has no implementation for n_exclusive_subjets");
+}
+
+// return the list of subjets obtained by unclustering the supplied
+// jet down to n subjets (or all constituents if there are fewer
+// than n).
+//
+// by default, an Error is thrown
+vector<PseudoJet> PseudoJetStructureBase::exclusive_subjets_up_to (const PseudoJet & /*reference*/, int /*nsub*/) const{
+  throw Error("This PseudoJet structure has no implementation for exclusive_subjets");
+}
+
+// return the dij that was present in the merging nsub+1 -> nsub 
+// subjets inside this jet.
+//
+// by default, an Error is thrown
+double PseudoJetStructureBase::exclusive_subdmerge(const PseudoJet & /*reference*/, int /*nsub*/) const{
+  throw Error("This PseudoJet structure has no implementation for exclusive_submerge");
+}
+
+// return the maximum dij that occurred in the whole event at the
+// stage that the nsub+1 -> nsub merge of subjets occurred inside 
+// this jet.
+//
+// by default, an Error is thrown
+double PseudoJetStructureBase::exclusive_subdmerge_max(const PseudoJet & /*reference*/, int /*nsub*/) const{
+  throw Error("This PseudoJet structure has no implementation for exclusive_submerge_max");
+}
+
+
+// retrieve the pieces building the jet. 
+//
+// by default, an Error is thrown
+std::vector<PseudoJet> PseudoJetStructureBase::pieces(const PseudoJet & /*reference*/) const{
+  throw Error("This PseudoJet structure has no implementation for pieces");  
+}
+
+// the following ones require a computation of the area in the
+// parent ClusterSequence (See ClusterSequenceAreaBase for details)
+//------------------------------------------------------------------
+
+// return the jet (scalar) area.
+//
+// by default, an Error is thrown
+double PseudoJetStructureBase::area(const PseudoJet & /*reference*/) const{
+  throw Error("This PseudoJet structure has no implementation for area");
+}
+
+// return the error (uncertainty) associated with the determination
+// of the area of this jet.
+//
+// by default, an Error is thrown
+double PseudoJetStructureBase::area_error(const PseudoJet & /*reference*/) const{
+  throw Error("This PseudoJet structure has no implementation for area_error");
+}
+
+// return the jet 4-vector area.
+//
+// by default, an Error is thrown
+PseudoJet PseudoJetStructureBase::area_4vector(const PseudoJet & /*reference*/) const{
+  throw Error("This PseudoJet structure has no implementation for area_4vector");
+}
+
+// true if this jet is made exclusively of ghosts.
+//
+// by default, an Error is thrown
+bool PseudoJetStructureBase::is_pure_ghost(const PseudoJet & /*reference*/) const{
+  throw Error("This PseudoJet structure has no implementation for is_pure_ghost");
+}
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/PseudoJetStructureBase.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/PseudoJetStructureBase.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/PseudoJetStructureBase.hh	(revision 5)
@@ -0,0 +1,237 @@
+//STARTHEADER
+// $Id: PseudoJetStructureBase.hh 2670 2011-11-11 17:01:06Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_PSEUDOJET_STRUCTURE_BASE_HH__
+#define __FASTJET_PSEUDOJET_STRUCTURE_BASE_HH__
+
+#include "fastjet/internal/base.hh"
+
+#include <vector>
+#include <string>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+class PseudoJet;
+class ClusterSequence;
+class ClusterSequenceAreaBase;
+
+/// @ingroup extra_info
+/// \class PseudoJetStructureBase
+///
+/// Contains any information related to the clustering that should be
+/// directly accessible to PseudoJet.
+///
+/// By default, this class implements basic access to the
+/// ClusterSequence related to a PseudoJet (like its constituents or
+/// its area). But it can be overloaded in order e.g. to give access
+/// to the jet substructure.
+///
+class PseudoJetStructureBase{
+public:
+  /// default ctor
+  PseudoJetStructureBase(){};
+
+  /// default (virtual) dtor
+  virtual ~PseudoJetStructureBase(){};
+
+  /// description
+  virtual std::string description() const{ return "PseudoJet with an unknown structure"; }
+
+  //-------------------------------------------------------------
+  /// @name Direct access to the associated ClusterSequence object.
+  ///
+  /// Get access to the associated ClusterSequence (if any)
+  //\{
+  //-------------------------------------------------------------
+  /// returns true if there is an associated ClusterSequence
+  virtual bool has_associated_cluster_sequence() const { return false;}
+
+  /// get a (const) pointer to the parent ClusterSequence (NULL if
+  /// inexistent)
+  virtual const ClusterSequence* associated_cluster_sequence() const;
+  
+  /// returns true if this PseudoJet has an associated and still
+  /// valid ClusterSequence.
+  virtual bool has_valid_cluster_sequence() const {return false;}
+
+  /// if the jet has a valid associated cluster sequence then return a
+  /// pointer to it; otherwise throw an error
+  virtual const ClusterSequence * validated_cs() const;
+
+  /// if the jet has valid area information then return a pointer to
+  /// the associated ClusterSequenceAreaBase object; otherwise throw an error
+  virtual const ClusterSequenceAreaBase * validated_csab() const;
+
+  //\}
+
+  //-------------------------------------------------------------
+  /// @name Methods for access to information about jet structure
+  ///
+  /// These allow access to jet constituents, and other jet
+  /// subtructure information. They only work if the jet is associated
+  /// with a ClusterSequence.
+  //-------------------------------------------------------------
+  //\{
+
+  /// check if it has been recombined with another PseudoJet in which
+  /// case, return its partner through the argument. Otherwise,
+  /// 'partner' is set to 0.
+  ///
+  /// By default, throws an Error
+  virtual bool has_partner(const PseudoJet &reference, PseudoJet &partner) const;
+
+  /// check if it has been recombined with another PseudoJet in which
+  /// case, return its child through the argument. Otherwise, 'child'
+  /// is set to 0.
+  /// 
+  /// By default, throws an Error
+  virtual bool has_child(const PseudoJet &reference, PseudoJet &child) const;
+
+  /// check if it is the product of a recombination, in which case
+  /// return the 2 parents through the 'parent1' and 'parent2'
+  /// arguments. Otherwise, set these to 0.
+  ///
+  /// By default, throws an Error
+  virtual bool has_parents(const PseudoJet &reference, PseudoJet &parent1, PseudoJet &parent2) const;
+
+  /// check if the reference PseudoJet is contained the second one
+  /// passed as argument.
+  ///
+  /// By default, throws an Error
+  virtual bool object_in_jet(const PseudoJet &reference, const PseudoJet &jet) const;
+
+
+  /// return true if the structure supports constituents. 
+  ///
+  /// false by default
+  virtual bool has_constituents() const {return false;}
+
+  /// retrieve the constituents. 
+  ///
+  /// By default, throws an Error
+  virtual std::vector<PseudoJet> constituents(const PseudoJet &reference) const;
+
+
+  /// return true if the structure supports exclusive_subjets. 
+  virtual bool has_exclusive_subjets() const {return false;}
+
+  /// return a vector of all subjets of the current jet (in the sense
+  /// of the exclusive algorithm) that would be obtained when running
+  /// the algorithm with the given dcut. 
+  ///
+  /// Time taken is O(m ln m), where m is the number of subjets that
+  /// are found. If m gets to be of order of the total number of
+  /// constituents in the jet, this could be substantially slower than
+  /// just getting that list of constituents.
+  ///
+  /// By default, throws an Error
+  virtual std::vector<PseudoJet> exclusive_subjets(const PseudoJet &reference, const double & dcut) const;
+
+  /// return the size of exclusive_subjets(...); still n ln n with same
+  /// coefficient, but marginally more efficient than manually taking
+  /// exclusive_subjets.size()
+  ///
+  /// By default, throws an Error
+  virtual int n_exclusive_subjets(const PseudoJet &reference, const double & dcut) const;
+
+  /// return the list of subjets obtained by unclustering the supplied
+  /// jet down to nsub subjets (or all constituents if there are fewer
+  /// than nsub).
+  ///
+  /// By default, throws an Error
+  virtual std::vector<PseudoJet> exclusive_subjets_up_to (const PseudoJet &reference, int nsub) const;
+
+  /// return the dij that was present in the merging nsub+1 -> nsub 
+  /// subjets inside this jet.
+  ///
+  /// By default, throws an Error
+  virtual double exclusive_subdmerge(const PseudoJet &reference, int nsub) const;
+
+  /// return the maximum dij that occurred in the whole event at the
+  /// stage that the nsub+1 -> nsub merge of subjets occurred inside 
+  /// this jet.
+  ///
+  /// By default, throws an Error
+  virtual double exclusive_subdmerge_max(const PseudoJet &reference, int nsub) const;
+
+
+  //-------------------------------------------------------------------
+  // information related to the pieces of the jet
+  //-------------------------------------------------------------------
+  /// return true if the structure supports pieces. 
+  ///
+  /// false by default
+  /// NB: "reference" is commented to avoid unused-variable compiler warnings
+  virtual bool has_pieces(const PseudoJet & /* reference */) const {
+    return false;}
+
+  /// retrieve the pieces building the jet. 
+  ///
+  /// By default, throws an Error.
+  /// NB: "reference" is commented to avoid unused-variable compiler warnings
+  virtual std::vector<PseudoJet> pieces(const PseudoJet & /* reference */
+                                        ) const;
+
+
+  // the following ones require a computation of the area in the
+  // parent ClusterSequence (See ClusterSequenceAreaBase for details)
+  //------------------------------------------------------------------
+
+  /// check if it has a defined area
+  ///
+  /// false by default
+  virtual bool has_area() const {return false;}
+
+  /// return the jet (scalar) area.
+  ///
+  /// By default, throws an Error
+  virtual double area(const PseudoJet &reference) const;
+
+  /// return the error (uncertainty) associated with the determination
+  /// of the area of this jet.
+  ///
+  /// By default, throws an Error
+  virtual double area_error(const PseudoJet &reference) const;
+
+  /// return the jet 4-vector area.
+  ///
+  /// By default, throws an Error
+  virtual PseudoJet area_4vector(const PseudoJet &reference) const;
+
+  /// true if this jet is made exclusively of ghosts.
+  ///
+  /// By default, throws an Error
+  virtual bool is_pure_ghost(const PseudoJet &reference) const;
+
+  //\} --- end of jet structure -------------------------------------
+};
+
+FASTJET_END_NAMESPACE
+
+#endif  //  __FASTJET_PSEUDOJET_STRUCTURE_BASE_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/RangeDefinition.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/RangeDefinition.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/RangeDefinition.cc	(revision 5)
@@ -0,0 +1,67 @@
+//STARTHEADER
+// $Id: RangeDefinition.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/RangeDefinition.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+ 
+LimitedWarning RangeDefinition::_warnings_deprecated;
+
+// calculate, and set in _total_area, the area with a numerical test
+// takes a reasonable time with rapmax = 10, npoints = 100
+void RangeDefinition::_numerical_total_area(double rapmax, int npoints) {
+
+      int count = 0;
+      double deltaphi = twopi/double(npoints);
+      double deltarap = 2.0*rapmax/double(npoints);
+      double phi = 0.0;
+      for(int i = 0; i < npoints; i++) {
+        double rap = -rapmax;
+        for (int j = 0; j < npoints; j++) {
+	  if ( is_in_range(rap,phi) ) { count++; }
+          rap += deltarap;
+        }
+        phi += deltaphi;
+      }
+
+      _total_area = double(count)/double(npoints*npoints)*2.0*twopi*rapmax;
+}
+
+
+// the use of RangeDefinition is deprecated since FastJet version
+// 3.0 onwards. Please use Selector instead.  
+// RangeDefinition is only provided for backward compatibility
+// reasons and is not guaranteed to work in future releases of
+// FastJet.
+void RangeDefinition::_warn_deprecated() const{
+  _warnings_deprecated.warn("The use of RangeDefinition is deprecated since FastJet version 3.0 onwards. Please consider using Selector (defined in fastjet/Selector.hh) instead. There is no guarantee that support for RangeDefinition will be provided in future releases of FastJet.");
+}
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/RangeDefinition.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/RangeDefinition.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/RangeDefinition.hh	(revision 5)
@@ -0,0 +1,179 @@
+//STARTHEADER
+// $Id: RangeDefinition.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_RANGEDEFINITION_HH__
+#define __FASTJET_RANGEDEFINITION_HH__
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/Error.hh"
+#include "fastjet/LimitedWarning.hh"
+#include<sstream>
+#include<iostream>
+#include<string>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+//
+/// @ingroup area_classes
+/// \class RangeDefinition
+/// class for holding a range definition specification, given by limits
+/// on rapidity and azimuth.
+///
+class RangeDefinition {
+public:
+  /// default constructor
+  RangeDefinition() { _warn_deprecated(); }
+
+  /// constructor for a range definition given by |y|<rapmax
+  RangeDefinition(double rapmax) {  _warn_deprecated(); 
+                     assert ( rapmax > 0.0 );
+                     _rapmax = rapmax;
+		     _rapmin = -rapmax;
+		     _phimin = 0.0;
+		     _phimax = twopi;
+		     _total_area = 2.0*rapmax*twopi;
+                     _phispan = _phimax-_phimin; }
+  
+  /// destructor does nothing
+  virtual ~RangeDefinition() {}
+     
+  /// constructor for a range definition given by 
+  /// rapmin <= y <= rapmax, phimin <= phi <= phimax
+  RangeDefinition(double rapmin, double rapmax, 
+                  double phimin = 0.0, double phimax = twopi) {
+                     _warn_deprecated(); 
+                     assert ( rapmin < rapmax);
+                     assert ( phimin < phimax);
+                     assert ( phimin > -twopi );
+                     assert ( phimax < 2*twopi);
+                     _rapmax = rapmax;
+		     _rapmin = rapmin;
+		     _phimin = phimin;
+		     _phimax = phimax;
+		     if (_phimax-_phimin > twopi)
+		       _total_area = (_rapmax - _rapmin)*twopi;
+		     else
+		       _total_area = (_rapmax - _rapmin)*(_phimax - _phimin);
+                     _phispan = _phimax-_phimin; }
+
+  /// returns true if the range is localizable (i.e. set_position is
+  /// meant to do something meaningful). 
+  ///
+  /// This version of the class is not localizable and so it returns
+  /// false.
+  ///
+  /// For localizable classes override this function with a function
+  /// that returns true
+  virtual inline bool is_localizable() const { return false; }
+
+
+  /// place the range on the rap-phi position
+  ///
+  /// THIS DOES NOT DO ANYTHING FOR THIS CLASS AND IS ONLY THERE
+  /// TO FACILITATE DERIVED CLASSES
+  ///
+  /// DON'T NECESSARILY COUNT ON IT IN THE FUTURE EITHER???
+  inline void set_position(const double & rap, const double & phi) {
+     if (! is_localizable() ) {
+       std::ostringstream err;
+       err << description() << 
+         "\nThis range is not localizable. set_position() should not be used on it.";         
+       throw Error(err.str()); 
+     } else {
+       _rapjet = rap;
+       _phijet = phi;
+     }
+  }
+
+  /// place the range on the jet position
+  inline void set_position(const PseudoJet & jet) {
+     set_position(jet.rap(),jet.phi());
+  }
+
+  /// return bool according to whether the jet is within the given range
+  inline bool is_in_range(const PseudoJet & jet) const {
+    double rap = jet.rap();
+    double phi = jet.phi();
+    return is_in_range(rap,phi);
+  }
+  
+  /// return bool according to whether a (rap,phi) point is in range
+  virtual inline bool is_in_range(double rap, double phi) const {
+    double dphi=phi-_phimin;
+    if (dphi >= twopi) dphi -= twopi;
+    if (dphi < 0)      dphi += twopi;
+    return  ( rap  >= _rapmin && 
+	      rap  <= _rapmax &&
+	      dphi <= _phispan );
+  }
+
+  /// return the minimal and maximal rapidity of this range; remember to 
+  /// replace this if you write a derived class with more complex ranges;
+  virtual inline void get_rap_limits(double & rapmin, double & rapmax) const {
+    rapmin = _rapmin;
+    rapmax = _rapmax;
+  }
+  
+  /// area of the range region
+  virtual inline double area() const { return _total_area; }
+  
+  /// textual description of range
+  virtual inline std::string description() const {
+    std::ostringstream ostr;
+    ostr << "Range: " << _rapmin << " <= y <= "   << _rapmax << ", "
+                      << _phimin << " <= phi <= " << _phimax ;
+    return ostr.str();
+}
+
+protected:
+  double _total_area;  // total area of specified range
+
+  /// calculate, and set  _total_area, by calculating which of points on 
+  /// a grid (npoints * npoints from -rapmax..rapmax,0..2pi) are contained
+  /// in the range; it takes a reasonable time with rapmax = 10,
+  /// npoints = 100.
+  void _numerical_total_area(double rapmax, int npoints) ;
+  double _rapjet,_phijet; // jet position. only used in localizable derived classes
+  
+private:
+  double _rapmin,_rapmax,_phimin,_phimax,_phispan;
+
+  static LimitedWarning _warnings_deprecated;
+
+  /// the use of RangeDefinition is deprecated since FastJet version
+  /// 3.0 onwards. Please use Selector instead.  
+  /// RangeDefinition is only provided for backward compatibility
+  /// reasons and is not guaranteed to work in future releases of
+  /// FastJet.
+  void _warn_deprecated() const; 
+};
+
+FASTJET_END_NAMESPACE        // defined in fastjet/internal/base.hh
+
+#endif // __FASTJET_RANGEDEFINITION_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/Selector.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/Selector.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/Selector.cc	(revision 5)
@@ -0,0 +1,1441 @@
+//STARTHEADER
+// $Id: Selector.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#include <sstream>
+#include <algorithm>
+#include "fastjet/Selector.hh"
+#include "fastjet/GhostedAreaSpec.hh"  // for area support
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+// implementations of some of the more complex bits of Selector
+//----------------------------------------------------------------------
+
+// implementation of the operator() acting on a vector of jets
+std::vector<PseudoJet> Selector::operator()(const std::vector<PseudoJet> & jets) const {
+  std::vector<PseudoJet> result;
+  const SelectorWorker * worker_local = validated_worker();
+  if (worker_local->applies_jet_by_jet()) {
+    //if (false) {
+    // for workers that apply jet by jet, this is more efficient
+    for (std::vector<PseudoJet>::const_iterator jet = jets.begin(); 
+         jet != jets.end(); jet++) {
+      if (worker_local->pass(*jet)) result.push_back(*jet);
+    }
+  } else {
+    // for workers that can only be applied to entire vectors,
+    // go through the following
+    std::vector<const PseudoJet *> jetptrs(jets.size());
+    for (unsigned i = 0; i < jets.size(); i++) {
+      jetptrs[i] = & jets[i];
+    }
+    worker_local->terminator(jetptrs);
+    for (unsigned i = 0; i < jetptrs.size(); i++) {
+      if (jetptrs[i]) result.push_back(jets[i]);
+    }
+  }
+  return result;
+}
+
+
+//----------------------------------------------------------------------
+// count the number of jets that pass the cuts
+unsigned int Selector::count(const std::vector<PseudoJet> & jets) const {
+  unsigned n = 0;
+  const SelectorWorker * worker_local = validated_worker();
+  
+  // separate strategies according to whether the worker applies jet by jet
+  if (worker_local->applies_jet_by_jet()) {
+    for (unsigned i = 0; i < jets.size(); i++) {
+      if (worker_local->pass(jets[i])) n++;
+    }
+  } else {
+    std::vector<const PseudoJet *> jetptrs(jets.size());
+    for (unsigned i = 0; i < jets.size(); i++) {
+      jetptrs[i] = & jets[i];
+    }
+    worker_local->terminator(jetptrs);
+    for (unsigned i = 0; i < jetptrs.size(); i++) {
+      if (jetptrs[i]) n++;
+    }
+  }
+
+  return n;
+}
+
+
+//----------------------------------------------------------------------
+// sift the input jets into two vectors -- those that pass the selector
+// and those that do not
+void Selector::sift(const std::vector<PseudoJet> & jets,
+		    std::vector<PseudoJet> & jets_that_pass,
+		    std::vector<PseudoJet> & jets_that_fail
+		    ) const {
+  const SelectorWorker * worker_local = validated_worker();
+  
+  jets_that_pass.clear();
+  jets_that_fail.clear();
+  
+  // separate strategies according to whether the worker applies jet by jet
+  if (worker_local->applies_jet_by_jet()) {
+    for (unsigned i = 0; i < jets.size(); i++) {
+      if (worker_local->pass(jets[i])) {
+	jets_that_pass.push_back(jets[i]);
+      } else {
+	jets_that_fail.push_back(jets[i]);
+      }
+    }
+  } else {
+    std::vector<const PseudoJet *> jetptrs(jets.size());
+    for (unsigned i = 0; i < jets.size(); i++) {
+      jetptrs[i] = & jets[i];
+    }
+    worker_local->terminator(jetptrs);
+    for (unsigned i = 0; i < jetptrs.size(); i++) {
+      if (jetptrs[i]) {
+	jets_that_pass.push_back(jets[i]);
+      } else {
+	jets_that_fail.push_back(jets[i]);
+      }
+    }
+  }
+}
+
+// area using default ghost area
+double Selector::area() const{
+  return area(gas::def_ghost_area);
+}
+
+// implementation of the Selector's area function
+double Selector::area(double ghost_area) const{
+  if (! is_geometric()) throw InvalidArea();
+  
+  // has area will already check we've got a valid worker
+  if (_worker->has_known_area()) return _worker->known_area();
+  
+  // generate a set of "ghosts"
+  double rapmin, rapmax;
+  get_rapidity_extent(rapmin, rapmax);
+  GhostedAreaSpec ghost_spec(rapmin, rapmax, 1, ghost_area);
+  std::vector<PseudoJet> ghosts;
+  ghost_spec.add_ghosts(ghosts);
+  
+  // check what passes the selection
+  return ghost_spec.ghost_area() * ((*this)(ghosts)).size();
+}
+
+
+//----------------------------------------------------------------------
+// implementations of some of the more complex bits of SelectorWorker
+//----------------------------------------------------------------------
+// check if it has a finite area
+bool SelectorWorker::has_finite_area() const { 
+  if (! is_geometric()) return false;
+  double rapmin, rapmax;
+  get_rapidity_extent(rapmin, rapmax);
+  return (rapmax != std::numeric_limits<double>::infinity())
+    &&  (-rapmin != std::numeric_limits<double>::infinity());
+}
+
+
+
+//----------------------------------------------------------------------
+// very basic set of selectors (at the moment just the identity!)
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+/// helper for selecting the n hardest jets
+class SW_Identity : public SelectorWorker {
+public:
+  /// ctor with specification of the number of objects to keep
+  SW_Identity(){}
+
+  /// just let everything pass
+  virtual bool pass(const PseudoJet &) const {
+    return true;
+  }
+
+  /// For each jet that does not pass the cuts, this routine sets the 
+  /// pointer to 0. 
+  virtual void terminator(vector<const PseudoJet *> &) const {
+    // everything passes, hence nothing to nullify
+    return;
+  }
+  
+  /// returns a description of the worker
+  virtual string description() const { return "Identity";}
+
+  /// strictly speaking, this is geometric
+  virtual bool is_geometric() const { return true;}
+};
+
+
+// returns an "identity" selector that lets everything pass
+Selector SelectorIdentity() {
+  return Selector(new SW_Identity);
+}
+
+
+//----------------------------------------------------------------------
+// selector and workers for operators
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+/// helper for combining selectors with a logical not
+class SW_Not : public SelectorWorker {
+public:
+  /// ctor
+  SW_Not(const Selector & s) : _s(s) {}
+
+  /// return a copy of the current object
+  virtual SelectorWorker* copy(){ return new SW_Not(*this);}
+
+  /// returns true if a given object passes the selection criterium
+  /// this has to be overloaded by derived workers
+  virtual bool pass(const PseudoJet & jet) const {
+    // make sure that the "pass" can be applied on both selectors
+    if (!applies_jet_by_jet())
+      throw Error("Cannot apply this selector worker to an individual jet");
+    
+    return ! _s.pass(jet);
+  } 
+
+  /// returns true if this can be applied jet by jet
+  virtual bool applies_jet_by_jet() const {return _s.applies_jet_by_jet();}
+
+  /// select the jets in the list that pass both selectors
+  virtual void terminator(vector<const PseudoJet *> & jets) const {
+    // if we can apply the selector jet-by-jet, call the base selector
+    // that does exactly that
+    if (applies_jet_by_jet()){
+      SelectorWorker::terminator(jets);
+      return;
+    }
+
+    // check the effect of the selector we want to negate
+    vector<const PseudoJet *> s_jets = jets;
+    _s.worker()->terminator(s_jets);
+
+    // now apply the negation: all the jets that pass the base
+    // selector (i.e. are not NULL) have to be set to NULL
+    for (unsigned int i=0; i<s_jets.size(); i++){
+      if (s_jets[i]) jets[i] = NULL;
+    }
+  }
+
+  /// returns a description of the worker
+  virtual string description() const {
+    ostringstream ostr;
+    ostr << "!(" << _s.description() << ")";
+    return ostr.str();
+  }
+
+  /// is geometric if the underlying selector is
+  virtual bool is_geometric() const { return _s.is_geometric();}
+
+  /// returns true if the worker can be set_referenced
+  virtual bool takes_reference() const { return _s.takes_reference();}
+
+  /// set the reference jet for this selector
+  virtual void set_reference(const PseudoJet &ref) { _s.set_reference(ref);}
+
+protected:
+  Selector _s;
+};
+
+
+// logical not applied on a selector
+Selector operator!(const Selector & s) {
+  return Selector(new SW_Not(s));
+}
+
+
+//----------------------------------------------------------------------
+/// Base class for binary operators
+class SW_BinaryOperator: public SelectorWorker {
+public:
+  /// ctor
+  SW_BinaryOperator(const Selector & s1, const Selector & s2) : _s1(s1), _s2(s2) {
+    // stores info for more efficient access to the selector's properties
+
+    // we can apply jet by jet only if this is the case for both sub-selectors
+    _applies_jet_by_jet = _s1.applies_jet_by_jet() && _s2.applies_jet_by_jet();
+
+    // the selector takes a reference if either of the sub-selectors does
+    _takes_reference = _s1.takes_reference() || _s2.takes_reference();
+
+    // we have a well-defined area provided the two objects have one
+    _is_geometric = _s1.is_geometric() && _s2.is_geometric();
+  }
+
+  /// returns true if this can be applied jet by jet
+  virtual bool applies_jet_by_jet() const {return _applies_jet_by_jet;}
+
+  /// returns true if this takes a reference jet
+  virtual bool takes_reference() const{ 
+    return _takes_reference;
+  }
+
+  /// sets the reference jet
+  virtual void set_reference(const PseudoJet &centre){
+    _s1.set_reference(centre);
+    _s2.set_reference(centre);
+  }
+
+  /// check if it has a finite area
+  virtual bool is_geometric() const { return _is_geometric;} 
+
+protected:
+  Selector _s1, _s2;
+  bool _applies_jet_by_jet;
+  bool _takes_reference;
+  bool _is_geometric;
+};
+
+
+
+//----------------------------------------------------------------------
+/// helper for combining selectors with a logical and
+class SW_And: public SW_BinaryOperator {
+public:
+  /// ctor
+  SW_And(const Selector & s1, const Selector & s2) : SW_BinaryOperator(s1,s2){}
+
+  /// return a copy of this
+  virtual SelectorWorker* copy(){ return new SW_And(*this);}
+
+  /// returns true if a given object passes the selection criterium
+  /// this has to be overloaded by derived workers
+  virtual bool pass(const PseudoJet & jet) const {
+    // make sure that the "pass" can be applied on both selectors
+    if (!applies_jet_by_jet())
+      throw Error("Cannot apply this selector worker to an individual jet");
+    
+    return _s1.pass(jet) && _s2.pass(jet);
+  }
+
+  /// select the jets in the list that pass both selectors
+  virtual void terminator(vector<const PseudoJet *> & jets) const {
+    // if we can apply the selector jet-by-jet, call the base selector
+    // that does exactly that
+    if (applies_jet_by_jet()){
+      SelectorWorker::terminator(jets);
+      return;
+    }
+
+    // check the effect of the first selector
+    vector<const PseudoJet *> s1_jets = jets;
+    _s1.worker()->terminator(s1_jets);
+
+    // apply the second
+    _s2.worker()->terminator(jets);
+
+    // terminate the jets that wiuld be terminated by _s1
+    for (unsigned int i=0; i<jets.size(); i++){
+      if (! s1_jets[i]) jets[i] = NULL;
+    }
+  }
+
+  /// returns the rapidity range for which it may return "true"
+  virtual void get_rapidity_extent(double & rapmin, double & rapmax) const {
+    double s1min, s1max, s2min, s2max;
+    _s1.get_rapidity_extent(s1min, s1max);
+    _s2.get_rapidity_extent(s2min, s2max);
+    rapmax = min(s1max, s2max);
+    rapmin = max(s1min, s2min);
+  }
+
+  /// returns a description of the worker
+  virtual string description() const {
+    ostringstream ostr;
+    ostr << "(" << _s1.description() << " && " << _s2.description() << ")";
+    return ostr.str();
+  }
+};
+
+
+// logical and between two selectors
+Selector operator&&(const Selector & s1, const Selector & s2) {
+  return Selector(new SW_And(s1,s2));
+}
+
+
+
+//----------------------------------------------------------------------
+/// helper for combining selectors with a logical or
+class SW_Or: public SW_BinaryOperator {
+public:
+  /// ctor
+  SW_Or(const Selector & s1, const Selector & s2) : SW_BinaryOperator(s1,s2) {}
+
+  /// return a copy of this
+  virtual SelectorWorker* copy(){ return new SW_Or(*this);}
+
+  /// returns true if a given object passes the selection criterium
+  /// this has to be overloaded by derived workers
+  virtual bool pass(const PseudoJet & jet) const {
+    // make sure that the "pass" can be applied on both selectors
+    if (!applies_jet_by_jet())
+      throw Error("Cannot apply this selector worker to an individual jet");
+    
+    return _s1.pass(jet) || _s2.pass(jet);
+  }
+
+  /// returns true if this can be applied jet by jet
+  virtual bool applies_jet_by_jet() const {
+    // watch out, even though it's the "OR" selector, to be applied jet
+    // by jet, both the base selectors need to be jet-by-jet-applicable,
+    // so the use of a && in the line below
+    return _s1.applies_jet_by_jet() && _s2.applies_jet_by_jet();
+  }
+
+  /// select the jets in the list that pass both selectors
+  virtual void terminator(vector<const PseudoJet *> & jets) const {
+    // if we can apply the selector jet-by-jet, call the base selector
+    // that does exactly that
+    if (applies_jet_by_jet()){
+      SelectorWorker::terminator(jets);
+      return;
+    }
+
+    // check the effect of the first selector
+    vector<const PseudoJet *> s1_jets = jets;
+    _s1.worker()->terminator(s1_jets);
+
+    // apply the second
+    _s2.worker()->terminator(jets);
+
+    // resurrect any jet that has been terminated by the second one
+    // and not by the first one
+    for (unsigned int i=0; i<jets.size(); i++){
+      if (s1_jets[i]) jets[i] = s1_jets[i];
+    }
+  }
+
+  /// returns a description of the worker
+  virtual string description() const {
+    ostringstream ostr;
+    ostr << "(" << _s1.description() << " || " << _s2.description() << ")";
+    return ostr.str();
+  }
+
+  /// returns the rapidity range for which it may return "true"
+  virtual void get_rapidity_extent(double & rapmin, double & rapmax) const {
+    double s1min, s1max, s2min, s2max;
+    _s1.get_rapidity_extent(s1min, s1max);
+    _s2.get_rapidity_extent(s2min, s2max);
+    rapmax = max(s1max, s2max);
+    rapmin = min(s1min, s2min);
+  }
+};
+
+
+// logical or between two selectors
+Selector operator ||(const Selector & s1, const Selector & s2) {
+  return Selector(new SW_Or(s1,s2));
+}
+
+//----------------------------------------------------------------------
+/// helper for multiplying two selectors (in an operator-like way)
+class SW_Mult: public SW_And {
+public:
+  /// ctor
+  SW_Mult(const Selector & s1, const Selector & s2) : SW_And(s1,s2) {}
+
+  /// return a copy of this
+  virtual SelectorWorker* copy(){ return new SW_Mult(*this);}
+
+  /// select the jets in the list that pass both selectors
+  virtual void terminator(vector<const PseudoJet *> & jets) const {
+    // if we can apply the selector jet-by-jet, call the base selector
+    // that does exactly that
+    if (applies_jet_by_jet()){
+      SelectorWorker::terminator(jets);
+      return;
+    }
+
+    // first apply _s2
+    _s2.worker()->terminator(jets);
+
+    // then apply _s1
+    _s1.worker()->terminator(jets);
+  }
+
+  /// returns a description of the worker
+  virtual string description() const {
+    ostringstream ostr;
+    ostr << "(" << _s1.description() << " * " << _s2.description() << ")";
+    return ostr.str();
+  }
+};
+
+
+// logical and between two selectors
+Selector operator*(const Selector & s1, const Selector & s2) {
+  return Selector(new SW_Mult(s1,s2));
+}
+
+
+//----------------------------------------------------------------------
+// selector and workers for kinematic cuts
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+// a series of basic classes that allow easy implementations of
+// min, max and ranges on a quantity-to-be-defined
+
+// generic holder for a quantity
+class QuantityBase{
+public:
+  QuantityBase(double q) : _q(q){}
+  virtual ~QuantityBase(){}
+  virtual double operator()(const PseudoJet & jet ) const =0;
+  virtual string description() const =0;
+  virtual bool is_geometric() const { return false;}
+  virtual double comparison_value() const {return _q;}
+  virtual double description_value() const {return comparison_value();}
+protected:
+  double _q;
+};  
+
+// generic holder for a squared quantity
+class QuantitySquareBase : public QuantityBase{
+public:
+  QuantitySquareBase(double sqrtq) : QuantityBase(sqrtq*sqrtq), _sqrtq(sqrtq){}
+  virtual double description_value() const {return _sqrtq;}
+protected:
+  double _sqrtq;
+};  
+
+// generic_quantity >= minimum
+template<typename QuantityType>
+class SW_QuantityMin : public SelectorWorker{
+public:
+  /// detfault ctor (initialises the pt cut)
+  SW_QuantityMin(double qmin) : _qmin(qmin) {}
+
+  /// returns true is the given object passes the selection pt cut
+  virtual bool pass(const PseudoJet & jet) const {return _qmin(jet) >= _qmin.comparison_value();}
+
+  /// returns a description of the worker
+  virtual string description() const {
+    ostringstream ostr;
+    ostr << _qmin.description() << " >= " << _qmin.description_value();
+    return ostr.str();
+  }
+
+  virtual bool is_geometric() const { return _qmin.is_geometric();}
+
+protected:
+  QuantityType _qmin;     ///< the cut
+};
+
+
+// generic_quantity <= maximum
+template<typename QuantityType>
+class SW_QuantityMax : public SelectorWorker {
+public:
+  /// detfault ctor (initialises the pt cut)
+  SW_QuantityMax(double qmax) : _qmax(qmax) {}
+
+  /// returns true is the given object passes the selection pt cut
+  virtual bool pass(const PseudoJet & jet) const {return _qmax(jet) <= _qmax.comparison_value();}
+
+  /// returns a description of the worker
+  virtual string description() const {
+    ostringstream ostr;
+    ostr << _qmax.description() << " <= " << _qmax.description_value();
+    return ostr.str();
+  }
+
+  virtual bool is_geometric() const { return _qmax.is_geometric();}
+
+protected:
+  QuantityType _qmax;   ///< the cut
+};
+
+
+// generic quantity in [minimum:maximum]
+template<typename QuantityType>
+class SW_QuantityRange : public SelectorWorker {
+public:
+  /// detfault ctor (initialises the pt cut)
+  SW_QuantityRange(double qmin, double qmax) : _qmin(qmin), _qmax(qmax) {}
+
+  /// returns true is the given object passes the selection pt cut
+  virtual bool pass(const PseudoJet & jet) const {
+    double q = _qmin(jet); // we could identically use _qmax
+    return (q >= _qmin.comparison_value()) && (q <= _qmax.comparison_value());
+  }
+
+  /// returns a description of the worker
+  virtual string description() const {
+    ostringstream ostr;
+    ostr << _qmin.description_value() << " <= " << _qmin.description() << " <= " << _qmax.description_value();
+    return ostr.str();
+  }
+
+  virtual bool is_geometric() const { return _qmin.is_geometric();}
+
+protected:
+  QuantityType _qmin;   // the lower cut 
+  QuantityType _qmax;   // the upper cut
+};
+
+
+//----------------------------------------------------------------------
+/// helper class for selecting on pt
+class QuantityPt2 : public QuantitySquareBase{
+public:
+  QuantityPt2(double pt) : QuantitySquareBase(pt){}
+  virtual double operator()(const PseudoJet & jet ) const { return jet.perp2();}
+  virtual string description() const {return "pt";}
+};  
+
+// returns a selector for a minimum pt
+Selector SelectorPtMin(double ptmin) {
+  return Selector(new SW_QuantityMin<QuantityPt2>(ptmin));
+}
+
+// returns a selector for a maximum pt
+Selector SelectorPtMax(double ptmax) {
+  return Selector(new SW_QuantityMax<QuantityPt2>(ptmax));
+}
+
+// returns a selector for a pt range
+Selector SelectorPtRange(double ptmin, double ptmax) {
+  return Selector(new SW_QuantityRange<QuantityPt2>(ptmin, ptmax));
+}
+
+
+//----------------------------------------------------------------------
+/// helper class for selecting on transverse energy
+class QuantityEt2 : public QuantitySquareBase{
+public:
+  QuantityEt2(double Et) : QuantitySquareBase(Et){}
+  virtual double operator()(const PseudoJet & jet ) const { return jet.Et2();}
+  virtual string description() const {return "Et";}
+};  
+
+// returns a selector for a minimum Et
+Selector SelectorEtMin(double Etmin) {
+  return Selector(new SW_QuantityMin<QuantityEt2>(Etmin));
+}
+
+// returns a selector for a maximum Et
+Selector SelectorEtMax(double Etmax) {
+  return Selector(new SW_QuantityMax<QuantityEt2>(Etmax));
+}
+
+// returns a selector for a Et range
+Selector SelectorEtRange(double Etmin, double Etmax) {
+  return Selector(new SW_QuantityRange<QuantityEt2>(Etmin, Etmax));
+}
+
+
+//----------------------------------------------------------------------
+/// helper class for selecting on energy
+class QuantityE : public QuantityBase{
+public:
+  QuantityE(double E) : QuantityBase(E){}
+  virtual double operator()(const PseudoJet & jet ) const { return jet.E();}
+  virtual string description() const {return "E";}
+};  
+
+// returns a selector for a minimum E
+Selector SelectorEMin(double Emin) {
+  return Selector(new SW_QuantityMin<QuantityE>(Emin));
+}
+
+// returns a selector for a maximum E
+Selector SelectorEMax(double Emax) {
+  return Selector(new SW_QuantityMax<QuantityE>(Emax));
+}
+
+// returns a selector for a E range
+Selector SelectorERange(double Emin, double Emax) {
+  return Selector(new SW_QuantityRange<QuantityE>(Emin, Emax));
+}
+
+
+//----------------------------------------------------------------------
+/// helper class for selecting on mass
+class QuantityM2 : public QuantitySquareBase{
+public:
+  QuantityM2(double m) : QuantitySquareBase(m){}
+  virtual double operator()(const PseudoJet & jet ) const { return jet.m2();}
+  virtual string description() const {return "mass";}
+};  
+
+// returns a selector for a minimum mass
+Selector SelectorMassMin(double mmin) {
+  return Selector(new SW_QuantityMin<QuantityM2>(mmin));
+}
+
+// returns a selector for a maximum mass
+Selector SelectorMassMax(double mmax) {
+  return Selector(new SW_QuantityMax<QuantityM2>(mmax));
+}
+
+// returns a selector for a mass range
+Selector SelectorMassRange(double mmin, double mmax) {
+  return Selector(new SW_QuantityRange<QuantityM2>(mmin, mmax));
+}
+
+
+
+//----------------------------------------------------------------------
+/// helper for selecting on rapidities: quantity
+class QuantityRap : public QuantityBase{
+public:
+  QuantityRap(double rap) : QuantityBase(rap){}
+  virtual double operator()(const PseudoJet & jet ) const { return jet.rap();}
+  virtual string description() const {return "rap";}
+  virtual bool is_geometric() const { return true;}
+};  
+
+
+/// helper for selecting on rapidities: min
+class SW_RapMin : public SW_QuantityMin<QuantityRap>{
+public:
+  SW_RapMin(double rapmin) : SW_QuantityMin<QuantityRap>(rapmin){}
+  virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
+    rapmax = std::numeric_limits<double>::max();     
+    rapmin = _qmin.comparison_value();
+  }
+};
+
+/// helper for selecting on rapidities: max
+class SW_RapMax : public SW_QuantityMax<QuantityRap>{
+public:
+  SW_RapMax(double rapmax) : SW_QuantityMax<QuantityRap>(rapmax){}
+  virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
+    rapmax = _qmax.comparison_value(); 
+    rapmin = -std::numeric_limits<double>::max();
+  }
+};
+
+/// helper for selecting on rapidities: range
+class SW_RapRange : public SW_QuantityRange<QuantityRap>{
+public:
+  SW_RapRange(double rapmin, double rapmax) : SW_QuantityRange<QuantityRap>(rapmin, rapmax){
+    assert(rapmin<=rapmax);
+  }
+  virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
+    rapmax = _qmax.comparison_value();      
+    rapmin = _qmin.comparison_value(); 
+  }
+  virtual bool has_known_area() const { return true;} ///< the area is analytically known
+  virtual double known_area() const { 
+    return twopi * (_qmax.comparison_value()-_qmin.comparison_value());
+  }
+};
+
+// returns a selector for a minimum rapidity
+Selector SelectorRapMin(double rapmin) {
+  return Selector(new SW_RapMin(rapmin));
+}
+
+// returns a selector for a maximum rapidity
+Selector SelectorRapMax(double rapmax) {
+  return Selector(new SW_RapMax(rapmax));
+}
+
+// returns a selector for a rapidity range
+Selector SelectorRapRange(double rapmin, double rapmax) {
+  return Selector(new SW_RapRange(rapmin, rapmax));
+}
+
+
+//----------------------------------------------------------------------
+/// helper for selecting on |rapidities|
+class QuantityAbsRap : public QuantityBase{
+public:
+  QuantityAbsRap(double absrap) : QuantityBase(absrap){}
+  virtual double operator()(const PseudoJet & jet ) const { return abs(jet.rap());}
+  virtual string description() const {return "|rap|";}
+  virtual bool is_geometric() const { return true;}
+};  
+
+
+/// helper for selecting on |rapidities|: max
+class SW_AbsRapMax : public SW_QuantityMax<QuantityAbsRap>{
+public:
+  SW_AbsRapMax(double absrapmax) : SW_QuantityMax<QuantityAbsRap>(absrapmax){}
+  virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
+    rapmax =  _qmax.comparison_value(); 
+    rapmin = -_qmax.comparison_value();
+  }
+  virtual bool has_known_area() const { return true;}   ///< the area is analytically known
+  virtual double known_area() const { 
+    return twopi * 2 * _qmax.comparison_value();
+  }
+};
+
+/// helper for selecting on |rapidities|: max
+class SW_AbsRapRange : public SW_QuantityRange<QuantityAbsRap>{
+public:
+  SW_AbsRapRange(double absrapmin, double absrapmax) : SW_QuantityRange<QuantityAbsRap>(absrapmin, absrapmax){}
+  virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
+    rapmax =  _qmax.comparison_value(); 
+    rapmin = -_qmax.comparison_value();
+  }
+  virtual bool has_known_area() const { return true;} ///< the area is analytically known
+  virtual double known_area() const { 
+    return twopi * 2 * (_qmax.comparison_value()-max(_qmin.comparison_value(),0.0)); // this should handle properly absrapmin<0
+  }
+};
+
+// returns a selector for a minimum |rapidity|
+Selector SelectorAbsRapMin(double absrapmin) {
+  return Selector(new SW_QuantityMin<QuantityAbsRap>(absrapmin));
+}
+
+// returns a selector for a maximum |rapidity|
+Selector SelectorAbsRapMax(double absrapmax) {
+  return Selector(new SW_AbsRapMax(absrapmax));
+}
+
+// returns a selector for a |rapidity| range
+Selector SelectorAbsRapRange(double rapmin, double rapmax) {
+  return Selector(new SW_AbsRapRange(rapmin, rapmax));
+}
+
+
+//----------------------------------------------------------------------
+/// helper for selecting on pseudo-rapidities
+class QuantityEta : public QuantityBase{
+public:
+  QuantityEta(double eta) : QuantityBase(eta){}
+  virtual double operator()(const PseudoJet & jet ) const { return jet.eta();}
+  virtual string description() const {return "eta";}
+  // virtual bool is_geometric() const { return true;} // not strictly only y and phi-dependent
+};  
+
+// returns a selector for a pseudo-minimum rapidity
+Selector SelectorEtaMin(double etamin) {
+  return Selector(new SW_QuantityMin<QuantityEta>(etamin));
+}
+
+// returns a selector for a pseudo-maximum rapidity
+Selector SelectorEtaMax(double etamax) {
+  return Selector(new SW_QuantityMax<QuantityEta>(etamax));
+}
+
+// returns a selector for a pseudo-rapidity range
+Selector SelectorEtaRange(double etamin, double etamax) {
+  return Selector(new SW_QuantityRange<QuantityEta>(etamin, etamax));
+}
+
+
+//----------------------------------------------------------------------
+/// helper for selecting on |pseudo-rapidities|
+class QuantityAbsEta : public QuantityBase{
+public:
+  QuantityAbsEta(double abseta) : QuantityBase(abseta){}
+  virtual double operator()(const PseudoJet & jet ) const { return abs(jet.eta());}
+  virtual string description() const {return "|eta|";}
+  virtual bool is_geometric() const { return true;}
+};  
+
+// returns a selector for a minimum |pseudo-rapidity|
+Selector SelectorAbsEtaMin(double absetamin) {
+  return Selector(new SW_QuantityMin<QuantityAbsEta>(absetamin));
+}
+
+// returns a selector for a maximum |pseudo-rapidity|
+Selector SelectorAbsEtaMax(double absetamax) {
+  return Selector(new SW_QuantityMax<QuantityAbsEta>(absetamax));
+}
+
+// returns a selector for a |pseudo-rapidity| range
+Selector SelectorAbsEtaRange(double absetamin, double absetamax) {
+  return Selector(new SW_QuantityRange<QuantityAbsEta>(absetamin, absetamax));
+}
+
+
+//----------------------------------------------------------------------
+/// helper for selecting on azimuthal angle
+///
+/// Note that the bounds have to be specified as min<max
+/// phimin has to be > -2pi
+/// phimax has to be <  4pi
+class SW_PhiRange : public SelectorWorker {
+public:
+  /// detfault ctor (initialises the pt cut)
+  SW_PhiRange(double phimin, double phimax) : _phimin(phimin), _phimax(phimax){
+    assert(_phimin<_phimax);
+    assert(_phimin>-twopi);
+    assert(_phimax<2*twopi);
+
+    _phispan = _phimax - _phimin;
+  }
+
+  /// returns true is the given object passes the selection pt cut
+  virtual bool pass(const PseudoJet & jet) const {
+    double dphi=jet.phi()-_phimin;
+    if (dphi >= twopi) dphi -= twopi;
+    if (dphi < 0)      dphi += twopi;
+    return (dphi <= _phispan);
+  }
+
+  /// returns a description of the worker
+  virtual string description() const {
+    ostringstream ostr;
+    ostr << _phimin << " <= phi <= " << _phimax;
+    return ostr.str();
+  }
+
+  virtual bool is_geometric() const { return true;}
+
+protected:
+  double _phimin;   // the lower cut 
+  double _phimax;   // the upper cut
+  double _phispan;  // the span of the range
+};
+
+
+// returns a selector for a phi range
+Selector SelectorPhiRange(double phimin, double phimax) {
+  return Selector(new SW_PhiRange(phimin, phimax));
+}
+
+//----------------------------------------------------------------------
+/// helper for selecting on both rapidity and azimuthal angle
+class SW_RapPhiRange : public SW_And{
+public:
+  SW_RapPhiRange(double rapmin, double rapmax, double phimin, double phimax)
+    : SW_And(SelectorRapRange(rapmin, rapmax), SelectorPhiRange(phimin, phimax)){
+    _known_area = ((phimax-phimin > twopi) ? twopi : phimax-phimin) * (rapmax-rapmin);
+  }
+
+  /// if it has a computable area, return it
+  virtual double known_area() const{
+    return _known_area;
+  }
+
+protected:
+  double _known_area;
+};
+
+Selector SelectorRapPhiRange(double rapmin, double rapmax, double phimin, double phimax) {
+  return Selector(new SW_RapPhiRange(rapmin, rapmax, phimin, phimax));
+}
+
+
+//----------------------------------------------------------------------
+/// helper for selecting the n hardest jets
+class SW_NHardest : public SelectorWorker {
+public:
+  /// ctor with specification of the number of objects to keep
+  SW_NHardest(unsigned int n) : _n(n) {};
+
+  /// pass makes no sense here normally the parent selector will throw
+  /// an error but for internal use in the SW, we'll throw one from
+  /// here by security
+  virtual bool pass(const PseudoJet &) const {
+    if (!applies_jet_by_jet())
+      throw Error("Cannot apply this selector worker to an individual jet");
+    return false;
+  }
+
+  /// For each jet that does not pass the cuts, this routine sets the 
+  /// pointer to 0. 
+  virtual void terminator(vector<const PseudoJet *> & jets) const {
+    // nothing to do if the size is too small
+    if (jets.size() < _n) return;
+
+    // do we want to first chech if things are already ordered before
+    // going through the ordering process? For now, no. Maybe carry
+    // out timing tests at some point to establish the optimal
+    // strategy.
+
+    vector<double> minus_pt2(jets.size());
+    vector<unsigned int> indices(jets.size());
+
+    for (unsigned int i=0; i<jets.size(); i++){
+      indices[i] = i;
+
+      // we need to make sure that the object has not already been
+      // nullified.  Note that if we have less than _n jets, this
+      // whole n-hardest selection will not have any effect.
+      minus_pt2[i] = jets[i] ? -jets[i]->perp2() : 0.0;
+    }
+    
+    IndexedSortHelper sort_helper(& minus_pt2);
+    
+    partial_sort(indices.begin(), indices.begin()+_n, indices.end(), sort_helper);
+    
+    for (unsigned int i=_n; i<jets.size(); i++)
+      jets[indices[i]] = NULL;
+  }
+  
+  /// returns true if this can be applied jet by jet
+  virtual bool applies_jet_by_jet() const {return false;}
+  
+  /// returns a description of the worker
+  virtual string description() const {
+    ostringstream ostr;
+    ostr << _n << " hardest";
+    return ostr.str();
+  }
+  
+protected:
+  unsigned int _n;
+};
+
+
+// returns a selector for the n hardest jets
+Selector SelectorNHardest(unsigned int n) {
+  return Selector(new SW_NHardest(n));
+}
+
+
+
+//----------------------------------------------------------------------
+// selector and workers for geometric ranges
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+/// a generic class for objects that contain a position
+class SW_WithReference : public SelectorWorker{
+public:
+  /// ctor
+  SW_WithReference() : _is_initialised(false){};
+
+  /// returns true if the worker takes a reference jet
+  virtual bool takes_reference() const { return true;}
+
+  /// sets the reference jet
+  virtual void set_reference(const PseudoJet &centre){
+    _is_initialised = true;
+    _reference = centre;
+  }
+
+protected:
+  PseudoJet _reference;
+  bool _is_initialised;
+};
+
+//----------------------------------------------------------------------
+/// helper for selecting on objects within a distance 'radius' of a reference
+class SW_Circle : public SW_WithReference {
+public:
+  SW_Circle(const double &radius) : _radius2(radius*radius) {}
+
+  /// return a copy of the current object
+  virtual SelectorWorker* copy(){ return new SW_Circle(*this);}
+
+  /// returns true if a given object passes the selection criterium
+  /// this has to be overloaded by derived workers
+  virtual bool pass(const PseudoJet & jet) const {
+    // make sure the centre is initialised
+    if (! _is_initialised)
+      throw Error("To use a SelectorCircle (or any selector that requires a reference), you first have to call set_reference(...)");
+    
+    return jet.squared_distance(_reference) <= _radius2;
+  } 
+
+  /// returns a description of the worker
+  virtual string description() const {
+    ostringstream ostr;
+    ostr << "distance from the centre <= " << sqrt(_radius2);
+    return ostr.str();
+  }
+
+  /// returns the rapidity range for which it may return "true"
+  virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{
+    // make sure the centre is initialised
+    if (! _is_initialised)
+      throw Error("To use a SelectorCircle (or any selector that requires a reference), you first have to call set_reference(...)");
+    
+    rapmax = _reference.rap()+sqrt(_radius2);
+    rapmin = _reference.rap()-sqrt(_radius2);
+  }
+
+  virtual bool is_geometric() const { return true;}    ///< implies a finite area
+  virtual bool has_finite_area() const { return true;} ///< regardless of the reference 
+  virtual bool has_known_area() const { return true;}  ///< the area is analytically known
+  virtual double known_area() const { 
+    return pi * _radius2;
+  }
+
+protected:
+  double _radius2;
+};
+
+
+// select on objets within a distance 'radius' of a variable location
+Selector SelectorCircle(const double & radius) {
+  return Selector(new SW_Circle(radius));
+}
+
+
+//----------------------------------------------------------------------
+/// helper for selecting on objects with a distance to a reference
+/// betwene 'radius_in' and 'radius_out'
+class SW_Doughnut : public SW_WithReference {
+public:
+  SW_Doughnut(const double &radius_in, const double &radius_out)
+    : _radius_in2(radius_in*radius_in), _radius_out2(radius_out*radius_out) {}
+
+  /// return a copy of the current object
+  virtual SelectorWorker* copy(){ return new SW_Doughnut(*this);}
+
+  /// returns true if a given object passes the selection criterium
+  /// this has to be overloaded by derived workers
+  virtual bool pass(const PseudoJet & jet) const {
+    // make sure the centre is initialised
+    if (! _is_initialised)
+      throw Error("To use a SelectorDoughnut (or any selector that requires a reference), you first have to call set_reference(...)");
+
+    double distance2 = jet.squared_distance(_reference);
+
+    return (distance2 <= _radius_out2) && (distance2 >= _radius_in2);
+  } 
+
+  /// returns a description of the worker
+  virtual string description() const {
+    ostringstream ostr;
+    ostr << sqrt(_radius_in2) << " <= distance from the centre <= " << sqrt(_radius_out2);
+    return ostr.str();
+  }
+
+  /// returns the rapidity range for which it may return "true"
+  virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{
+    // make sure the centre is initialised
+    if (! _is_initialised)
+      throw Error("To use a SelectorDoughnut (or any selector that requires a reference), you first have to call set_reference(...)");
+
+    rapmax = _reference.rap()+sqrt(_radius_out2);
+    rapmin = _reference.rap()-sqrt(_radius_out2);
+  }
+
+  virtual bool is_geometric() const { return true;}    ///< implies a finite area
+  virtual bool has_finite_area() const { return true;} ///< regardless of the reference 
+  virtual bool has_known_area() const { return true;}  ///< the area is analytically known
+  virtual double known_area() const { 
+    return pi * (_radius_out2-_radius_in2);
+  }
+
+protected:
+  double _radius_in2, _radius_out2;
+};
+
+
+
+// select on objets with distance from the centre is between 'radius_in' and 'radius_out' 
+Selector SelectorDoughnut(const double & radius_in, const double & radius_out) {
+  return Selector(new SW_Doughnut(radius_in, radius_out));
+}
+
+
+//----------------------------------------------------------------------
+/// helper for selecting on objects with rapidity within a distance 'delta' of a reference
+class SW_Strip : public SW_WithReference {
+public:
+  SW_Strip(const double &delta) : _delta(delta) {}
+
+  /// return a copy of the current object
+  virtual SelectorWorker* copy(){ return new SW_Strip(*this);}
+
+  /// returns true if a given object passes the selection criterium
+  /// this has to be overloaded by derived workers
+  virtual bool pass(const PseudoJet & jet) const {
+    // make sure the centre is initialised
+    if (! _is_initialised)
+      throw Error("To use a SelectorStrip (or any selector that requires a reference), you first have to call set_reference(...)");
+    
+    return abs(jet.rap()-_reference.rap()) <= _delta;
+  } 
+
+  /// returns a description of the worker
+  virtual string description() const {
+    ostringstream ostr;
+    ostr << "|rap - rap_reference| <= " << _delta;
+    return ostr.str();
+  }
+
+  /// returns the rapidity range for which it may return "true"
+  virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{
+    // make sure the centre is initialised
+    if (! _is_initialised)
+      throw Error("To use a SelectorStrip (or any selector that requires a reference), you first have to call set_reference(...)");
+    
+    rapmax = _reference.rap()+_delta;
+    rapmin = _reference.rap()-_delta;
+  }
+
+  virtual bool is_geometric() const { return true;}    ///< implies a finite area
+  virtual bool has_finite_area() const { return true;} ///< regardless of the reference 
+  virtual bool has_known_area() const { return true;}  ///< the area is analytically known
+  virtual double known_area() const { 
+    return twopi * 2 * _delta;
+  }
+
+protected:
+  double _delta;
+};
+
+
+// select on objets within a distance 'radius' of a variable location
+Selector SelectorStrip(const double & half_width) {
+  return Selector(new SW_Strip(half_width));
+}
+
+
+//----------------------------------------------------------------------
+/// helper for selecting on objects with rapidity within a distance
+/// 'delta_rap' of a reference and phi within a distanve delta_phi of
+/// a reference
+class SW_Rectangle : public SW_WithReference {
+public:
+  SW_Rectangle(const double &delta_rap, const double &delta_phi)
+    : _delta_rap(delta_rap),  _delta_phi(delta_phi) {}
+
+  /// return a copy of the current object
+  virtual SelectorWorker* copy(){ return new SW_Rectangle(*this);}
+
+  /// returns true if a given object passes the selection criterium
+  /// this has to be overloaded by derived workers
+  virtual bool pass(const PseudoJet & jet) const {
+    // make sure the centre is initialised
+    if (! _is_initialised)
+      throw Error("To use a SelectorRectangle (or any selector that requires a reference), you first have to call set_reference(...)");
+
+    return (abs(jet.rap()-_reference.rap()) <= _delta_rap) && (abs(jet.delta_phi_to(_reference)) <= _delta_phi);
+  } 
+
+  /// returns a description of the worker
+  virtual string description() const {
+    ostringstream ostr;
+    ostr << "|rap - rap_reference| <= " << _delta_rap << " && |phi - phi_reference| <= " << _delta_phi ;
+    return ostr.str();
+  }
+
+  /// returns the rapidity range for which it may return "true"
+  virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{
+    // make sure the centre is initialised
+    if (! _is_initialised)
+      throw Error("To use a SelectorRectangle (or any selector that requires a reference), you first have to call set_reference(...)");
+
+    rapmax = _reference.rap()+_delta_rap;
+    rapmin = _reference.rap()-_delta_rap;
+  }
+
+  virtual bool is_geometric() const { return true;}    ///< implies a finite area
+  virtual bool has_finite_area() const { return true;} ///< regardless of the reference 
+  virtual bool has_known_area() const { return true;}  ///< the area is analytically known
+  virtual double known_area() const { 
+    return 4 * _delta_rap * _delta_phi;
+  }
+
+protected:
+  double _delta_rap, _delta_phi;
+};
+
+
+// select on objets within a distance 'radius' of a variable location
+Selector SelectorRectangle(const double & half_rap_width, const double & half_phi_width) {
+  return Selector(new SW_Rectangle(half_rap_width, half_phi_width));
+}
+
+
+//----------------------------------------------------------------------
+/// helper for selecting the jets that carry at least a given fraction
+/// of the reference jet
+class SW_PtFractionMin : public SW_WithReference {
+public:
+  /// ctor with specification of the number of objects to keep
+  SW_PtFractionMin(double fraction) : _fraction2(fraction*fraction){}
+
+  /// return a copy of the current object
+  virtual SelectorWorker* copy(){ return new SW_PtFractionMin(*this);}
+
+  /// return true if the jet carries a large enough fraction of the reference.
+  /// Throw an error if the reference is not initialised.
+  virtual bool pass(const PseudoJet & jet) const {
+    // make sure the centre is initialised
+    if (! _is_initialised)
+      throw Error("To use a SelectorPtFractionMin (or any selector that requires a reference), you first have to call set_reference(...)");
+
+    // otherwise, just call that method on the jet
+    return (jet.perp2() >= _fraction2*_reference.perp2());
+  }
+  
+  /// returns a description of the worker
+  virtual string description() const {
+    ostringstream ostr;
+    ostr << "pt >= " << sqrt(_fraction2) << "* pt_ref";
+    return ostr.str();
+  }
+
+protected:
+  double _fraction2;
+};
+
+
+// select objects that carry at least a fraction "fraction" of the reference jet
+// (Note that this selectir takes a reference)
+Selector SelectorPtFractionMin(double fraction){
+  return Selector(new SW_PtFractionMin(fraction));
+}
+
+
+//----------------------------------------------------------------------
+// additional (mostly helper) selectors
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+/// helper for selecting the 0-momentum jets
+class SW_IsZero : public SelectorWorker {
+public:
+  /// ctor
+  SW_IsZero(){}
+
+  /// return true if the jet has zero momentum
+  virtual bool pass(const PseudoJet & jet) const {
+    return jet==0;
+  }
+  
+  /// rereturns a description of the worker
+  virtual string description() const { return "zero";}
+};
+
+
+// select objects with zero momentum
+Selector SelectorIsZero(){
+  return Selector(new SW_IsZero());
+}
+
+
+//----------------------------------------------------------------------
+/// helper for selecting the pure ghost
+class SW_IsPureGhost : public SelectorWorker {
+public:
+  /// ctor
+  SW_IsPureGhost(){}
+
+  /// return true if the jet is a pure-ghost jet
+  virtual bool pass(const PseudoJet & jet) const {
+    // if the jet has no area support then it's certainly not a ghost
+    if (!jet.has_area()) return false;
+
+    // otherwise, just call that method on the jet
+    return jet.is_pure_ghost();
+  }
+  
+  /// rereturns a description of the worker
+  virtual string description() const { return "pure ghost";}
+};
+
+
+// select objects that are (or are only made of) ghosts
+Selector SelectorIsPureGhost(){
+  return Selector(new SW_IsPureGhost());
+}
+
+
+//----------------------------------------------------------------------
+// Selector and workers for obtaining a Selector from an old
+// RangeDefinition
+//
+// This is mostly intended for backward compatibility and is likely to
+// be removed in a future major release of FastJet
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+/// helper for selecting on both rapidity and azimuthal angle
+class SW_RangeDefinition : public SelectorWorker{
+public:
+  /// ctor from a RangeDefinition
+  SW_RangeDefinition(const RangeDefinition &range) : _range(&range){}
+
+  /// transfer the selection creterium to the underlying RangeDefinition
+  virtual bool pass(const PseudoJet & jet) const {
+    return _range->is_in_range(jet);
+  } 
+
+  /// returns a description of the worker
+  virtual string description() const {
+    return _range->description();
+  }
+
+  /// returns the rapidity range for which it may return "true"
+  virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{
+    _range->get_rap_limits(rapmin, rapmax);
+  }
+
+  /// check if it has a finite area
+  virtual bool is_geometric() const { return true;}
+
+  /// check if it has an analytically computable area
+  virtual bool has_known_area() const { return true;}
+  
+  /// if it has a computable area, return it
+  virtual double known_area() const{
+    return _range->area();
+  }
+
+protected:
+  const RangeDefinition *_range;
+};
+
+
+// ctor from a RangeDefinition
+//----------------------------------------------------------------------
+//
+// This is provided for backward compatibility and will be removed in
+// a future major release of FastJet
+Selector::Selector(const RangeDefinition &range) {
+  _worker.reset(new SW_RangeDefinition(range));
+}
+
+
+// operators applying directly on a Selector
+//----------------------------------------------------------------------
+
+// operator &=
+// For 2 Selectors a and b, a &= b is eauivalent to a = a & b;
+Selector & Selector::operator &=(const Selector & b){
+  _worker.reset(new SW_And(*this, b));
+  return *this;
+}
+
+// operator &=
+// For 2 Selectors a and b, a &= b is eauivalent to a = a & b;
+Selector & Selector::operator |=(const Selector & b){
+  _worker.reset(new SW_Or(*this, b));
+  return *this;
+}
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/Selector.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/Selector.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/Selector.hh	(revision 5)
@@ -0,0 +1,466 @@
+#ifndef __SELECTOR_HH__
+#define __SELECTOR_HH__
+
+//STARTHEADER
+// $Id: Selector.hh 2687 2011-11-14 11:17:51Z soyez $
+//
+// Copyright (c) 2009-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/RangeDefinition.hh"  // for initialisation from a RangeDefinition
+#include <limits>
+#include <cmath>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+/// @ingroup selectors
+/// \class Selector
+/// Class that encodes information about cuts and other selection
+/// criteria that can be applied to PseudoJet(s).
+///
+class Selector;
+//----------------------------------------------------------------------
+
+/// @ingroup selectors
+/// \class SelectorWorker
+/// default selector worker is an abstract virtual base class
+///
+/// The Selector class is only an interface, it is the SelectorWorker
+/// that really does the work. To implement various selectors, one
+/// thus has to overload this class.
+class SelectorWorker {
+public:
+  //----------------------------------------------------------
+  // fundamental info
+  //----------------------------------------------------------
+  /// default dtor
+  virtual ~SelectorWorker() {}
+
+  //----------------------------------------------------------
+  // basic operations for checking what gets selected
+  //----------------------------------------------------------
+
+  /// returns true if a given object passes the selection criterion.
+  /// This has to be overloaded by derived workers
+  virtual bool pass(const PseudoJet & jet) const = 0;
+
+  /// For each jet that does not pass the cuts, this routine sets the 
+  /// pointer to 0. 
+  ///
+  /// It does not assume that the PseudoJet* passed as argumetn are not NULL
+  virtual void terminator(std::vector<const PseudoJet *> & jets) const {
+    for (unsigned i = 0; i < jets.size(); i++) {
+      if (jets[i] && !pass(*jets[i])) jets[i] = NULL;
+    }
+  }
+
+  /// returns true if this can be applied jet by jet
+  virtual bool applies_jet_by_jet() const {return true;}
+
+  /// returns a description of the worker
+  virtual std::string description() const {return "missing description";}
+
+
+  //----------------------------------------------------------
+  // operations for dealing with reference jets
+  //----------------------------------------------------------
+
+  /// returns true if the worker is defined with respect to a reference jet
+  virtual bool takes_reference() const { return false;}
+
+  /// sets the reference jet for the selector
+  /// NB: "reference" is commented to avoid unused-variable compiler warnings
+  virtual void set_reference(const PseudoJet & /*reference*/){
+    throw Error("set_reference(...) cannot be used for a selector worker that does not take a reference");
+  }
+
+  /// return a copy of the current object.
+  ///
+  /// This function is only called for objects that take a reference and need
+  /// not be reimplemented otherwise.
+  virtual SelectorWorker* copy(){ 
+    throw Error("this SelectorWorker has nothing to copy");
+  }
+
+  //----------------------------------------------------------
+  // operations for area and extent
+  //----------------------------------------------------------
+
+  /// returns the rapidity range for which it may return "true"
+  virtual void get_rapidity_extent(double & rapmin, double & rapmax) const {
+    rapmax = std::numeric_limits<double>::infinity();
+    rapmin = -rapmax; 
+  }
+
+  /// check if it is a geometric selector (i.e. only puts constraints
+  /// on rapidity and azimuthal angle)
+  virtual bool is_geometric() const { return false;}
+
+  /// check if it has a finite area
+  virtual bool has_finite_area() const;
+
+  /// check if it has an analytically computable area
+  virtual bool has_known_area() const { return false;}
+
+  /// if it has a computable area, return it
+  virtual double known_area() const{
+    throw Error("this selector has no computable area");
+  }
+};
+
+//----------------------------------------------------------------------
+// class Selector
+//
+// Class that encodes information about cuts that 
+class Selector{
+public:
+  /// default constructor produces a Selector whose action is undefined
+  /// (any attempt to use it will lead to an error)
+  Selector() {}
+
+  /// constructor that causes the Selector to use the supplied worker
+  ///
+  /// Note that the Selector takes ownership of the pointer to the
+  /// worker (and so will delete automatically when appropriate).
+  Selector(SelectorWorker * worker_in) {_worker.reset(worker_in);}
+
+
+  /// ctor from a RangeDefinition
+  ///
+  /// This is provided for backward compatibility and will be removed in
+  /// a future major release of FastJet
+  ///
+  /// Watch out that the Selector will only hold a pointer to the
+  /// range so the selector will crash if one tries to use it after
+  /// the range has gone out of scope. We thus strongly advise against
+  /// the direct use of this constructor.
+  Selector(const RangeDefinition &range);
+
+  /// dummy virtual dtor
+  virtual ~Selector(){}
+
+  /// return true if the jet passes the selection
+  bool pass(const PseudoJet & jet) const {
+    if (!validated_worker()->applies_jet_by_jet()) {
+      throw Error("Cannot apply this selector to an individual jet");
+    }
+    return _worker->pass(jet);
+  }
+
+  /// an operator way of knowing whether a given jet passes the selection or not
+  bool operator()(const PseudoJet & jet) const {
+    return pass(jet);
+  }
+
+  /// Return a count of the objects that pass the selection.
+  ///
+  /// This will often be more efficient that getting the vector of objects that
+  /// passes and then evaluating the size of the vector
+  unsigned int count(const std::vector<PseudoJet> & jets) const;
+
+  /// sift the input jets into two vectors -- those that pass the selector
+  /// and those that do not
+  void sift(const std::vector<PseudoJet> & jets,
+		  std::vector<PseudoJet> & jets_that_pass,
+		  std::vector<PseudoJet> & jets_that_fail) const;
+
+  /// returns true if this can be applied jet by jet
+  bool applies_jet_by_jet() const {
+    return validated_worker()->applies_jet_by_jet();
+  }
+
+  /// returns a vector with the jets that pass the selection
+  std::vector<PseudoJet> operator()(const std::vector<PseudoJet> & jets) const;
+
+  /// For each jet that does not pass the cuts, this routine sets the 
+  /// pointer to 0. 
+  ///
+  /// It is legitimate for some (or all) of the pointers that are
+  /// passed to already be NULL.
+  virtual void nullify_non_selected(std::vector<const PseudoJet *> & jets) const {
+    validated_worker()->terminator(jets);
+  }
+
+  /// returns the rapidity range for which it may return "true"
+  void get_rapidity_extent(double &rapmin, double &rapmax) const {
+    return validated_worker()->get_rapidity_extent(rapmin, rapmax);
+  }
+
+  /// returns a textual description of the selector
+  std::string description() const {
+    return validated_worker()->description();
+  }
+
+  /// returns true if it is a geometric selector (i.e. one that only puts
+  /// constraints on rapidities and azimuthal angles)
+  bool is_geometric() const{
+    return validated_worker()->is_geometric();
+  }
+
+  /// returns true if it has a meaningful and finite area (i.e. the
+  /// Selector has the property that is_geometric() returns true and
+  /// the rapidity extent is finite).
+  bool has_finite_area() const{
+    return validated_worker()->has_finite_area();
+  }
+
+  /// returns the rapidity-phi area associated with the Selector
+  /// (throws InvalidArea if the area does not make sense).
+  ///
+  /// If the result is not known analytically, the area will be
+  /// estimated using a pseudo Monte Carlo method (as for jet areas),
+  /// using the default ghost area from the GhostedAreaSpec class
+  /// (0.01). The Monte Carlo estimate involves a time penalty
+  /// proportional to the ratio of the rapidity extent of the Selector
+  /// divided by the ghost area.
+  double area() const;
+
+  /// returns the rapidity-phi area associated with the Selector
+  /// (throws InvalidArea if the area does not make sense).
+  ///
+  /// The behaviour is the as with the area() call, but with the
+  /// ability to additionally specify the ghost area to be used in the
+  /// case of a Monte Carlo area evaluation.
+  ///
+  double area(double ghost_area) const;
+
+  /// returns a (reference to) the underlying worker's shared pointer
+  const SharedPtr<SelectorWorker> & worker() const {return _worker;}
+
+  /// returns a worker if there is a valid one, otherwise throws an InvalidWorker error
+  const SelectorWorker* validated_worker() const {
+    const SelectorWorker* worker_ptr = _worker.get();
+    if (worker_ptr == 0) throw InvalidWorker();
+    return worker_ptr;
+  }
+
+  /// returns true if this can be applied jet by jet
+  bool takes_reference() const {
+    return validated_worker()->takes_reference();
+  }
+
+  /// set the reference jet for this Selector
+  const Selector & set_reference(const PseudoJet &reference){
+
+    // if the worker does not take a reference jet, do nothing 
+    if (! validated_worker()->takes_reference()){
+      return *this;
+    }
+    
+    // since this is a non-const operation, make sure we have a
+    // correct behaviour with respect to shared workers
+    _copy_worker_if_needed();
+
+    _worker->set_reference(reference);
+    return *this;
+  }
+
+  /// class that gets throw when a Selector is applied despite it not
+  /// having a valid underlying worker.
+  class InvalidWorker : public Error {
+  public:
+    InvalidWorker() : Error("Attempt to use Selector with no valid underlying worker") {}
+  };
+
+  /// class that gets throw when a Selector is applied despite it not
+  /// having a valid underlying worker.
+  class InvalidArea : public Error {
+  public:
+    InvalidArea() : Error("Attempt to obtain area from Selector for which this is not meaningful") {}
+  };
+
+  // some operators (applying directly on a Selector)
+  //----------------------------------------------------------------------
+  /// For 2 Selectors a and b, a &= b is eauivalent to a = a && b;
+  Selector & operator &=(const Selector & b);
+
+  /// For 2 Selectors a and b, a |= b is eauivalent to a = a || b;
+  Selector & operator |=(const Selector & b);
+
+
+protected:
+  /// Helper for copying selector workers if needed
+  ///
+  /// The following is needed if we want to modify a selectors that
+  /// shares a worker with another selector. In that case, we need to
+  /// get another copy of the worker to avoid interferences
+  ///
+  /// Note that any non-const operation has to call this to behave
+  /// correctly w.r.t shared workers!
+  void _copy_worker_if_needed(){
+    // do nothing if there's a sinlge user of the worker
+    if (_worker.unique()) return;
+
+    // call the worker's copy
+    //std::cout << "will make a copy of " << description() << std::endl;
+    _worker.reset(_worker->copy());
+  }
+
+private:
+  SharedPtr<SelectorWorker> _worker; ///< the underlying worker
+};
+
+
+//----------------------------------------------------------------------
+// a list of specific selectors
+//----------------------------------------------------------------------
+
+/// \addtogroup selectors
+/// @{
+
+
+// fundamental selectors
+//----------------------------------------------------------------------
+
+// "identity" selector that lets everything pass
+Selector SelectorIdentity();
+
+// logical operations
+//----------------------------------------------------------------------
+
+/// logical not applied on a selector
+///
+/// This will keep objects that do not pass the 's' selector
+Selector operator!(const Selector & s);
+
+/// logical or between two selectors
+///
+/// this will keep the objects that are selected by s1 or s2
+Selector operator ||(const Selector & s1, const Selector & s2);
+
+
+/// logical and between two selectors
+///
+/// this will keep the objects that are selected by both s1 and s2
+/// 
+/// watch out: for both s1 and s2, the selection is applied on the
+///   original list of objects. For successive applications of two
+///   selectors (convolution/multiplication) see the operator *
+Selector operator&&(const Selector & s1, const Selector & s2);
+
+/// successive application of 2 selectors
+///
+/// Apply the selector s2, then the selector s1.
+///
+/// watch out: the operator * acts like an operator product i.e. does
+///   not commute. The order of its arguments is therefore important.
+///   Whenever they commute (in particluar, when they apply jet by
+///   jet), this would have the same effect as the logical &&.
+Selector operator*(const Selector & s1, const Selector & s2);
+
+
+// selection with kinematic cuts
+//----------------------------------------------------------------------
+Selector SelectorPtMin(double ptmin);                    ///< select objects with pt >= ptmin
+Selector SelectorPtMax(double ptmax);                    ///< select objects with pt <= ptmax
+Selector SelectorPtRange(double ptmin, double ptmax);    ///< select objects with ptmin <= pt <= ptmax
+
+Selector SelectorEtMin(double Etmin);                    ///< select objects with Et >= Etmin
+Selector SelectorEtMax(double Etmax);                    ///< select objects with Et <= Etmax
+Selector SelectorEtRange(double Etmin, double Etmax);    ///< select objects with Etmin <= Et <= Etmax
+
+Selector SelectorEMin(double Emin);                      ///< select objects with E >= Emin
+Selector SelectorEMax(double Emax);                      ///< select objects with E <= Emax
+Selector SelectorERange(double Emin, double Emax);       ///< select objects with Emin <= E <= Emax
+
+Selector SelectorMassMin(double Mmin);                      ///< select objects with Mass >= Mmin
+Selector SelectorMassMax(double Mmax);                      ///< select objects with Mass <= Mmax
+Selector SelectorMassRange(double Mmin, double Mmax);       ///< select objects with Mmin <= Mass <= Mmax
+
+Selector SelectorRapMin(double rapmin);                  ///< select objects with rap >= rapmin
+Selector SelectorRapMax(double rapmax);                  ///< select objects with rap <= rapmax
+Selector SelectorRapRange(double rapmin, double rapmax); ///< select objects with rapmin <= rap <= rapmax
+
+Selector SelectorAbsRapMin(double absrapmin);                     ///< select objects with |rap| >= absrapmin
+Selector SelectorAbsRapMax(double absrapmax);                     ///< select objects with |rap| <= absrapmax
+Selector SelectorAbsRapRange(double absrapmin, double absrapmax); ///< select objects with absrapmin <= |rap| <= absrapmax
+
+Selector SelectorEtaMin(double etamin);                  ///< select objects with eta >= etamin
+Selector SelectorEtaMax(double etamax);                  ///< select objects with eta <= etamax
+Selector SelectorEtaRange(double etamin, double etamax); ///< select objects with etamin <= eta <= etamax
+
+Selector SelectorAbsEtaMin(double absetamin);                     ///< select objects with |eta| >= absetamin
+Selector SelectorAbsEtaMax(double absetamax);                     ///< select objects with |eta| <= absetamax
+Selector SelectorAbsEtaRange(double absetamin, double absetamax); ///< select objects with absetamin <= |eta| <= absetamax
+
+Selector SelectorPhiRange(double phimin, double phimax); ///< select objects with phimin <= phi <= phimax
+
+/// select objects with rapmin <= rap <= rapmax  &&  phimin <= phi <= phimax
+///
+/// Note that this is essentially a combination of SelectorRapRange
+/// and SelectorPhiRange. We provide it as a Selector on its own in
+/// order to use the known area (which would otherwise be lost by the &&
+/// operator)
+Selector SelectorRapPhiRange(double rapmin, double rapmax, double phimin, double phimax);
+
+/// select the n hardest objects 
+Selector SelectorNHardest(unsigned int n); 
+
+
+// Selectors that take (require) a reference jet.
+//----------------------------------------------------------------------
+
+/// select objets within a distance 'radius' from the location of the
+/// reference jet, set by Selector::set_reference(...)
+Selector SelectorCircle(const double & radius); 
+
+/// select objets with distance from the reference jet is between 'radius_in'
+/// and 'radius_out'; the reference jet is set by Selector::set_reference(...)
+Selector SelectorDoughnut(const double & radius_in, const double & radius_out); 
+
+/// select objets within a rapidity distance 'half_width' from the
+/// location of the reference jet, set by Selector::set_reference(...)
+Selector SelectorStrip(const double & half_width);
+
+/// select objets within rapidity distance 'half_rap_width' from the
+/// reference jet and azimuthal-angle distance within 'half_phi_width'; the
+/// reference jet is set by Selector::set_reference(...)
+Selector SelectorRectangle(const double & half_rap_width, const double & half_phi_width);
+
+
+/// select objects that carry at least a fraction "fraction" of the
+/// reference jet. The reference jet must have been set with
+/// Selector::set_reference(...)
+Selector SelectorPtFractionMin(double fraction);
+
+
+// additional (mostly helper) selectors
+//----------------------------------------------------------------------
+
+/// select PseudoJet with 0 momentum
+Selector SelectorIsZero();
+
+/// select objects that are (or are only made of) ghosts.
+/// PseudoJets for which has_area() are considered non-pure-ghost.
+Selector SelectorIsPureGhost();
+
+/// @}
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
+
+#endif // __SELECTOR_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/SharedPtr.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/SharedPtr.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/SharedPtr.hh	(revision 5)
@@ -0,0 +1,396 @@
+#ifndef __FASTJET_SHARED_PTR_HH__
+#define __FASTJET_SHARED_PTR_HH__
+
+//STARTHEADER
+// $Id: SharedPtr.hh 2680 2011-11-12 17:12:05Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/internal/base.hh"
+#include <cstdlib>  // for NULL!!!
+
+// for testing purposes, the following define makes it possible
+// for our SharedPtr simply to be derived from the STL TR1 one.
+// #define USETR1SHAREDPTR
+
+#ifdef USETR1SHAREDPTR
+#include <tr1/memory>
+#endif // USETR1SHAREDPTR
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+#ifdef USETR1SHAREDPTR
+
+/// @ingroup advanced_usage
+/// \class SharedPtr
+/// replaces our shared pointer with the TR1 one (for testing purpose)
+///
+/// for testing purposes, it can be useful to replace our home-made
+/// SharedPtr with the standard library one. Having a class derived
+/// from the standard one is way of arranging for this to happen.
+/// 
+/// The other way of working this is a template class with an 
+/// internal typedef (http://bytes.com/topic/c/answers/60312-typedef-template)
+/// since templated typedefs don't work in standard C++
+///
+/// Note that some facilities that are present in the FastJet shared
+/// pointer (resetting use-count) are not handled by the TR1 shared
+/// pointer; and the FastJet SharedPtr has a different underlying data
+/// structure from the TR1 shared pointer, which prevents us from
+/// implementing some of TR1 features (notably assignment from shared
+/// pointers to a derived class).
+template<class T>
+class SharedPtr : public std::tr1::shared_ptr<T> {
+public:
+  SharedPtr() : std::tr1::shared_ptr<T>() {}
+  SharedPtr(T * t) : std::tr1::shared_ptr<T>(t) {}
+  SharedPtr(const SharedPtr<T> & t) : std::tr1::shared_ptr<T>(t) {}
+  // for some reason operator() doesn't get inherited
+  inline operator bool() const {return (this->get()!=NULL);}
+  /// return the pointer we're pointing to  
+  T* operator ()() const{
+    return this->get(); // automatically returns NULL when out-of-scope
+  }
+};
+
+
+#else // USETR1SHAREDPTR
+
+/**
+ * @ingroup advanced_usage
+ * \class SharedPtr
+ * an implementation of C++0x shared pointers (or boost's)
+ *
+ * this class implements a smart pointer, based on the shared+ptr
+ * proposal. A description of shared_ptr can be found in Section 2.2.3
+ * of the first C++ Technical Report (TR1)
+ *   http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1745.pdf
+ * or, alternatively, on the Boost C++ library website at
+ *   http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/shared_ptr.htm
+ *
+ * Our implementation is compatible with both of these apart from a
+ * series of members and functions that have not been implemented:
+ *  - conversion from weak and auto pointers
+ *  - support for deleters and allocators
+ *  - static, constant and dynamic casts
+ *  - constructor and assignment sharing ownership with a shared
+ *    pointer r but storing a different pointer than r (needed for the
+ *    previous item)
+ * In the last 2 cases, their implementation would require storing two
+ * pointers for every copies of the shared pointer, while our
+ * implementation only needs one. We did not implement then since we
+ * want to limit as much as possible memory and time consumption, and
+ * can easily avoid (at least for our needs so far) the casts.
+ *
+ * We also add the possibility to force an update of the count.
+ * 
+ * The class has been tested against the existing boost (v1.42)
+ * implementation (for the parts that we have implemented).
+ */
+template<class T>
+class SharedPtr{
+public:
+  /// forward declaration of the counting container
+  class __SharedCountingPtr;
+
+  /// default ctor
+  SharedPtr() : _ptr(NULL){}
+  
+  /// initialise with the main data
+  /// \param  t  : the object we want a smart pointer to
+  template<class Y> explicit SharedPtr(Y* ptr){
+    _ptr = new __SharedCountingPtr(ptr);
+  }
+  
+  /// overload the copy ctor so that it updates count
+  /// \param  share : the object we want to copy
+  SharedPtr(SharedPtr const & share) : _ptr(share._get_container()){
+    if (_ptr!=NULL) ++(*_ptr);
+  }
+  // old version
+  //  SharedPtr(SharedPtr const & share) : _ptr(NULL){
+  //    reset(share);
+  //  }
+    
+  // will not work with the current structure
+  // /// overload the copy ctor so that it updates count
+  // /// \param  share : the object we want to copy
+  // template<class Y> SharedPtr(SharedPtr<Y> const & share) : _ptr(NULL){
+  //   reset(share);
+  // }
+
+  /// default dtor
+  ~SharedPtr(){
+    // make sure the object has been allocated
+    if (_ptr==NULL) return;
+
+    _decrease_count();
+  }
+
+  /// reset the pointer to default value (NULL)
+  void reset(){
+    // // if we already are pointing to sth, be sure to decrease its count
+    // if (_ptr!=NULL) _decrease_count();
+    // _ptr = NULL;
+    SharedPtr().swap(*this);
+  }
+  
+  // will not work with the current structure
+  /// reset from a pointer
+  template<class Y> void reset(Y * ptr){
+    // // if we already are pointing to sth, be sure to decrease its count
+    // if (_ptr!=NULL) _decrease_count();
+    // 
+    // _ptr = new __SharedCountingPtr(ptr);
+    SharedPtr(ptr).swap(*this);
+  }
+
+  // not part of the standard
+  /// do a smart copy
+  /// \param  share : the object we want to copy
+  /// Q? Do we need a non-template<Y> version as for the ctor and the assignment?
+  template<class Y> void reset(SharedPtr<Y> const & share){
+  //void reset(SharedPtr const & share){
+    // if we already are pointing to sth, be sure to decrease its count
+    if (_ptr!=NULL){
+      // in the specific case where we're having the same
+      // share,reset() has actually no effect. However if *this is the
+      // only instance still alive (implying share==*this) bringing
+      // the count down to 0 and deleting the object will not have the
+      // expected effect. So we just avoid that situation explicitly
+      if (_ptr == share._get_container()) return;
+    
+      _decrease_count();
+    }
+    
+    // Watch out: if share is empty, construct an empty shared_ptr
+    
+    // copy the container
+    _ptr = share._get_container();  // Note: automatically set it to NULL if share is empty
+    
+    if (_ptr!=NULL) ++(*_ptr);
+  }
+  
+  /// overload the = operator so that it updates count
+  /// \param  share : the object we want to copy
+  SharedPtr& operator=(SharedPtr const & share){
+    reset(share);
+    return *this;
+  }
+  
+  /// overload the = operator so that it updates count
+  /// \param  share : the object we want to copy
+  template<class Y> SharedPtr& operator=(SharedPtr<Y> const & share){
+    reset(share);
+    return *this;
+  }
+  
+  /// return the pointer we're pointing to  
+  T* operator ()() const{
+    if (_ptr==NULL) return NULL;
+    return _ptr->get(); // automatically returns NULL when out-of-scope
+  }
+  
+  /// indirection, get a reference to the stored pointer
+  ///
+  /// !!! WATCH OUT
+  /// It fails to check the requirement that the stored pointer must
+  /// not be NULL!!  So you need explicitly to check the validity in
+  /// your code
+  inline T& operator*() const{
+    return *(_ptr->get());
+  }
+
+  /// indirection, get the stored pointer
+  ///
+  /// !!! WATCH OUT
+  /// It fails to check the requirement that the stored pointer must
+  /// not be NULL!!  So you need explicitly to check the validity in
+  /// your code
+  inline T* operator->() const{
+    if (_ptr==NULL) return NULL;
+    return _ptr->get();
+  }  
+
+  /// get the stored pointer
+  inline T* get() const{
+    if (_ptr==NULL) return NULL;
+    return _ptr->get();
+  }
+
+  /// check if the instance is unique
+  inline bool unique() const{
+    return (use_count()==1);
+  }
+
+  /// return the number of counts
+  inline long use_count() const{
+    if (_ptr==NULL) return 0;
+    return _ptr->use_count(); // automatically returns NULL when out-of-scope
+  }
+
+  /// conversion to bool
+  /// This will allow you to use the indirection nicely
+  inline operator bool() const{
+    return (get()!=NULL);
+  }
+
+  /// exchange the content of the two pointers
+  inline void swap(SharedPtr & share){
+    __SharedCountingPtr* share_container = share._ptr;
+    share._ptr = _ptr;
+    _ptr = share_container;
+  }
+
+  /// force the count to be set to a specified value
+  ///   \param count   the value that we need to reset to
+  void set_count(const long & count){
+    if (_ptr==NULL) return;
+    _ptr->set_count(count);
+  }
+
+  /**
+   * \if internal_doc
+   * \class __SharedCountingPtr
+   * A reference-counting pointer
+   *
+   * This is implemented as a container for that pointer together with
+   * reference counting.
+   * The pointer is deleted when the number of counts goes to 0;
+   * \endif
+   */
+  class __SharedCountingPtr{
+  public:
+    /// default ctor
+    __SharedCountingPtr() : _ptr(NULL), _count(0){}
+    
+    /// ctor with initialisation
+    template<class Y> explicit __SharedCountingPtr(Y* ptr) : _ptr(ptr), _count(1){}
+    
+    /// default dtor
+    ~__SharedCountingPtr(){ 
+      // force the deletion of the object we keep track of
+      if (_ptr!=NULL){ delete _ptr;}
+    }
+
+    /// return a pointer to the object
+    inline T* get() const {return _ptr;}
+
+    /// return the count
+    inline long use_count() const {return _count;}
+
+    /// prefix increment operator
+    inline long operator++(){return ++_count;}
+
+    /// prefix decrement operator
+    inline long operator--(){return --_count;}
+
+    /// postfix increment operator
+    /// The "dummy" int argument is just a C++ trick to differentiate
+    /// it from the prefix increment
+    inline long operator++(int){return _count++;}
+
+    /// postfix decrement operator
+    /// The "dummy" int argument is just a C++ trick to differentiate
+    /// it from the prefix decrement
+    inline long operator--(int){return _count--;}
+
+    /// force the count to be set to a specified value
+    ///   \param count   the value that we ned to reset to
+    void set_count(const long & count){
+      _count = count;
+    }
+
+  private:
+    T *_ptr;              ///< the pointer we're counting the references to
+    long _count;  ///< the number of references
+  };
+
+private:
+  /// return the common container
+  inline __SharedCountingPtr* _get_container() const{
+    return _ptr;
+  }
+
+  /// decrease the pointer count and support deletion
+  /// Warning: we don't test that the pointer is allocated
+  ///          This can be dangerous if we have explicitly reset the
+  ///          count.  Generally speaking, if the count goes negative
+  ///          after _ptr has been effectively deleted, this is going
+  ///          to lead to a segmentation fault. But, if in the course
+  ///          of the deletion of _ptr, the deletion of its pointer
+  ///          (_ptr::_ptr, i.e. the real data we're storing) makes
+  ///          the counts to become negative, this is going to pass
+  ///          smoothly.
+  void _decrease_count(){
+    // decrease the count
+    (*_ptr)--;
+    
+    // if no one else is using it, free the allocated memory
+    if (_ptr->use_count()==0)
+      delete _ptr; // that automatically deletes the object itself
+  }
+
+  // the real info
+  __SharedCountingPtr *_ptr;
+};
+
+
+/// comparison: equality
+template<class T,class U>
+inline bool operator==(SharedPtr<T> const & t, SharedPtr<U> const & u){
+  return t.get() == u.get();
+}
+
+/// comparison: difference
+template<class T,class U>
+inline bool operator!=(SharedPtr<T> const & t, SharedPtr<U> const & u){
+  return t.get() != u.get();
+}
+
+/// comparison: orgering
+template<class T,class U>
+inline bool operator<(SharedPtr<T> const & t, SharedPtr<U> const & u){
+  return t.get() < u.get();
+}
+
+/// swapping
+template<class T>
+inline void swap(SharedPtr<T> & a, SharedPtr<T> & b){
+  return a.swap(b);
+}
+
+/// getting the pointer
+template<class T>
+inline T* get_pointer(SharedPtr<T> const & t){
+  return t.get();
+}
+
+#endif // USETR1SHAREDPTR
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
+
+#endif   // __FASTJET_SHARED_PTR_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/VERSION
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/VERSION	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/VERSION	(revision 5)
@@ -0,0 +1,1 @@
+3.0.3
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/Voronoi.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/Voronoi.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/Voronoi.cc	(revision 5)
@@ -0,0 +1,1228 @@
+//STARTHEADER
+// $Id: Voronoi.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 1994 by AT&T Bell Laboratories (see below)
+//
+//
+//----------------------------------------------------------------------
+// This file is included as part of FastJet but was mostly written by
+// S. Fortune in C, put into C++ with memory management by S
+// O'Sullivan, and with further interface and memory management
+// modifications by Gregory Soyez.
+//
+// Permission to use, copy, modify, and distribute this software for
+// any purpose without fee is hereby granted, provided that this
+// entire notice is included in all copies of any software which is or
+// includes a copy or modification of this software and in all copies
+// of the supporting documentation for such software. THIS SOFTWARE IS
+// BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTY.
+// IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY REPRESENTATION
+// OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS
+// SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+//
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+/*
+ * The author of this software is Steven Fortune.  
+ * Copyright (c) 1994 by AT&T Bell Laboratories.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+/* 
+ * This code was originally written by Stephan Fortune in C code.  I,
+ * Shane O'Sullivan, have since modified it, encapsulating it in a C++
+ * class and, fixing memory leaks and adding accessors to the Voronoi
+ * Edges.  Permission to use, copy, modify, and distribute this
+ * software for any purpose without fee is hereby granted, provided
+ * that this entire notice is included in all copies of any software
+ * which is or includes a copy or modification of this software and in
+ * all copies of the supporting documentation for such software.  THIS
+ * SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
+ * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ */
+
+/*
+ * This code, included in the FastJet distribution, was originally
+ * written by Stephan Fortune in C and adapted to C++ by Shane
+ * O'Sullivan under the terms reported above.
+ *
+ * Below are the list of changes implemented by the FastJet authors:
+ *
+ * 2011-11-14  Gregory Soyez  <soyez@fastjet.fr>
+ * 
+ *      * removed 'plot' and 'triangulate' (were always 0)
+ *      * removed unused plot functions (openpl, circle, range, 
+ *        out_bisector, out_ep, out_vertex, out_site, out_triple)
+ *      * removed unused 'VPoint p' in 'intersect'
+ *
+ *
+ * 2011-07-22  Gregory Soyez  <soyez@fastjet.fr>
+ * 
+ *      * replaced Point by VPoint (to avoid any potential conflict
+ *        with an already existing class Point in FastJet
+ * 
+ * 
+ * 2011-06-28  Gregory Soyez  <soyez@fastjet.fr>
+ * 
+ *      * added support for situations with degenerate particles (we just
+ *        discard the particles degenerate wiht an already existing
+ *        one which is perfectly sufficient for our needs)
+ *      * in 'VoronoiDiagramGenerator::intersect', improved the numerical
+ *        precision in cases where the 2 parents are nearly degenerate
+ * 
+ * 
+ * 2011-06-14  Gregory Soyez  <soyez@fastjet.fr>
+ * 
+ *      * fixed a potential overflow bug in VoronoiDiagramGenerator::PQbucket
+ * 
+ * 
+ * 2007-05-07  Gregory Soyez  <soyez@fastjet.fr>
+ * 
+ *      * fied a few memory leaks
+ *
+ *      * put the code in the fastjet namespace
+ * 
+ *      * replaced float by double
+ * 
+ *      * generateVoronoi() takes a vector of Point instead of 2
+ *        pointers
+ * 
+ *      * added info about the parent sites to GraphEdge (and clip_line)
+ * 
+ *      * removed condition on minimal distance between sites
+ */
+
+#include <stdio.h>
+#include "fastjet/internal/Voronoi.hh"
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE
+
+LimitedWarning VoronoiDiagramGenerator::_warning_degeneracy;
+
+VoronoiDiagramGenerator::VoronoiDiagramGenerator(){
+  siteidx = 0;
+  sites = NULL;
+  parent_sites = NULL;
+
+  allMemoryList = new FreeNodeArrayList;
+  allMemoryList->memory = NULL;
+  allMemoryList->next = NULL;
+  currentMemoryBlock = allMemoryList;
+  allEdges = NULL;
+  iteratorEdges = 0;
+  minDistanceBetweenSites = 0;
+
+  ELhash = NULL;
+  PQhash = NULL;
+}
+
+VoronoiDiagramGenerator::~VoronoiDiagramGenerator(){
+  cleanup();
+  cleanupEdges();
+
+  if (allMemoryList != NULL)
+    delete allMemoryList;
+}
+
+
+
+bool VoronoiDiagramGenerator::generateVoronoi(vector<VPoint> *_parent_sites,
+					      double minX, double maxX, 
+					      double minY, double maxY, 
+					      double minDist){
+  cleanup();
+  cleanupEdges();
+  int i;
+  double x, y;
+
+  minDistanceBetweenSites = minDist;
+
+  parent_sites = _parent_sites;
+
+  nsites = n_parent_sites = parent_sites->size();
+  debug = 1;
+  sorted = 0; 
+  freeinit(&sfl, sizeof (Site));
+		
+  //sites = (Site *) myalloc(nsites*sizeof( *sites));
+  sites = (Site *) myalloc(nsites*sizeof( Site));
+  //parent_sites = (Site *) myalloc(nsites*sizeof( Site));
+ 
+  if (sites == 0)
+    return false;
+
+  xmax = xmin = (*parent_sites)[0].x;
+  ymax = ymin = (*parent_sites)[0].y;
+  
+  for(i=0;i<nsites;i++){
+    x = (*parent_sites)[i].x;
+    y = (*parent_sites)[i].y;
+    sites[i].coord.x = x;
+    sites[i].coord.y = y;
+    sites[i].sitenbr = i;
+    sites[i].refcnt  = 0;
+    
+    if (x<xmin)
+      xmin=x;
+    else if (x>xmax)
+      xmax=x;
+    
+    if (y<ymin)
+      ymin=y;
+    else if (y>ymax)
+      ymax=y;
+  }
+	
+  qsort(sites, nsites, sizeof (*sites), scomp);
+
+  // Gregory Soyez
+  // 
+  // check if some of the particles are degenerate to avoid a crash.
+  //
+  // At the moment, we work under the assumption that they will be
+  // "clustered" later on, so we just keep the 1st one and discard the
+  // others
+  unsigned int offset=0;
+  for (int is=1;is<nsites;is++){
+    if (sites[is].coord.y==sites[is-1].coord.y && sites[is].coord.x==sites[is-1].coord.x){
+      offset++;
+    } else if (offset>0){
+      sites[is-offset] = sites[is];
+    }
+  }
+
+  if (offset>0){
+    nsites-=offset;
+    _warning_degeneracy.warn("VoronoiDiagramGenerator: two (or more) particles are degenerate in rapidity and azimuth, Voronoi cell assigned to the first of each set of degenerate particles.");
+  }
+
+  siteidx = 0;
+  geominit();
+  double temp = 0;
+  if(minX > maxX){
+    temp = minX;
+    minX = maxX;
+    maxX = temp;
+  }
+  if(minY > maxY){
+    temp = minY;
+    minY = maxY;
+    maxY = temp;
+  }
+  borderMinX = minX;
+  borderMinY = minY;
+  borderMaxX = maxX;
+  borderMaxY = maxY;
+	
+  siteidx = 0;
+  voronoi();
+
+  return true;
+}
+
+bool VoronoiDiagramGenerator::ELinitialize(){
+  int i;
+  freeinit(&hfl, sizeof(Halfedge));
+  ELhashsize = 2 * sqrt_nsites;
+  //ELhash = (Halfedge **) myalloc ( sizeof *ELhash * ELhashsize);
+  ELhash = (Halfedge **) myalloc ( sizeof(Halfedge*)*ELhashsize);
+  
+  if(ELhash == 0)
+    return false;
+  
+  for(i=0; i<ELhashsize; i +=1) ELhash[i] = (Halfedge *)NULL;
+  ELleftend = HEcreate((Edge*) NULL, 0);
+  ELrightend = HEcreate((Edge*) NULL, 0);
+  ELleftend->ELleft = (Halfedge*) NULL;
+  ELleftend->ELright = ELrightend;
+  ELrightend->ELleft = ELleftend;
+  ELrightend->ELright = (Halfedge*) NULL;
+  ELhash[0] = ELleftend;
+  ELhash[ELhashsize-1] = ELrightend;
+
+  return true;
+}
+
+
+Halfedge* VoronoiDiagramGenerator::HEcreate(Edge *e,int pm){
+  Halfedge *answer;
+  answer = (Halfedge*) getfree(&hfl);
+  answer->ELedge = e;
+  answer->ELpm = pm;
+  answer->PQnext = (Halfedge*) NULL;
+  answer->vertex = (Site*) NULL;
+  answer->ELrefcnt = 0;
+  return answer;
+}
+
+
+void VoronoiDiagramGenerator::ELinsert(Halfedge *lb, Halfedge *newHe)
+{
+  newHe->ELleft = lb;
+  newHe->ELright = lb->ELright;
+  (lb->ELright)->ELleft = newHe;
+  lb->ELright = newHe;
+}
+
+
+/* Get entry from hash table, pruning any deleted nodes */
+Halfedge* VoronoiDiagramGenerator::ELgethash(int b){
+  Halfedge *he;
+	
+  if ((b<0) || (b>=ELhashsize)) 
+    return (Halfedge *) NULL;
+
+  he = ELhash[b]; 
+  if ((he==(Halfedge*) NULL) || (he->ELedge!=(Edge*) DELETED)) 
+    return he;
+	
+  /* Hash table points to deleted half edge.  Patch as necessary. */
+  ELhash[b] = (Halfedge*) NULL;
+  if ((he->ELrefcnt -= 1) == 0) 
+    makefree((Freenode*)he, &hfl);
+  return (Halfedge*) NULL;
+}	
+
+Halfedge * VoronoiDiagramGenerator::ELleftbnd(VPoint *p){
+  int i, bucket;
+  Halfedge *he;
+	
+  /* Use hash table to get close to desired halfedge */
+  // use the hash function to find the place in the hash map that this
+  // HalfEdge should be
+  // Gregory Soyez: the original code was 
+  //
+  //   bucket = (int)((p->x - xmin)/deltax * ELhashsize);	
+  //   // make sure that the bucket position in within the range of the
+  //   //hash array
+  //   if (bucket<0) bucket =0;
+  //   if (bucket>=ELhashsize) bucket = ELhashsize - 1;
+  //
+  // but this runs the risk of having a overflow which would 
+  // cause bucket to be truncated at 0 instead of ELhashsize - 1
+  // (or vice-versa)
+  // We fix this by performing the test immediately on the double
+  // We put in a extra bit of margin to be sure the conversion does
+  // not play dirty tricks on us
+
+  //const double &px = p->x;
+  if (p->x < xmin){ bucket=0;}
+  else if (p->x >= xmax){ bucket = ELhashsize - 1;}
+  else{
+    bucket= (int)((p->x - xmin)/deltax * ELhashsize);
+    if (bucket>=ELhashsize) bucket = ELhashsize - 1;  // the lower cut should be robust
+  }
+
+  he = ELgethash(bucket);
+
+  // if the HE isn't found, search backwards and forwards in the hash
+  // map for the first non-null entry
+  if (he == (Halfedge*) NULL){   
+    for(i=1;1;i++){	
+      if ((he=ELgethash(bucket-i)) != (Halfedge*) NULL) 
+	break;
+      if ((he=ELgethash(bucket+i)) != (Halfedge*) NULL) 
+	break;
+    };
+    totalsearch += i;
+  };
+  ntry += 1;
+  /* Now search linear list of halfedges for the correct one */
+  if ((he==ELleftend)  || (he != ELrightend && right_of(he,p))){
+    do{
+      he = he->ELright;
+    } while (he!=ELrightend && right_of(he,p));
+      // keep going right on the list until either the end is reached,
+      // or you find the 1st edge which the point
+      he = he->ELleft;	//isn't to the right of
+  } else 
+    // if the point is to the left of the HalfEdge, then search left
+    // for the HE just to the left of the point
+    do{
+      he = he->ELleft;
+    } while ((he!=ELleftend )&& (!right_of(he,p)));
+		
+  /* Update hash table and reference counts */
+  if ((bucket > 0) && (bucket <ELhashsize-1)){	
+    if(ELhash[bucket] != (Halfedge *) NULL){
+      ELhash[bucket]->ELrefcnt -= 1;
+    }
+    ELhash[bucket] = he;
+    ELhash[bucket]->ELrefcnt += 1;
+  };
+
+  return he;
+}
+
+
+/* This delete routine can't reclaim node, since pointers from hash
+   table may be present.   */
+void VoronoiDiagramGenerator::ELdelete(Halfedge *he){
+  (he->ELleft)->ELright = he->ELright;
+  (he->ELright)->ELleft = he->ELleft;
+  he->ELedge = (Edge*) DELETED;
+}
+
+
+Halfedge* VoronoiDiagramGenerator::ELright(Halfedge *he){
+  return he->ELright;
+}
+
+
+Halfedge* VoronoiDiagramGenerator::ELleft(Halfedge *he){
+  return he->ELleft;
+}
+
+
+Site * VoronoiDiagramGenerator::leftreg(Halfedge *he){
+  if (he->ELedge == (Edge*) NULL) 
+    return(bottomsite);
+  return (he->ELpm == le) 
+    ? he->ELedge->reg[le] 
+    : he->ELedge->reg[re];
+}
+
+Site * VoronoiDiagramGenerator::rightreg(Halfedge *he){
+  if (he->ELedge == (Edge*) NULL)
+    // if this halfedge has no edge, return the bottom site (whatever
+    // that is)
+    return bottomsite;
+  
+  // if the ELpm field is zero, return the site 0 that this edge
+  // bisects, otherwise return site number 1
+  return (he->ELpm == le)
+    ? he->ELedge->reg[re] 
+    : he->ELedge->reg[le];
+}
+
+void VoronoiDiagramGenerator::geominit(){
+  double sn;
+  
+  freeinit(&efl, sizeof(Edge));
+  nvertices = 0;
+  nedges = 0;
+  sn = (double)nsites+4;
+  sqrt_nsites = (int)sqrt(sn);
+  deltay = ymax - ymin;
+  deltax = xmax - xmin;
+}
+
+
+Edge * VoronoiDiagramGenerator::bisect(Site *s1, Site *s2){
+  double dx,dy,adx,ady;
+  Edge *newedge;	
+
+  newedge = (Edge*) getfree(&efl);
+	
+  newedge->reg[0] = s1; //store the sites that this edge is bisecting
+  newedge->reg[1] = s2;
+  ref(s1); 
+  ref(s2);
+
+  // to begin with, there are no endpoints on the bisector - it goes
+  // to infinity
+  newedge->ep[0] = (Site*) NULL;
+  newedge->ep[1] = (Site*) NULL;
+  
+  // get the difference in x dist between the sites
+  dx = s2->coord.x - s1->coord.x;
+  dy = s2->coord.y - s1->coord.y;
+
+  // make sure that the difference is positive
+  adx = dx>0 ? dx : -dx;
+  ady = dy>0 ? dy : -dy;
+
+  // get the slope of the line
+  newedge->c = (double)(s1->coord.x * dx + s1->coord.y * dy
+			+ (dx*dx + dy*dy)*0.5);
+
+  if (adx>ady){	
+    //set formula of line, with x fixed to 1
+    newedge->a = 1.0; newedge->b = dy/dx; newedge->c /= dx;
+  } else {	
+    //set formula of line, with y fixed to 1
+    newedge->b = 1.0; newedge->a = dx/dy; newedge->c /= dy;
+  }
+	
+  newedge->edgenbr = nedges;
+  nedges++;
+
+  return newedge;
+}
+
+
+// create a new site where the HalfEdges el1 and el2 intersect - note
+// that the VPoint in the argument list is not used, don't know why
+// it's there
+//
+// Gregory Soyez: removed the uinused point p
+Site* VoronoiDiagramGenerator::intersect(Halfedge *el1, Halfedge *el2
+					 /*, VPoint *p*/){
+  Edge *e1,*e2, *e;
+  Halfedge *el;
+  double d, xint, yint;
+  int right_of_site;
+  Site *v;
+	
+  e1 = el1->ELedge;
+  e2 = el2->ELedge;
+  if ((e1==(Edge*)NULL) || (e2==(Edge*)NULL)) 
+    return ((Site*) NULL);
+
+  // if the two edges bisect the same parent, return null
+  if (e1->reg[1] == e2->reg[1]) 
+    return (Site*) NULL;
+
+  // Gregory Soyez:
+  //	
+  // if the 2 parents are too close, the intersection is going to be
+  // computed from the "long edges" of the triangle which could causes
+  // large rounding errors. In this case, use the bisector of the 2
+  // parents to find the interaction point
+  // 
+  // The following replaces 
+  //   d = e1->a * e2->b - e1->b * e2->a;
+  //   if (-1.0e-10<d && d<1.0e-10) 
+  //     return (Site*) NULL;
+  //   	
+  //   xint = (e1->c*e2->b - e2->c*e1->b)/d;
+  //   yint = (e2->c*e1->a - e1->c*e2->a)/d;
+
+  double dx = e2->reg[1]->coord.x - e1->reg[1]->coord.x;
+  double dy = e2->reg[1]->coord.y - e1->reg[1]->coord.y;
+  double dxref = e1->reg[1]->coord.x - e1->reg[0]->coord.x;
+  double dyref = e1->reg[1]->coord.y - e1->reg[0]->coord.y;
+
+  if (dx*dx + dy*dy < 1e-14*(dxref*dxref+dyref*dyref)){
+    // make sure that the difference is positive
+    double adx = dx>0 ? dx : -dx;
+    double ady = dy>0 ? dy : -dy;
+    
+    // get the slope of the line
+    double a,b;
+    double c = (double)(e1->reg[1]->coord.x * dx + e1->reg[1]->coord.y * dy
+			+ (dx*dx + dy*dy)*0.5);
+    
+    if (adx>ady){
+      a = 1.0; b = dy/dx; c /= dx;
+    } else {
+      b = 1.0; a = dx/dy; c /= dy;
+    }
+
+    d = e1->a * b - e1->b * a;
+    if (-1.0e-10<d && d<1.0e-10) {
+      return (Site*) NULL;
+    }
+	
+    xint = (e1->c*b - c*e1->b)/d;
+    yint = (c*e1->a - e1->c*a)/d;
+    
+  } else {	
+    d = e1->a * e2->b - e1->b * e2->a;
+    if (-1.0e-10<d && d<1.0e-10) {
+      return (Site*) NULL;
+    }
+	
+    xint = (e1->c*e2->b - e2->c*e1->b)/d;
+    yint = (e2->c*e1->a - e1->c*e2->a)/d;
+  }
+  // end of Gregory Soyez's modifications
+
+  volatile double local_y1 = e1->reg[1]->coord.y;
+  volatile double local_y2 = e2->reg[1]->coord.y;
+	
+  if( (local_y1 < local_y2) ||
+      ((local_y1 == local_y2) &&
+       (e1->reg[1]->coord.x <  e2->reg[1]->coord.x)) ){	
+    el = el1; 
+    e = e1;
+  } else {	
+    el = el2; 
+    e = e2;
+  }
+	
+  right_of_site = xint >= e->reg[1]->coord.x;
+  if ((right_of_site && el->ELpm == le) || (!right_of_site && el->ELpm == re)) 
+    return (Site*) NULL;
+	
+  // create a new site at the point of intersection - this is a new
+  // vector event waiting to happen
+  v = (Site*) getfree(&sfl);
+  v->refcnt = 0;
+  v->coord.x = xint;
+  v->coord.y = yint;
+  return v;
+}
+
+//HERE
+
+/* returns 1 if p is to right of halfedge e */
+int VoronoiDiagramGenerator::right_of(Halfedge *el,VPoint *p)
+{
+  Edge *e;
+  Site *topsite;
+  int right_of_site, above, fast;
+  double dxp, dyp, dxs, t1, t2, t3, yl;
+	
+  e = el->ELedge;
+  topsite = e->reg[1];
+  right_of_site = p->x > topsite->coord.x;
+  if(right_of_site && el->ELpm == le) return(1);
+  if(!right_of_site && el->ELpm == re) return (0);
+	
+  if (e->a == 1.0)
+    {	dyp = p->y - topsite->coord.y;
+    dxp = p->x - topsite->coord.x;
+    fast = 0;
+    if ((!right_of_site & (e->b<0.0)) | (right_of_site & (e->b>=0.0)) )
+      {	above = dyp>= e->b*dxp;	
+      fast = above;
+      }
+    else 
+      {	above = p->x + p->y*e->b > e-> c;
+      if(e->b<0.0) above = !above;
+      if (!above) fast = 1;
+      };
+    if (!fast)
+      {	dxs = topsite->coord.x - (e->reg[0])->coord.x;
+      above = e->b * (dxp*dxp - dyp*dyp) <
+	dxs*dyp*(1.0+2.0*dxp/dxs + e->b*e->b);
+      if(e->b<0.0) above = !above;
+      };
+    }
+  else  /*e->b==1.0 */
+    {	yl = e->c - e->a*p->x;
+    t1 = p->y - yl;
+    t2 = p->x - topsite->coord.x;
+    t3 = yl - topsite->coord.y;
+    above = t1*t1 > t2*t2 + t3*t3;
+    };
+  return (el->ELpm==le ? above : !above);
+}
+
+
+void VoronoiDiagramGenerator::endpoint(Edge *e,int lr,Site * s)
+{
+  e->ep[lr] = s;
+  ref(s);
+  if(e->ep[re-lr]== (Site *) NULL) 
+    return;
+
+  clip_line(e);
+
+  deref(e->reg[le]);
+  deref(e->reg[re]);
+  makefree((Freenode*)e, &efl);
+}
+
+
+double VoronoiDiagramGenerator::dist(Site *s,Site *t)
+{
+  double dx,dy;
+  dx = s->coord.x - t->coord.x;
+  dy = s->coord.y - t->coord.y;
+  return (double)(sqrt(dx*dx + dy*dy));
+}
+
+
+void VoronoiDiagramGenerator::makevertex(Site *v)
+{
+  v->sitenbr = nvertices;
+  nvertices += 1;
+  //GS unused plot: out_vertex(v);
+}
+
+
+void VoronoiDiagramGenerator::deref(Site *v)
+{
+  v->refcnt -= 1;
+  if (v->refcnt == 0 ) 
+    makefree((Freenode*)v, &sfl);
+}
+
+void VoronoiDiagramGenerator::ref(Site *v)
+{
+  v->refcnt += 1;
+}
+
+//push the HalfEdge into the ordered linked list of vertices
+void VoronoiDiagramGenerator::PQinsert(Halfedge *he,Site * v, double offset)
+{
+  Halfedge *last, *next;
+	
+  he->vertex = v;
+  ref(v);
+  he->ystar = (double)(v->coord.y + offset);
+  last = &PQhash[PQbucket(he)];
+  while ((next = last->PQnext) != (Halfedge *) NULL &&
+	 (he->ystar  > next->ystar  ||
+	  (he->ystar == next->ystar && v->coord.x > next->vertex->coord.x)))
+    {	
+      last = next;
+    };
+  he->PQnext = last->PQnext; 
+  last->PQnext = he;
+  PQcount += 1;
+}
+
+//remove the HalfEdge from the list of vertices 
+void VoronoiDiagramGenerator::PQdelete(Halfedge *he)
+{
+  Halfedge *last;
+	
+  if(he->vertex != (Site *) NULL)
+    {	
+      last = &PQhash[PQbucket(he)];
+      while (last->PQnext != he) 
+	last = last->PQnext;
+
+      last->PQnext = he->PQnext;
+      PQcount -= 1;
+      deref(he->vertex);
+      he->vertex = (Site *) NULL;
+    };
+}
+
+int VoronoiDiagramGenerator::PQbucket(Halfedge *he)
+{
+  // Gregory Soyez: the original code was 
+  //
+  //   bucket = (int)((he->ystar - ymin)/deltay * PQhashsize);
+  //   if (bucket<0) bucket = 0;
+  //   if (bucket>=PQhashsize) bucket = PQhashsize-1 ;
+  //   if (bucket < PQmin) PQmin = bucket;
+  //   return(bucket);
+  //
+  // but this runs the risk of having a overflow which would 
+  // cause bucket to be truncated at 0 instead of PQhashsize-1
+  // (or vice-versa)
+  // We fix this by performing the test immediately on the double
+  // We put in a extra bit of margin to be sure the conversion does
+  // not play dirty tricks on us
+
+  int bucket;
+	
+  double hey = he->ystar;
+  if (hey < ymin){ bucket = 0;}
+  else if (hey >= ymax){ bucket = PQhashsize-1;}
+  else {
+    bucket = (int)((hey - ymin)/deltay * PQhashsize);
+    if (bucket>=PQhashsize) bucket = PQhashsize-1 ;
+  }
+
+  if (bucket < PQmin) PQmin = bucket;
+  return(bucket);
+}
+
+
+
+int VoronoiDiagramGenerator::PQempty()
+{
+  return(PQcount==0);
+}
+
+
+VPoint VoronoiDiagramGenerator::PQ_min()
+{
+  VPoint answer;
+	
+  while(PQhash[PQmin].PQnext == (Halfedge *)NULL) {PQmin += 1;};
+  answer.x = PQhash[PQmin].PQnext->vertex->coord.x;
+  answer.y = PQhash[PQmin].PQnext->ystar;
+  return (answer);
+}
+
+Halfedge * VoronoiDiagramGenerator::PQextractmin()
+{
+  Halfedge *curr;
+	
+  curr = PQhash[PQmin].PQnext;
+  PQhash[PQmin].PQnext = curr->PQnext;
+  PQcount -= 1;
+  return(curr);
+}
+
+
+bool VoronoiDiagramGenerator::PQinitialize()
+{
+  int i; 
+	
+  PQcount = 0;
+  PQmin = 0;
+  PQhashsize = 4 * sqrt_nsites;
+  //PQhash = (Halfedge *) myalloc(PQhashsize * sizeof *PQhash);
+  PQhash = (Halfedge *) myalloc(PQhashsize * sizeof(Halfedge));
+
+  if(PQhash == 0)
+    return false;
+
+  for(i=0; i<PQhashsize; i+=1) PQhash[i].PQnext = (Halfedge *)NULL;
+
+  return true;
+}
+
+
+void VoronoiDiagramGenerator::freeinit(Freelist *fl,int size)
+{
+  fl->head = (Freenode *) NULL;
+  fl->nodesize = size;
+}
+
+char * VoronoiDiagramGenerator::getfree(Freelist *fl)
+{
+  int i; 
+  Freenode *t;
+
+  if(fl->head == (Freenode *) NULL)
+    {	
+      t =  (Freenode *) myalloc(sqrt_nsites * fl->nodesize);
+
+      if(t == 0)
+	return 0;
+		
+      currentMemoryBlock->next = new FreeNodeArrayList;
+      currentMemoryBlock = currentMemoryBlock->next;
+      currentMemoryBlock->memory = t;
+      currentMemoryBlock->next = 0;
+
+      for(i=0; i<sqrt_nsites; i+=1) 	
+	makefree((Freenode *)((char *)t+i*fl->nodesize), fl);		
+    };
+  t = fl->head;
+  fl->head = (fl->head)->nextfree;
+  return((char *)t);
+}
+
+
+
+void VoronoiDiagramGenerator::makefree(Freenode *curr,Freelist *fl)
+{
+  curr->nextfree = fl->head;
+  fl->head = curr;
+}
+
+void VoronoiDiagramGenerator::cleanup()
+{
+  if(sites != NULL){
+    free(sites);
+    sites = 0;
+  }
+
+  FreeNodeArrayList* current=NULL, *prev=NULL;
+
+  current = prev = allMemoryList;
+
+  while(current->next!=NULL){
+    prev = current;
+    current = current->next;
+    free(prev->memory);
+    delete prev;
+    prev = NULL;
+  }
+
+  if(current!=NULL){
+    if (current->memory!=NULL){
+      free(current->memory);
+    }
+    delete current;
+  }
+
+  allMemoryList = new FreeNodeArrayList;
+  allMemoryList->next = NULL;
+  allMemoryList->memory = NULL;
+  currentMemoryBlock = allMemoryList;
+
+  if (ELhash!=NULL)
+    free(ELhash);
+
+  if (PQhash!=NULL)
+    free(PQhash);
+}
+
+void VoronoiDiagramGenerator::cleanupEdges()
+{
+  GraphEdge* geCurrent = NULL, *gePrev = NULL;
+  geCurrent = gePrev = allEdges;
+
+  while(geCurrent!=NULL){
+    gePrev = geCurrent;
+    geCurrent = geCurrent->next;
+    delete gePrev;
+  }
+
+  allEdges = 0;
+
+}
+
+void VoronoiDiagramGenerator::pushGraphEdge(double x1, double y1, double x2, double y2,
+					    Site *s1, Site *s2)
+{
+  GraphEdge* newEdge = new GraphEdge;
+  newEdge->next = allEdges;
+  allEdges = newEdge;
+  newEdge->x1 = x1;
+  newEdge->y1 = y1;
+  newEdge->x2 = x2;
+  newEdge->y2 = y2;
+
+  newEdge->point1 = s1->sitenbr;
+  newEdge->point2 = s2->sitenbr;
+}
+
+
+char * VoronoiDiagramGenerator::myalloc(unsigned n)
+{
+  char *t=0;	
+  t=(char*)malloc(n);
+  total_alloc += n;
+  return(t);
+}
+
+
+// unused plot functions
+//
+// /* for those who don't have Cherry's plot */
+// /* #include <plot.h> */
+// void VoronoiDiagramGenerator::openpl(){}
+// void VoronoiDiagramGenerator::circle(double x, double y, double radius){}
+// void VoronoiDiagramGenerator::range(double minX, double minY, double maxX, double maxY){}
+// 
+// 
+// 
+// void VoronoiDiagramGenerator::out_bisector(Edge *e)
+// {
+// 	
+// 
+// }
+// 
+// 
+// void VoronoiDiagramGenerator::out_ep(Edge *e)
+// {
+// 	
+// 	
+// }
+// 
+// void VoronoiDiagramGenerator::out_vertex(Site *v)
+// {
+// 	
+// }
+// 
+// 
+// void VoronoiDiagramGenerator::out_site(Site *s)
+// {
+//   // Gregory Soyez: 
+//   //   plot was always 0 so the expression below was always false
+//   //   and even if it was not, 'circle' does nothing!
+//   //
+//   // if(!triangulate & plot & !debug)
+//   //   circle (s->coord.x, s->coord.y, cradius);
+// 	
+// }
+// 
+// 
+// void VoronoiDiagramGenerator::out_triple(Site *s1, Site *s2,Site * s3)
+// {
+// 	
+// }
+
+
+
+void VoronoiDiagramGenerator::plotinit()
+{
+  double dx,dy,d;
+	
+  dy = ymax - ymin;
+  dx = xmax - xmin;
+  d = (double)(( dx > dy ? dx : dy) * 1.1);
+  pxmin = (double)(xmin - (d-dx)/2.0);
+  pxmax = (double)(xmax + (d-dx)/2.0);
+  pymin = (double)(ymin - (d-dy)/2.0);
+  pymax = (double)(ymax + (d-dy)/2.0);
+  cradius = (double)((pxmax - pxmin)/350.0);
+  //GS unused: openpl();
+  //GS unused: range(pxmin, pymin, pxmax, pymax);
+}
+
+
+void VoronoiDiagramGenerator::clip_line(Edge *e)
+{
+  Site *s1, *s2;
+  double x1=0,x2=0,y1=0,y2=0; //, temp = 0;
+
+  x1 = e->reg[0]->coord.x;
+  x2 = e->reg[1]->coord.x;
+  y1 = e->reg[0]->coord.y;
+  y2 = e->reg[1]->coord.y;
+
+  //if the distance between the two points this line was created from is less than 
+  //the square root of 2, then ignore it
+  //TODO improve/remove
+  //if(sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1))) < minDistanceBetweenSites)
+  //  {
+  //    return;
+  //  }
+  pxmin = borderMinX;
+  pxmax = borderMaxX;
+  pymin = borderMinY;
+  pymax = borderMaxY;
+
+  if(e->a == 1.0 && e ->b >= 0.0)
+    {	
+      s1 = e->ep[1];
+      s2 = e->ep[0];
+    }
+  else 
+    {
+      s1 = e->ep[0];
+      s2 = e->ep[1];
+    };
+	
+  if(e->a == 1.0)
+    {
+      y1 = pymin;
+      if (s1!=(Site *)NULL && s1->coord.y > pymin)
+	{
+	  y1 = s1->coord.y;
+	}
+      if(y1>pymax) 
+	{
+	  //	printf("\nClipped (1) y1 = %f to %f",y1,pymax);
+	  y1 = pymax;
+	  //return;
+	}
+      x1 = e->c - e->b * y1;
+      y2 = pymax;
+      if (s2!=(Site *)NULL && s2->coord.y < pymax) 
+	y2 = s2->coord.y;
+
+      if(y2<pymin) 
+	{
+	  //printf("\nClipped (2) y2 = %f to %f",y2,pymin);
+	  y2 = pymin;
+	  //return;
+	}
+      x2 = (e->c) - (e->b) * y2;
+      if (((x1> pxmax) & (x2>pxmax)) | ((x1<pxmin)&(x2<pxmin))) 
+	{
+	  //printf("\nClipLine jumping out(3), x1 = %f, pxmin = %f, pxmax = %f",x1,pxmin,pxmax);
+	  return;
+	}
+      if(x1> pxmax)
+	{	x1 = pxmax; y1 = (e->c - x1)/e->b;};
+      if(x1<pxmin)
+	{	x1 = pxmin; y1 = (e->c - x1)/e->b;};
+      if(x2>pxmax)
+	{	x2 = pxmax; y2 = (e->c - x2)/e->b;};
+      if(x2<pxmin)
+	{	x2 = pxmin; y2 = (e->c - x2)/e->b;};
+    }
+  else
+    {
+      x1 = pxmin;
+      if (s1!=(Site *)NULL && s1->coord.x > pxmin) 
+	x1 = s1->coord.x;
+      if(x1>pxmax) 
+	{
+	  //printf("\nClipped (3) x1 = %f to %f",x1,pxmin);
+	  //return;
+	  x1 = pxmax;
+	}
+      y1 = e->c - e->a * x1;
+      x2 = pxmax;
+      if (s2!=(Site *)NULL && s2->coord.x < pxmax) 
+	x2 = s2->coord.x;
+      if(x2<pxmin) 
+	{
+	  //printf("\nClipped (4) x2 = %f to %f",x2,pxmin);
+	  //return;
+	  x2 = pxmin;
+	}
+      y2 = e->c - e->a * x2;
+      if (((y1> pymax) & (y2>pymax)) | ((y1<pymin)&(y2<pymin))) 
+	{
+	  //printf("\nClipLine jumping out(6), y1 = %f, pymin = %f, pymax = %f",y2,pymin,pymax);
+	  return;
+	}
+      if(y1> pymax)
+	{	y1 = pymax; x1 = (e->c - y1)/e->a;};
+      if(y1<pymin)
+	{	y1 = pymin; x1 = (e->c - y1)/e->a;};
+      if(y2>pymax)
+	{	y2 = pymax; x2 = (e->c - y2)/e->a;};
+      if(y2<pymin)
+	{	y2 = pymin; x2 = (e->c - y2)/e->a;};
+    };
+	
+  //printf("\nPushing line (%f,%f,%f,%f)",x1,y1,x2,y2);
+  //fprintf(stdout, "Line with vertices (%f,%f) and (%f,%f)\n", 
+  //	e->reg[0]->coord.x, e->reg[1]->coord.x, e->reg[0]->coord.y, e->reg[1]->coord.y);
+  pushGraphEdge(x1,y1,x2,y2,e->reg[0],e->reg[1]);
+}
+
+
+/* implicit parameters: nsites, sqrt_nsites, xmin, xmax, ymin, ymax,
+   deltax, deltay (can all be estimates).
+   Performance suffers if they are wrong; better to make nsites,
+   deltax, and deltay too big than too small.  (?) */
+
+bool VoronoiDiagramGenerator::voronoi()
+{
+  Site *newsite, *bot, *top, *temp, *p;
+  Site *v;
+  VPoint newintstar;
+  int pm;
+  Halfedge *lbnd, *rbnd, *llbnd, *rrbnd, *bisector;
+  Edge *e;
+	
+  PQinitialize();
+  bottomsite = nextone();
+  //GS unused plot: out_site(bottomsite);
+  bool retval = ELinitialize();
+
+  if(!retval)
+    return false;
+	
+  newsite = nextone();
+  while(1)
+    {
+
+      if(!PQempty()) 
+	newintstar = PQ_min();
+		
+      //if the lowest site has a smaller y value than the lowest vector intersection, process the site
+      //otherwise process the vector intersection		
+      if (newsite != (Site *)NULL  && (PQempty() || newsite->coord.y < newintstar.y
+				       || (newsite->coord.y == newintstar.y && newsite->coord.x < newintstar.x)))
+	{/* new site is smallest - this is a site event*/
+	  //GS unused plot: out_site(newsite);						//output the site
+	  lbnd = ELleftbnd(&(newsite->coord));				//get the first HalfEdge to the LEFT of the new site
+	  rbnd = ELright(lbnd);						//get the first HalfEdge to the RIGHT of the new site
+	  bot = rightreg(lbnd);						//if this halfedge has no edge, , bot = bottom site (whatever that is)
+	  e = bisect(bot, newsite);					//create a new edge that bisects 
+	  bisector = HEcreate(e, le);					//create a new HalfEdge, setting its ELpm field to 0			
+	  ELinsert(lbnd, bisector);					//insert this new bisector edge between the left and right vectors in a linked list	
+	    
+	  if ((p = intersect(lbnd, bisector)) != (Site *) NULL) 	//if the new bisector intersects with the left edge, remove the left edge's vertex, and put in the new one
+	    {	
+	      PQdelete(lbnd);
+	      PQinsert(lbnd, p, dist(p,newsite));
+	    };
+	  lbnd = bisector;						
+	  bisector = HEcreate(e, re);					//create a new HalfEdge, setting its ELpm field to 1
+	  ELinsert(lbnd, bisector);					//insert the new HE to the right of the original bisector earlier in the IF stmt
+	    
+	  if ((p = intersect(bisector, rbnd)) != (Site *) NULL)	//if this new bisector intersects with the
+	    {	
+	      PQinsert(bisector, p, dist(p,newsite));			//push the HE into the ordered linked list of vertices
+	    };
+	  newsite = nextone();	
+	}
+      else if (!PQempty()) /* intersection is smallest - this is a vector event */			
+	{	
+	  lbnd = PQextractmin();						//pop the HalfEdge with the lowest vector off the ordered list of vectors				
+	  llbnd = ELleft(lbnd);						//get the HalfEdge to the left of the above HE
+	  rbnd = ELright(lbnd);						//get the HalfEdge to the right of the above HE
+	  rrbnd = ELright(rbnd);						//get the HalfEdge to the right of the HE to the right of the lowest HE 
+	  bot = leftreg(lbnd);						//get the Site to the left of the left HE which it bisects
+	  top = rightreg(rbnd);						//get the Site to the right of the right HE which it bisects
+	    
+	  //GS unused plot: out_triple(bot, top, rightreg(lbnd));		//output the triple of sites, stating that a circle goes through them
+	    
+	  v = lbnd->vertex;						//get the vertex that caused this event
+	  makevertex(v);							//set the vertex number - couldn't do this earlier since we didn't know when it would be processed
+	  endpoint(lbnd->ELedge,lbnd->ELpm,v);	//set the endpoint of the left HalfEdge to be this vector
+	  endpoint(rbnd->ELedge,rbnd->ELpm,v);	//set the endpoint of the right HalfEdge to be this vector
+	  ELdelete(lbnd);							//mark the lowest HE for deletion - can't delete yet because there might be pointers to it in Hash Map	
+	  PQdelete(rbnd);							//remove all vertex events to do with the  right HE
+	  ELdelete(rbnd);							//mark the right HE for deletion - can't delete yet because there might be pointers to it in Hash Map	
+	  pm = le;								//set the pm variable to zero
+	    
+	  if (bot->coord.y > top->coord.y)		//if the site to the left of the event is higher than the Site
+	    {										//to the right of it, then swap them and set the 'pm' variable to 1
+	      temp = bot; 
+	      bot = top; 
+	      top = temp; 
+	      pm = re;
+	    }
+	  e = bisect(bot, top);					//create an Edge (or line) that is between the two Sites. This creates
+	  //the formula of the line, and assigns a line number to it
+	  bisector = HEcreate(e, pm);				//create a HE from the Edge 'e', and make it point to that edge with its ELedge field
+	  ELinsert(llbnd, bisector);				//insert the new bisector to the right of the left HE
+	  endpoint(e, re-pm, v);					//set one endpoint to the new edge to be the vector point 'v'.
+	  //If the site to the left of this bisector is higher than the right
+	  //Site, then this endpoint is put in position 0; otherwise in pos 1
+	  deref(v);								//delete the vector 'v'
+	    
+	  //if left HE and the new bisector don't intersect, then delete the left HE, and reinsert it 
+	  if((p = intersect(llbnd, bisector)) != (Site *) NULL)
+	    {	
+	      PQdelete(llbnd);
+	      PQinsert(llbnd, p, dist(p,bot));
+	    };
+	    
+	  //if right HE and the new bisector don't intersect, then reinsert it 
+	  if ((p = intersect(bisector, rrbnd)) != (Site *) NULL)
+	    {	
+	      PQinsert(bisector, p, dist(p,bot));
+	    };
+	}
+      else break;
+    };
+
+	
+
+
+  for(lbnd=ELright(ELleftend); lbnd != ELrightend; lbnd=ELright(lbnd))
+    {	
+      e = lbnd->ELedge;
+
+      clip_line(e);
+    };
+
+  //cleanup();
+
+  return true;
+	
+}
+
+
+int scomp(const void *p1,const void *p2)
+{
+  VPoint *s1 = (VPoint*)p1, *s2=(VPoint*)p2;
+  if(s1->y < s2->y) return(-1);
+  if(s1->y > s2->y) return(1);
+  if(s1->x < s2->x) return(-1);
+  if(s1->x > s2->x) return(1);
+  return(0);
+}
+
+/* return a single in-storage site */
+Site * VoronoiDiagramGenerator::nextone()
+{
+  Site *s;
+  if(siteidx < nsites)
+    {	
+      s = &sites[siteidx];
+      siteidx += 1;
+      return(s);
+    }
+  else	
+    return( (Site *)NULL);
+}
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/WrappedStructure.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/WrappedStructure.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/WrappedStructure.hh	(revision 5)
@@ -0,0 +1,285 @@
+//STARTHEADER
+// $Id: WrappedStructure.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_WRAPPED_STRUCTURE_HH__
+#define __FASTJET_WRAPPED_STRUCTURE_HH__
+
+#include "fastjet/PseudoJetStructureBase.hh"
+#include "fastjet/Error.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+/// @ingroup extra_info
+/// \class WrappedStructure
+///
+/// This wraps a (shared) pointer to an underlying structure
+///
+/// The typical use-case is when a PseusoJet needs to share its
+/// structure with another PseudoJet but also include extra
+/// information in its structure. For the memory management to be
+/// handled properly, it should hold a shared pointer to the shared
+/// structure. This is what this class ensures. Deriving a structure
+/// from this class would then allow for the implementation of the
+/// extra features.
+///
+class WrappedStructure : public PseudoJetStructureBase{
+public:
+  /// default ctor
+  /// the argument is the structure we need to wrap
+  WrappedStructure(const SharedPtr<PseudoJetStructureBase> & to_be_shared)
+    : _structure(to_be_shared){
+    if (!_structure())
+      throw Error("Trying to construct a wrapped structure around an empty (NULL) structure");
+  }
+
+  /// default (virtual) dtor
+  virtual ~WrappedStructure(){}
+
+  /// description
+  virtual std::string description() const{ 
+    return "PseudoJet wrapping the structure ("+_structure->description()+")"; 
+  }
+
+  //-------------------------------------------------------------
+  /// @name Direct access to the associated ClusterSequence object.
+  ///
+  /// Get access to the associated ClusterSequence (if any)
+  //\{
+  //-------------------------------------------------------------
+  /// returns true if there is an associated ClusterSequence
+  virtual bool has_associated_cluster_sequence() const {
+    return _structure->has_associated_cluster_sequence();
+  }
+
+  /// get a (const) pointer to the parent ClusterSequence (NULL if
+  /// inexistent)
+  virtual const ClusterSequence* associated_cluster_sequence() const{
+    return _structure->associated_cluster_sequence();
+  }
+  
+  /// returns true if this PseudoJet has an associated and still
+  /// valid ClusterSequence.
+  virtual bool has_valid_cluster_sequence() const {
+    return _structure->has_valid_cluster_sequence();
+  }
+
+  /// if the jet has a valid associated cluster sequence then return a
+  /// pointer to it; otherwise throw an error
+  virtual const ClusterSequence * validated_cs() const{
+    return _structure->validated_cs();
+  }
+
+  /// if the jet has valid area information then return a pointer to
+  /// the associated ClusterSequenceAreaBase object; otherwise throw an error
+  virtual const ClusterSequenceAreaBase * validated_csab() const{
+    return _structure->validated_csab();
+  }
+
+  //\}
+
+  //-------------------------------------------------------------
+  /// @name Methods for access to information about jet structure
+  ///
+  /// These allow access to jet constituents, and other jet
+  /// subtructure information. They only work if the jet is associated
+  /// with a ClusterSequence.
+  //-------------------------------------------------------------
+  //\{
+
+  /// check if it has been recombined with another PseudoJet in which
+  /// case, return its partner through the argument. Otherwise,
+  /// 'partner' is set to 0.
+  ///
+  /// By default, throws an Error
+  virtual bool has_partner(const PseudoJet &reference, PseudoJet &partner) const{
+    return _structure->has_partner(reference, partner);
+  }
+
+  /// check if it has been recombined with another PseudoJet in which
+  /// case, return its child through the argument. Otherwise, 'child'
+  /// is set to 0.
+  /// 
+  /// By default, throws an Error
+  virtual bool has_child(const PseudoJet &reference, PseudoJet &child) const{
+    return _structure->has_child(reference, child);
+  }
+
+  /// check if it is the product of a recombination, in which case
+  /// return the 2 parents through the 'parent1' and 'parent2'
+  /// arguments. Otherwise, set these to 0.
+  ///
+  /// By default, throws an Error
+  virtual bool has_parents(const PseudoJet &reference, PseudoJet &parent1, PseudoJet &parent2) const{
+    return _structure->has_parents(reference, parent1, parent2);
+  }
+
+  /// check if the reference PseudoJet is contained the second one
+  /// passed as argument.
+  ///
+  /// By default, throws an Error
+  virtual bool object_in_jet(const PseudoJet &reference, const PseudoJet &jet) const{
+    return _structure->object_in_jet(reference, jet);
+  }
+
+
+  /// return true if the structure supports constituents. 
+  ///
+  /// false by default
+  virtual bool has_constituents() const {
+    return _structure->has_constituents();
+  }
+
+  /// retrieve the constituents. 
+  ///
+  /// By default, throws an Error
+  virtual std::vector<PseudoJet> constituents(const PseudoJet &reference) const{
+    return _structure->constituents(reference);
+  }
+
+  /// return true if the structure supports exclusive_subjets. 
+  virtual bool has_exclusive_subjets() const {
+    return _structure->has_exclusive_subjets();
+  }
+
+  /// return a vector of all subjets of the current jet (in the sense
+  /// of the exclusive algorithm) that would be obtained when running
+  /// the algorithm with the given dcut. 
+  ///
+  /// Time taken is O(m ln m), where m is the number of subjets that
+  /// are found. If m gets to be of order of the total number of
+  /// constituents in the jet, this could be substantially slower than
+  /// just getting that list of constituents.
+  ///
+  /// By default, throws an Error
+  virtual std::vector<PseudoJet> exclusive_subjets(const PseudoJet &reference, const double & dcut) const{
+    return _structure->exclusive_subjets(reference, dcut);
+  }
+
+  /// return the size of exclusive_subjets(...); still n ln n with same
+  /// coefficient, but marginally more efficient than manually taking
+  /// exclusive_subjets.size()
+  ///
+  /// By default, throws an Error
+  virtual int n_exclusive_subjets(const PseudoJet &reference, const double & dcut) const{
+    return _structure->n_exclusive_subjets(reference, dcut);
+  }
+
+  /// return the list of subjets obtained by unclustering the supplied
+  /// jet down to n subjets (or all constituents if there are fewer
+  /// than n).
+  ///
+  /// By default, throws an Error
+  virtual std::vector<PseudoJet> exclusive_subjets_up_to (const PseudoJet &reference, int nsub) const{
+    return _structure->exclusive_subjets_up_to (reference, nsub);
+  }
+
+  /// return the dij that was present in the merging nsub+1 -> nsub 
+  /// subjets inside this jet.
+  ///
+  /// By default, throws an Error
+  virtual double exclusive_subdmerge(const PseudoJet &reference, int nsub) const{
+    return _structure->exclusive_subdmerge(reference, nsub);
+  }
+
+  /// return the maximum dij that occurred in the whole event at the
+  /// stage that the nsub+1 -> nsub merge of subjets occurred inside 
+  /// this jet.
+  ///
+  /// By default, throws an Error
+  virtual double exclusive_subdmerge_max(const PseudoJet &reference, int nsub) const{
+    return _structure->exclusive_subdmerge_max(reference, nsub);
+  }
+
+
+  //-------------------------------------------------------------------
+  // information related to the pieces of the jet
+  //-------------------------------------------------------------------
+  /// return true if the structure supports pieces. 
+  ///
+  /// false by default
+  virtual bool has_pieces(const PseudoJet &reference) const {
+    return _structure->has_pieces(reference);
+  }
+
+  /// retrieve the pieces building the jet. 
+  ///
+  /// By default, throws an Error
+  virtual std::vector<PseudoJet> pieces(const PseudoJet &reference) const{
+    return _structure->pieces(reference);
+  }
+
+  // the following ones require a computation of the area in the
+  // parent ClusterSequence (See ClusterSequenceAreaBase for details)
+  //------------------------------------------------------------------
+
+  /// check if it has a defined area
+  ///
+  /// false by default
+  virtual bool has_area() const {
+    return _structure->has_area();
+  }
+
+  /// return the jet (scalar) area.
+  ///
+  /// By default, throws an Error
+  virtual double area(const PseudoJet &reference) const{
+    return _structure->area(reference);
+  }
+
+  /// return the error (uncertainty) associated with the determination
+  /// of the area of this jet.
+  ///
+  /// By default, throws an Error
+  virtual double area_error(const PseudoJet &reference) const{
+    return _structure->area_error(reference);
+  }
+
+  /// return the jet 4-vector area.
+  ///
+  /// By default, throws an Error
+  virtual PseudoJet area_4vector(const PseudoJet &reference) const{
+    return _structure->area_4vector(reference);
+  }
+
+  /// true if this jet is made exclusively of ghosts.
+  ///
+  /// By default, throws an Error
+  virtual bool is_pure_ghost(const PseudoJet &reference) const{
+    return _structure->is_pure_ghost(reference);
+  }
+
+  //\} --- end of jet structure -------------------------------------
+
+protected:
+  SharedPtr<PseudoJetStructureBase> _structure;  ///< the wrapped structure
+};
+
+FASTJET_END_NAMESPACE
+
+#endif  //  __FASTJET_PSEUDOJET_STRUCTURE_BASE_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/config.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/config.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/config.h	(revision 5)
@@ -0,0 +1,12 @@
+#ifndef __FASTJET_CONFIG_H__
+#define __FASTJET_CONFIG_H__
+
+// by default, use an automatically generated config_auto.h
+// unless it's a windows machine in which case
+#ifndef WIN32
+#include "config_auto.h"
+#else 
+#include "fastjet/config_win.h"
+#endif // WIN32
+
+#endif // __FASTJET_CONFIG_H__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/config_auto.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/config_auto.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/config_auto.h	(revision 5)
@@ -0,0 +1,178 @@
+#ifndef _INCLUDE_FASTJET_CONFIG_AUTO_H
+#define _INCLUDE_FASTJET_CONFIG_AUTO_H 1
+ 
+/* include/fastjet/config_auto.h. Generated automatically at end of configure. */
+/* include/fastjet/config_raw.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* The ATLASCone plugin is enabled */
+#ifndef FASTJET_ENABLE_PLUGIN_ATLASCONE 
+#define FASTJET_ENABLE_PLUGIN_ATLASCONE  /**/ 
+#endif
+
+/* The CDFCones plugin is enabled */
+#ifndef FASTJET_ENABLE_PLUGIN_CDFCONES 
+#define FASTJET_ENABLE_PLUGIN_CDFCONES  /**/ 
+#endif
+
+/* The CMSIterativeCone plugin is enabled */
+#ifndef FASTJET_ENABLE_PLUGIN_CMSITERATIVECONE 
+#define FASTJET_ENABLE_PLUGIN_CMSITERATIVECONE  /**/ 
+#endif
+
+/* The D0RunICone plugin is enabled */
+#ifndef FASTJET_ENABLE_PLUGIN_D0RUNICONE 
+#define FASTJET_ENABLE_PLUGIN_D0RUNICONE  /**/ 
+#endif
+
+/* The D0RunIICone plugin is enabled */
+#ifndef FASTJET_ENABLE_PLUGIN_D0RUNIICONE 
+#define FASTJET_ENABLE_PLUGIN_D0RUNIICONE  /**/ 
+#endif
+
+/* The EECambridge plugin is enabled */
+#ifndef FASTJET_ENABLE_PLUGIN_EECAMBRIDGE 
+#define FASTJET_ENABLE_PLUGIN_EECAMBRIDGE  /**/ 
+#endif
+
+/* The GridJet plugin is enabled */
+#ifndef FASTJET_ENABLE_PLUGIN_GRIDJET 
+#define FASTJET_ENABLE_PLUGIN_GRIDJET  /**/ 
+#endif
+
+/* The Jade plugin is enabled */
+#ifndef FASTJET_ENABLE_PLUGIN_JADE 
+#define FASTJET_ENABLE_PLUGIN_JADE  /**/ 
+#endif
+
+/* The NestedDefs plugin is enabled */
+#ifndef FASTJET_ENABLE_PLUGIN_NESTEDDEFS 
+#define FASTJET_ENABLE_PLUGIN_NESTEDDEFS  /**/ 
+#endif
+
+/* The PxCone plugin is enabled */
+/* #undef ENABLE_PLUGIN_PXCONE */
+
+/* The SISCone plugin is enabled */
+#ifndef FASTJET_ENABLE_PLUGIN_SISCONE 
+#define FASTJET_ENABLE_PLUGIN_SISCONE  /**/ 
+#endif
+
+/* The TrackJet plugin is enabled */
+#ifndef FASTJET_ENABLE_PLUGIN_TRACKJET 
+#define FASTJET_ENABLE_PLUGIN_TRACKJET  /**/ 
+#endif
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#ifndef FASTJET_HAVE_DLFCN_H 
+#define FASTJET_HAVE_DLFCN_H  1 
+#endif
+
+/* Define to 1 if you have the <execinfo.h> header file. */
+#ifndef FASTJET_HAVE_EXECINFO_H 
+#define FASTJET_HAVE_EXECINFO_H  1 
+#endif
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#ifndef FASTJET_HAVE_INTTYPES_H 
+#define FASTJET_HAVE_INTTYPES_H  1 
+#endif
+
+/* Define to 1 if you have the `m' library (-lm). */
+#ifndef FASTJET_HAVE_LIBM 
+#define FASTJET_HAVE_LIBM  1 
+#endif
+
+/* Define to 1 if you have the <memory.h> header file. */
+#ifndef FASTJET_HAVE_MEMORY_H 
+#define FASTJET_HAVE_MEMORY_H  1 
+#endif
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#ifndef FASTJET_HAVE_STDINT_H 
+#define FASTJET_HAVE_STDINT_H  1 
+#endif
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#ifndef FASTJET_HAVE_STDLIB_H 
+#define FASTJET_HAVE_STDLIB_H  1 
+#endif
+
+/* Define to 1 if you have the <strings.h> header file. */
+#ifndef FASTJET_HAVE_STRINGS_H 
+#define FASTJET_HAVE_STRINGS_H  1 
+#endif
+
+/* Define to 1 if you have the <string.h> header file. */
+#ifndef FASTJET_HAVE_STRING_H 
+#define FASTJET_HAVE_STRING_H  1 
+#endif
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#ifndef FASTJET_HAVE_SYS_STAT_H 
+#define FASTJET_HAVE_SYS_STAT_H  1 
+#endif
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#ifndef FASTJET_HAVE_SYS_TYPES_H 
+#define FASTJET_HAVE_SYS_TYPES_H  1 
+#endif
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#ifndef FASTJET_HAVE_UNISTD_H 
+#define FASTJET_HAVE_UNISTD_H  1 
+#endif
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#ifndef FASTJET_LT_OBJDIR 
+#define FASTJET_LT_OBJDIR  ".libs/" 
+#endif
+
+/* Name of package */
+#ifndef FASTJET_PACKAGE 
+#define FASTJET_PACKAGE  "fastjet" 
+#endif
+
+/* Define to the address where bug reports for this package should be sent. */
+#ifndef FASTJET_PACKAGE_BUGREPORT 
+#define FASTJET_PACKAGE_BUGREPORT  "" 
+#endif
+
+/* Define to the full name of this package. */
+#ifndef FASTJET_PACKAGE_NAME 
+#define FASTJET_PACKAGE_NAME  "FastJet" 
+#endif
+
+/* Define to the full name and version of this package. */
+#ifndef FASTJET_PACKAGE_STRING 
+#define FASTJET_PACKAGE_STRING  "FastJet 3.0.3" 
+#endif
+
+/* Define to the one symbol short name of this package. */
+#ifndef FASTJET_PACKAGE_TARNAME 
+#define FASTJET_PACKAGE_TARNAME  "fastjet" 
+#endif
+
+/* Define to the home page for this package. */
+#ifndef FASTJET_PACKAGE_URL 
+#define FASTJET_PACKAGE_URL  "" 
+#endif
+
+/* Define to the version of this package. */
+#ifndef FASTJET_PACKAGE_VERSION 
+#define FASTJET_PACKAGE_VERSION  "3.0.3" 
+#endif
+
+/* Define to 1 if you have the ANSI C header files. */
+#ifndef FASTJET_STDC_HEADERS 
+#define FASTJET_STDC_HEADERS  1 
+#endif
+
+/* Version number of package */
+#ifndef FASTJET_VERSION 
+#define FASTJET_VERSION  "3.0.3" 
+#endif
+ 
+/* once: _INCLUDE_FASTJET_CONFIG_AUTO_H */
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/config_raw.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/config_raw.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/config_raw.h	(revision 5)
@@ -0,0 +1,105 @@
+/* include/fastjet/config_raw.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* The ATLASCone plugin is enabled */
+#define ENABLE_PLUGIN_ATLASCONE /**/
+
+/* The CDFCones plugin is enabled */
+#define ENABLE_PLUGIN_CDFCONES /**/
+
+/* The CMSIterativeCone plugin is enabled */
+#define ENABLE_PLUGIN_CMSITERATIVECONE /**/
+
+/* The D0RunICone plugin is enabled */
+#define ENABLE_PLUGIN_D0RUNICONE /**/
+
+/* The D0RunIICone plugin is enabled */
+#define ENABLE_PLUGIN_D0RUNIICONE /**/
+
+/* The EECambridge plugin is enabled */
+#define ENABLE_PLUGIN_EECAMBRIDGE /**/
+
+/* The GridJet plugin is enabled */
+#define ENABLE_PLUGIN_GRIDJET /**/
+
+/* The Jade plugin is enabled */
+#define ENABLE_PLUGIN_JADE /**/
+
+/* The NestedDefs plugin is enabled */
+#define ENABLE_PLUGIN_NESTEDDEFS /**/
+
+/* The PxCone plugin is enabled */
+/* #undef ENABLE_PLUGIN_PXCONE */
+
+/* The SISCone plugin is enabled */
+#define ENABLE_PLUGIN_SISCONE /**/
+
+/* The TrackJet plugin is enabled */
+#define ENABLE_PLUGIN_TRACKJET /**/
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <execinfo.h> header file. */
+#define HAVE_EXECINFO_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `m' library (-lm). */
+#define HAVE_LIBM 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#define LT_OBJDIR ".libs/"
+
+/* Name of package */
+#define PACKAGE "fastjet"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "FastJet"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "FastJet 3.0.3"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "fastjet"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "3.0.3"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "3.0.3"
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/config_win.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/config_win.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/config_win.h	(revision 5)
@@ -0,0 +1,40 @@
+#define FASTJET_PACKAGE_STRING  "FastJet 3.0.3"
+#define FASTJET_PACKAGE_VERSION  "3.0.3"
+
+/* The ATLASCone plugin is disabled by default*/
+#undef FASTJET_ENABLE_PLUGIN_ATLASCONE 
+
+/* The CDFJetClu and CDFMidPoint plugins are enabled by default*/
+#define FASTJET_ENABLE_PLUGIN_CDFCONES 
+
+/* The CMSIterativeCone plugin is disabled by default*/
+#undef FASTJET_ENABLE_PLUGIN_CMSITERATIVECONE 
+
+/* The D0RunICone plugin is disabled by default*/
+#undef FASTJET_ENABLE_PLUGIN_D0RUNICONE 
+
+/* The D0RunIICone plugin is disabled by default*/
+#undef FASTJET_ENABLE_PLUGIN_D0RUNIICONE 
+
+/* The EECambridge plugin is enabled by default*/
+#define FASTJET_ENABLE_PLUGIN_EECAMBRIDGE 
+
+/* The Jade plugin is enabled by default*/
+#define FASTJET_ENABLE_PLUGIN_JADE 
+
+/* The NestedDefs plugin is enabled by default*/
+#define FASTJET_ENABLE_PLUGIN_NESTEDDEFS 
+
+/* The PxCone plugin is disabled by default*/
+#undef FASTJET_ENABLE_PLUGIN_PXCONE
+
+/* The SISCone plugin is enabled by default*/
+#define FASTJET_ENABLE_PLUGIN_SISCONE 
+
+/* The TrackJet plugin is disabled by default*/
+#undef FASTJET_ENABLE_PLUGIN_TRACKJET
+
+/* The GridJet plugin is enabled by default */
+#define FASTJET_ENABLE_PLUGIN_GRIDJET
+
+/* end of plugin section */
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/BasicRandom.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/BasicRandom.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/BasicRandom.hh	(revision 5)
@@ -0,0 +1,194 @@
+// Simple random number generator class taken from nlojet++.
+// Some doxygen-style comments added by Gavin Salam, August 2006.
+// $Id: BasicRandom.hh 1761 2010-09-16 10:43:18Z soyez $
+//
+//  Copyright (C) 2002 Zoltan Nagy
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#ifndef __FASTJET_BASICRANDOM_HH__
+#define __FASTJET_BASICRANDOM_HH__ 1
+
+//   Standard includes
+#include <iostream>
+#include <vector>
+#include <cassert>
+#include "fastjet/internal/base.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+/// \if internal_doc
+/// @ingroup internal
+/// \class BasicRandom
+/// Base class for random number generator of a generic value type
+/// \endif
+template<typename _Tp> class BasicRandom {
+public:
+  typedef _Tp          value_type;
+  typedef unsigned int size_type;
+  typedef value_type*  pointer;
+  
+  //   give pseudo random numbers
+  value_type operator() ();
+  void       operator() (size_type, pointer);
+
+  //   (re)initialize the random number generator
+  void randomize(void *);
+
+  //   minimum and maximum values
+  static value_type min();
+  static value_type max();
+
+  //   print the informations about the generator to the stream
+  void print_info(std::ostream& __os = std::cout);
+};
+
+//   default random generator
+int __default_random_generator(int *__iseed); 
+
+
+//   specializations
+
+/// \if internal_doc
+/// @ingroup internal
+/// template specialization (int) for the BasicRandom template class. 
+/// \endif
+template<>
+class BasicRandom<int>
+{
+public:
+  typedef int          value_type;
+  typedef unsigned int size_type;
+  typedef value_type*  pointer;
+  
+  // constructors
+  explicit BasicRandom(int __s1 = 12345, int __s2 = 67890) {
+    _M_iseed[0] = __s1;
+    _M_iseed[1] = __s2;
+  }
+    
+  //   give pseudo random numbers
+  value_type operator() () { 
+    return __default_random_generator(_M_iseed);
+  }
+  
+  void operator() (size_type __n, pointer __res) {
+    for(size_type __i = 0; __i < __n; __i++) 
+      __res[__i] = __default_random_generator(_M_iseed);
+  }
+
+  //   (re)initialize the random number generator
+  void randomize(void *__iseed) {
+    int *__new_seed = (int*) __iseed;
+    _M_iseed[0] = __new_seed[0];
+    _M_iseed[1] = __new_seed[1];
+  }
+
+  void set_status(const std::vector<int> & __iseed) {
+    assert(__iseed.size() >= 2);
+    _M_iseed[0] = __iseed[0];
+    _M_iseed[1] = __iseed[1];
+  }
+
+  void get_status(std::vector<int> & __iseed) {
+    __iseed.resize(2);
+    __iseed[0] = _M_iseed[0];
+    __iseed[1] = _M_iseed[1];
+  }
+  
+  //   minimum and maximum values
+  inline static value_type min() { return 0;}
+  inline static value_type max() { return 2147483647;}
+
+  //   print the informations about the generator to the stream
+  void print_info(std::ostream& __os = std::cout) {
+    __os<<"BasicRandom<int> : "<<_M_iseed[0]<<", "<<_M_iseed[1]<<std::endl;
+  }
+  
+private:
+  int _M_iseed[2];
+};
+  
+
+/// \if internal_doc
+/// @ingroup internal
+/// template specialization (double) for the BasicRandom template class. 
+/// \endif
+template<> class BasicRandom<double> {
+public:
+  typedef double       value_type;
+  typedef unsigned int size_type;
+  typedef value_type*  pointer;
+  
+  /// constructor that takes two integers to specify the seed
+  explicit BasicRandom(int __s1 = 12345, int __s2 = 67890) {
+    _M_iseed[0] = __s1;
+    _M_iseed[1] = __s2;
+  }
+    
+  /// return a single pseudorandom double number, in the range 0.0 to 1.0
+  /// (not sure whether this range is open or closed)
+  value_type operator() () { 
+    return 4.6566128752457969241e-10*__default_random_generator(_M_iseed);
+  }
+  
+  /// given a pointer __res to the beginning of an array, fill that array
+  /// with __n random numbers
+  void operator() (size_type __n, pointer __res) {
+    for(size_type __i = 0; __i < __n; __i++) 
+      __res[__i] = this -> operator()(); 
+  }
+
+  ///  (re)initialize the random number generator from an array of seeds
+  void randomize(void *__iseed) {
+    int *__new_seed = (int*) __iseed;
+    _M_iseed[0] = __new_seed[0];
+    _M_iseed[1] = __new_seed[1];
+  }
+  
+  void set_status(const std::vector<int> & __iseed) {
+    assert(__iseed.size() >= 2);
+    _M_iseed[0] = __iseed[0];
+    _M_iseed[1] = __iseed[1];
+  }
+
+  void get_status(std::vector<int> & __iseed) {
+    __iseed.resize(2);
+    __iseed[0] = _M_iseed[0];
+    __iseed[1] = _M_iseed[1];
+  }
+  
+  /// minimum value returned by the generator
+  inline static value_type min() { return 0.0;}
+  /// maximum value returned by the generator
+  inline static value_type max() { return 1.0;}
+
+  ///  print information about the generator to the stream
+  void print_info(std::ostream& __os = std::cout) {
+    __os<<"BasicRandom<double> : "<<_M_iseed[0]<<", "<<_M_iseed[1]<<std::endl;
+  }
+  
+private:
+  int _M_iseed[2];
+};
+  
+//   globally defined random number generator
+extern BasicRandom<int>     _G_random_int;
+extern BasicRandom<double>  _G_random_double;
+
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_BASICRANDOM_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/ClosestPair2D.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/ClosestPair2D.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/ClosestPair2D.hh	(revision 5)
@@ -0,0 +1,240 @@
+//STARTHEADER
+// $Id: ClosestPair2D.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLOSESTPAIR2D__HH__
+#define __FASTJET_CLOSESTPAIR2D__HH__
+
+#include<vector>
+#include<stack>
+#include<iostream>
+#include "fastjet/internal/ClosestPair2DBase.hh"
+#include "fastjet/internal/SearchTree.hh"
+#include "fastjet/internal/MinHeap.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+/// \if internal_doc
+/// @ingroup internal
+/// \class ClosestPair2D
+/// concrete implementation for finding closest pairs in 2D -- will
+/// use Chan's (hopefully efficient) shuffle based structures
+/// \endif
+class ClosestPair2D : public ClosestPair2DBase {
+public:
+  /// constructor from a vector of 2D positions -- number of objects
+  /// after insertion and deletion must never exceed positions.size();
+  /// objects are given IDs that correspond to their index in the vector 
+  /// of positions
+  ClosestPair2D(const std::vector<Coord2D> & positions, 
+		const Coord2D & left_corner, const Coord2D & right_corner) {
+    _initialize(positions, left_corner, right_corner, positions.size());
+  };
+
+  /// constructor which allows structure to grow beyond positions.size(), up
+  /// to max_size
+  ClosestPair2D(const std::vector<Coord2D> & positions, 
+		const Coord2D & left_corner, const Coord2D & right_corner,
+		const unsigned int max_size) {
+    _initialize(positions, left_corner, right_corner, max_size);
+  };
+
+  /// provides the IDs of the closest pair as well as the distance between
+  /// them
+  void closest_pair(unsigned int & ID1, unsigned int & ID2, 
+		    double & distance2) const;
+
+  /// removes the entry labelled by ID from the object;
+  void remove(unsigned int ID);
+ 
+  /// inserts the position into the closest pair structure and returns the
+  /// ID that has been allocated for the object.
+  unsigned int insert(const Coord2D &);
+
+  /// removes ID1 and ID2 and inserts position, returning the ID 
+  /// corresponding to position...
+  virtual unsigned int replace(unsigned int ID1, unsigned int ID2, 
+			       const Coord2D & position);
+
+  /// replaces IDs_to_remove with points at the new_positions
+  /// indicating the IDs allocated to the new points in new_IDs
+  virtual void replace_many(const std::vector<unsigned int> & IDs_to_remove,
+			    const std::vector<Coord2D> & new_positions,
+			    std::vector<unsigned int> & new_IDs);
+
+  // mostly for checking how things are working...
+  inline void print_tree_depths(std::ostream & outdev) const {
+    outdev    << _trees[0]->max_depth() << " "
+	      << _trees[1]->max_depth() << " "
+	      << _trees[2]->max_depth() << "\n";
+  };
+
+  unsigned int size();
+
+private:
+  
+  void _initialize(const std::vector<Coord2D> & positions, 
+	      const Coord2D & left_corner, const Coord2D & right_corner,
+	      const unsigned int max_size);
+
+  static const unsigned int _nshift = 3;
+
+  class Point; // will be defined below
+
+  /// since sets of three objects will crop up repeatedly, useful
+  /// to have a triplet class?
+  template<class T> class triplet {
+  public:
+    inline const T & operator[](unsigned int i) const {return _contents[i];};
+    inline       T & operator[](unsigned int i)       {return _contents[i];};
+  private:
+    T _contents[_nshift];
+  };
+
+
+  /// class that will take care of ordering of shuffles for us
+  class Shuffle {
+  public:
+    unsigned int x, y;
+    Point * point;
+    bool operator<(const Shuffle &) const;
+    void operator+=(unsigned int shift) {x += shift; y+= shift;};
+  };
+
+  typedef SearchTree<Shuffle>     Tree;
+  typedef Tree::circulator        circulator;
+  typedef Tree::const_circulator  const_circulator;
+
+
+  triplet<std::auto_ptr<Tree> >  _trees;
+  std::auto_ptr<MinHeap> _heap;
+  std::vector<Point>     _points;
+  std::stack<Point *>    _available_points;
+
+  /// points that are "under review" in some way
+  std::vector<Point *>   _points_under_review;
+
+  // different statuses for review
+  static const unsigned int _remove_heap_entry = 1;
+  static const unsigned int _review_heap_entry = 2;
+  static const unsigned int _review_neighbour  = 4;
+
+  /// add a label to a point as to the nature of review needed
+  /// (includes adding it to list of points needing review) [doesn't
+  /// affect other labels already set for the point]
+  void _add_label(Point * point, unsigned int review_flag);
+
+  /// sets the label for the point to be exclusively this 
+  /// review flag (and adds it to list of points needing review
+  /// if not already there)
+  void _set_label(Point * point, unsigned int review_flag);
+
+  /// for all entries of the _points_under_review[] vector, carry out
+  /// the actions indicated by its review flag; the points are
+  /// then removed from _points_under_review[] and their flags
+  /// set to zero
+  void _deal_with_points_to_review();
+
+  /// carry out the search-tree related operations of point removal
+  void _remove_from_search_tree(Point * point_to_remove);
+
+  /// carry out the search-tree related operations of point insertion
+  void _insert_into_search_tree(Point * new_point);
+
+  /// takes a point and creates a shuffle with the given shift
+  void _point2shuffle(Point & , Shuffle & , unsigned int shift);
+
+  /// pieces needed for converting coordinates to integer
+  Coord2D _left_corner;
+  double _range;
+
+  int _ID(const Point *) const;
+
+  triplet<unsigned int> _shifts;     // absolute shifts
+  triplet<unsigned int> _rel_shifts; // shifts relative to previous shift
+
+  unsigned int _cp_search_range;
+};
+
+
+//----------------------------------------------------------------------
+/// \if internal_doc
+/// @ingroup internal
+/// \class ClosestPair2D::Point
+/// class for representing all info needed about a point
+/// \endif
+class ClosestPair2D::Point {
+public:
+  /// the point's coordinates
+  Coord2D coord;
+  /// a pointer to its closest neighbour in our structure
+  Point * neighbour;
+  /// the corresponding squared distance
+  double  neighbour_dist2;
+  /// circulators for each of the shifts of the shuffles
+  triplet<circulator> circ;
+
+  /// indicates that something special is currently happening to this point
+  unsigned int review_flag;
+
+  /// returns the distance between two of these objects
+  double distance2(const Point & other) const {
+    return coord.distance2(other.coord);
+  };
+
+  /// creates a shuffle for us with a given shift
+  //void set_shuffle(Shuffle & shuffle);
+};
+
+
+//----------------------------------------------------------------------
+/// returns true if floor(ln_base2(x)) < floor(ln_base2(y)), using
+/// Chan's neat trick...
+inline bool floor_ln2_less(unsigned x, unsigned y) {
+  if (x>y) return false;
+  return (x < (x^y)); // beware of operator precedence...
+}
+
+
+//----------------------------------------------------------------------
+/// returns the ID for the specified point...
+inline int ClosestPair2D::_ID(const Point * point) const {
+  return point - &(_points[0]);
+}
+
+
+//
+inline unsigned int ClosestPair2D::size() {
+  return _points.size() - _available_points.size();
+}
+
+
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_CLOSESTPAIR2D__HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/ClosestPair2DBase.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/ClosestPair2DBase.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/ClosestPair2DBase.hh	(revision 5)
@@ -0,0 +1,135 @@
+//STARTHEADER
+// $Id: ClosestPair2DBase.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLOSESTPAIR2DBASE__HH__
+#define __FASTJET_CLOSESTPAIR2DBASE__HH__
+
+#include<vector>
+#include "fastjet/internal/base.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+/// \if internal_doc
+/// @ingroup internal
+/// \class Coord2D
+/// class for representing 2d coordinates and carrying out some basic 
+/// operations on them
+/// \endif
+class Coord2D {
+public:
+  double x, y;
+
+  Coord2D() {};
+
+  Coord2D(double a, double b): x(a), y(b) {};
+
+  /// return the vector difference between two coordinates
+  Coord2D operator-(const Coord2D & other) const {
+    return Coord2D(x - other.x,  y - other.y);};
+
+  /// return the vector sum between two coordinates
+  Coord2D operator+(const Coord2D & other) const {
+    return Coord2D(x + other.x,  y + other.y);};
+
+  /// return the product of the coordinate with the factor
+  Coord2D operator*(double factor) const {return Coord2D(factor*x,factor*y);};
+  friend Coord2D operator*(double factor, const Coord2D & coord) {
+    return Coord2D(factor*coord.x,factor*coord.y);
+  }
+
+  /// division of each component of coordinate
+  Coord2D operator/(double divisor) const {
+    return Coord2D(x / divisor,  y / divisor);};
+
+  /// return the squared distance between two coordinates
+  friend double distance2(const Coord2D & a, const Coord2D & b) {
+    double dx = a.x - b.x, dy = a.y-b.y;
+    return dx*dx+dy*dy;
+  };
+  /// return the squared distance between two coordinates
+  double distance2(const Coord2D & b) const {
+    double dx = x - b.x, dy = y-b.y;
+    return dx*dx+dy*dy;
+  };
+};
+
+
+//----------------------------------------------------------------------
+/// \if internal_doc
+/// @ingroup internal
+/// \class ClosestPair2DBase
+/// abstract base class for finding closest pairs in 2D
+/// \endif
+class ClosestPair2DBase {
+public:
+  /// provides the IDs of the closest pair as well as the squared
+  /// distance between them
+  virtual void closest_pair(unsigned int & ID1, unsigned int & ID2, 
+			    double & distance2) const = 0;
+  
+  /// removes the entry labelled by ID from the object;
+  virtual void remove(unsigned int ID) = 0;
+ 
+  /// inserts the position into the closest pair structure and returns the
+  /// ID that has been allocated for the object.
+  virtual unsigned int insert(const Coord2D & position) = 0;
+
+  /// replaces the specified ID1 and ID2 with something at a new position
+  /// assuming that ID1 and ID2 are in sequence wrt position; it returns
+  /// the ID of the new object...
+  virtual unsigned int replace(unsigned int ID1, unsigned int ID2, 
+			       const Coord2D & position) {
+    remove(ID1); 
+    remove(ID2); 
+    unsigned new_ID = insert(position);
+    return(new_ID);
+  };
+
+  /// replaces IDs_to_remove with points at the new_positions
+  /// indicating the IDs allocated to the new points in new_IDs
+  virtual void replace_many(const std::vector<unsigned int> & IDs_to_remove,
+		       const std::vector<Coord2D> & new_positions,
+		       std::vector<unsigned int> & new_IDs) {
+    for(unsigned i = 0; i < IDs_to_remove.size(); i++) {
+      remove(IDs_to_remove[i]);}
+    new_IDs.resize(0);
+    for(unsigned i = 0; i < new_positions.size(); i++) {
+      new_IDs.push_back(insert(new_positions[i]));}
+  }
+
+  virtual unsigned int size() = 0;
+
+  virtual ~ClosestPair2DBase() {};
+  
+};
+
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_CLOSESTPAIR2DBASE__HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/ClusterSequence_N2.icc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/ClusterSequence_N2.icc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/ClusterSequence_N2.icc	(revision 5)
@@ -0,0 +1,200 @@
+// -*- C++ -*-
+#ifndef __CLUSTERQUENCE_N2_ICC__
+#define __CLUSTERQUENCE_N2_ICC__
+#include "fastjet/ClusterSequence.hh"
+
+//STARTHEADER
+// $Id: ClusterSequence_N2.cc 1351 2009-01-09 18:03:03Z salam $
+//
+// Copyright (c) 2005-2009, Matteo Cacciari, Gavin Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet; if not, write to the Free Software
+//  Foundation, Inc.:
+//      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+//----------------------------------------------------------------------
+/// Order(N^2) clustering 
+///
+/// Works for any class BJ that satisfies certain minimal 
+/// requirements (which are ...?)
+///
+/// - need to have _bj_set_jetinfo
+/// - need to have _bj_dist
+/// - should contain members kt2 (=energy^2), NN, NN_dist, _jets_index
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+// this should not normally appear in an include file, but we'll make an 
+// exception seeing as this is
+//using namespace std;
+
+
+template<class BJ> void ClusterSequence::_simple_N2_cluster() {
+  int n = _jets.size();
+  BJ * briefjets = new BJ[n];
+  BJ * jetA = briefjets, * jetB;
+  
+  // initialise the basic jet info 
+  for (int i = 0; i< n; i++) {
+    _bj_set_jetinfo(jetA, i);
+    jetA++; // move on to next entry of briefjets
+  }
+  BJ * tail = jetA; // a semaphore for the end of briefjets
+  BJ * head = briefjets; // a nicer way of naming start
+
+  // now initialise the NN distances: jetA will run from 1..n-1; and
+  // jetB from 0..jetA-1
+  for (jetA = head + 1; jetA != tail; jetA++) {
+    // set NN info for jetA based on jets running from head..jetA-1,
+    // checking in the process whether jetA itself is an undiscovered
+    // NN of one of those jets.
+    _bj_set_NN_crosscheck(jetA, head, jetA);
+  }
+
+
+  // now create the diJ (where J is i's NN) table -- remember that 
+  // we differ from standard normalisation here by a factor of R2
+  double * diJ = new double[n];
+  jetA = head;
+  for (int i = 0; i < n; i++) {
+    diJ[i] = _bj_diJ(jetA);
+    jetA++; // have jetA follow i
+  }
+
+  // now run the recombination loop
+  int history_location = n-1;
+  while (tail != head) {
+
+    // find the minimum of the diJ on this round
+    double diJ_min = diJ[0];
+    int diJ_min_jet = 0;
+    for (int i = 1; i < n; i++) {
+      if (diJ[i] < diJ_min) {diJ_min_jet = i; diJ_min  = diJ[i];}
+    }
+    
+    // do the recombination between A and B
+    history_location++;
+    jetA = & briefjets[diJ_min_jet];
+    // GPS mod 2009-02-11
+    //jetB = jetA->NN;
+    jetB = static_cast<BJ *>(jetA->NN);
+    // put the normalisation back in
+    diJ_min *= _invR2; 
+    if (jetB != NULL) {
+      // jet-jet recombination
+      // If necessary relabel A & B to ensure jetB < jetA, that way if
+      // the larger of them == newtail then that ends up being jetA and 
+      // the new jet that is added as jetB is inserted in a position that
+      // has a future!
+      if (jetA < jetB) {std::swap(jetA,jetB);}
+
+      int nn; // new jet index
+      _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
+
+      // what was jetB will now become the new jet
+      _bj_set_jetinfo(jetB, nn);
+
+    } else {
+      // jet-beam recombination
+      _do_iB_recombination_step(jetA->_jets_index, diJ_min);
+    }
+
+    // now update our nearest neighbour info and diJ table
+    // first reduce size of table
+    tail--; n--;
+    // Copy last jet contents and diJ info into position of jetA
+    *jetA = *tail;
+    diJ[jetA - head] = diJ[tail-head];
+
+    // Initialise jetB's NN distance as well as updating it for 
+    // other particles.
+    // NB: by having different loops for jetB == or != NULL we could
+    //     perhaps save a few percent (usually avoid one if inside loop),
+    //     but will not do it for now because on laptop fluctuations are
+    //     too large to reliably measure a few percent difference...
+    for (BJ * jetI = head; jetI != tail; jetI++) {
+      // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
+      if (jetI->NN == jetA || jetI->NN == jetB) {
+	_bj_set_NN_nocross(jetI, head, tail);
+	diJ[jetI-head] = _bj_diJ(jetI); // update diJ 
+      } 
+      // check whether new jetB is closer than jetI's current NN and
+      // if need be update things
+      if (jetB != NULL) {
+	double dist = _bj_dist(jetI,jetB);
+	if (dist < jetI->NN_dist) {
+	  if (jetI != jetB) {
+	    jetI->NN_dist = dist;
+	    jetI->NN = jetB;
+	    diJ[jetI-head] = _bj_diJ(jetI); // update diJ...
+	  }
+	}
+	if (dist < jetB->NN_dist) {
+	  if (jetI != jetB) {
+	    jetB->NN_dist = dist;
+	    jetB->NN      = jetI;}
+	}
+      }
+      // if jetI's NN is the new tail then relabel it so that it becomes jetA
+      if (jetI->NN == tail) {jetI->NN = jetA;}
+    }
+
+    
+    if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
+
+
+  }
+  
+
+  // final cleaning up;
+  delete[] diJ;
+  delete[] briefjets;
+}
+
+
+
+// //----------------------------------------------------------------------
+// // initialises a GenBriefJet
+// template<> inline void ClusterSequence::_bj_set_jetinfo(
+//                            GenBriefJet * const jetA, const int _jets_index) const {
+// 
+//   jetA->init(_jets[_jets_index]);
+//   jetA->_jets_index = _jets_index;
+// 
+// }
+// 
+// 
+// //----------------------------------------------------------------------
+// // returns the distance between two GenBriefJets
+// template<> double ClusterSequence::_bj_dist(
+//                 const GenBriefJet * const jeta, 
+//                 const GenBriefJet * const jetb) const {
+//   return jeta->geom_ij(jetb);
+// }
+
+FASTJET_END_NAMESPACE
+
+#endif // __CLUSTERQUENCE_N2_ICC__
+
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/Dnn2piCylinder.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/Dnn2piCylinder.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/Dnn2piCylinder.hh	(revision 5)
@@ -0,0 +1,271 @@
+//STARTHEADER
+// $Id: Dnn2piCylinder.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef DROP_CGAL // in case we do not have the code for CGAL
+#ifndef __FASTJET_DNN2PICYLINDER_HH__
+#define __FASTJET_DNN2PICYLINDER_HH__
+
+#include "fastjet/internal/DynamicNearestNeighbours.hh"
+#include "fastjet/internal/DnnPlane.hh"
+#include "fastjet/internal/numconsts.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+
+/// \if internal_doc
+/// @ingroup internal
+/// \class Dnn2piCylinder
+/// class derived from DynamicNearestNeighbours that provides an
+/// implementation for the surface of cylinder (using one 
+/// DnnPlane object spanning 0--2pi).
+/// \endif
+class Dnn2piCylinder : public DynamicNearestNeighbours {
+ public:
+  /// empty initaliser
+  Dnn2piCylinder() {}
+
+  /// Initialiser from a set of points on an Eta-Phi plane, where
+  /// eta can have an arbitrary ranges and phi must be in range
+  /// 0 <= phi < 2pi;
+  /// 
+  /// NB: this class is more efficient than the plain Dnn4piCylinder
+  /// class, but can give wrong answers when the nearest neighbour is
+  /// further away than 2pi (in this case a point's nearest neighbour
+  /// becomes itself, because it is considered to be a distance 2pi
+  /// away). For the kt-algorithm (e.g.) this is actually not a
+  /// problem (the distance need only be accurate when it is less than
+  /// R, assuming R<2pi [not necessarily always the case as of
+  /// 2010-11-19, when we've removed the requirement R<pi/2 in the
+  /// JetDefinition constructor]), so we can tell the routine to
+  /// ignore this problem -- alternatively the routine will crash if
+  /// it detects it occurring (only when finding the nearest neighbour
+  /// index, not its distance).
+  Dnn2piCylinder(const std::vector<EtaPhi> &,
+		 const bool & ignore_nearest_is_mirror = false,
+		 const bool & verbose = false );
+
+  /// Returns the index of  the nearest neighbour of point labelled
+  /// by ii (assumes ii is valid)
+  int NearestNeighbourIndex(const int & ii) const ;
+
+  /// Returns the distance to the nearest neighbour of point labelled
+  /// by index ii (assumes ii is valid)
+  double NearestNeighbourDistance(const int & ii) const ;
+
+  /// Returns true iff the given index corresponds to a point that
+  /// exists in the DNN structure (meaning that it has been added, and
+  /// not removed in the meantime)
+  bool Valid(const int & index) const;
+
+  void RemoveAndAddPoints(const std::vector<int> & indices_to_remove,
+			  const std::vector<EtaPhi> & points_to_add,
+			  std::vector<int> & indices_added,
+			  std::vector<int> & indices_of_updated_neighbours);
+
+  ~Dnn2piCylinder();
+
+ private:
+
+  // our extras to help us navigate, find distance, etc.
+  const static int INEXISTENT_VERTEX=-3;
+
+  bool _verbose;
+
+  bool _ignore_nearest_is_mirror;
+
+  /// Picture of how things will work... Copy 0--pi part of the 0--2pi
+  /// cylinder into a region 2pi--2pi+ a bit of a Euclidean plane. Below we
+  /// show points labelled by + that have a mirror image in this
+  /// manner, while points labelled by * do not have a mirror image.
+  ///      	 			  
+  ///      |           .     |		  
+  ///      |	       .     |		  
+  ///      |           .     |		  
+  ///      |           .     |		  
+  ///      |        2  .     |		  
+  ///      |        *  .     |		  
+  ///      | +         . +   |		  
+  ///      | 0         . 1   |
+  ///      |	       .     |
+  ///      0          2pi   2pi + a bit
+  ///   	     
+  /// Each "true" point has its true "cylinder" index (the index that
+  /// is known externally to this class) as well as euclidean plane
+  /// indices (main_index and mirror index in the MirrorVertexInfo
+  /// structure), which are private concepts of this class.
+  /// 
+  /// In above picture our structures would hold the following info
+  /// (the picture shows the euclidean-plane numbering)
+  ///
+  /// _mirror_info[cylinder_index = 0] = (0, 1)
+  /// _mirror_info[cylinder_index = 1] = (2, INEXISTENT_VERTEX)
+  ///
+  /// We also need to be able to go from the euclidean plane indices
+  /// back to the "true" cylinder index, and for this purpose we use
+  /// the std::vector _cylinder_index_of_plane_vertex[...], which in the above example has
+  /// the following contents
+  ///
+  /// _cylinder_index_of_plane_vertex[0] = 0
+  /// _cylinder_index_of_plane_vertex[1] = 0
+  /// _cylinder_index_of_plane_vertex[2] = 1
+  ///
+
+  /// 
+  struct MirrorVertexInfo {
+    /// index of the given point (appearing in the range 0--2pi) in the 
+    /// 0--2pi euclidean plane structure (position will coincide with
+    /// that on the 0--2pi cylinder, but index labelling it will be
+    /// different)
+    int main_index; 
+    /// index of the mirror point (appearing in the range 2pi--3pi) in the
+    /// 0--3pi euclidean plane structure
+    int mirror_index; 
+  };
+
+  // for each "true" vertex we have reference to indices in the euclidean
+  // plane structure
+  std::vector<MirrorVertexInfo> _mirror_info;
+  // for each index in the euclidean 0--2pi plane structure we want to
+  // be able to get back to the "true" vertex index on the overall
+  // 0--2pi cylinder structure
+  std::vector<int> _cylinder_index_of_plane_vertex;
+
+  // NB: we define POINTERS here because the initialisation gave
+  //     us problems (things crashed!), perhaps because in practice
+  //     we were making a copy without being careful and defining
+  //     a proper copy constructor.
+  DnnPlane * _DNN;
+
+  /// given a phi value in the 0--pi range return one 
+  /// in the 2pi--3pi range; whereas if it is in the pi-2pi range then
+  /// remap it to be inthe range (-pi)--0.
+  inline EtaPhi _remap_phi(const EtaPhi & point) {
+    double phi = point.second;
+    if (phi < pi) { phi += twopi ;} else {phi -= twopi;}
+    return EtaPhi(point.first, phi);}
+
+
+  //----------------------------------------------------------------------
+  /// Actions here are similar to those in the
+  /// Dnn3piCylinder::_RegisterCylinderPoint case, however here we do
+  /// NOT create the mirror point -- instead we initialise the structure
+  /// as if there were no need for the mirror point.
+  ///
+  /// ADDITIONALLY push the cylinder_point onto the vector plane_points.
+  void _RegisterCylinderPoint (const EtaPhi & cylinder_point,
+			       std::vector<EtaPhi> & plane_points);
+
+  /// For each plane point specified in the vector plane_indices,
+  /// establish whether there is a need to create a mirror point
+  /// according to the following criteria:
+  ///
+  /// . phi < pi
+  /// . mirror does not already exist
+  /// . phi < NearestNeighbourDistance 
+  ///   (if this is not true then there is no way that its mirror point
+  ///   could have a nearer neighbour).
+  ///
+  /// If conditions all hold, then create the mirror point, insert it
+  /// into the _DNN structure, adjusting any nearest neighbours, and
+  /// return the list of plane points whose nearest neighbours have
+  /// changed (this will include the new neighbours that have just been
+  /// added)
+  void _CreateNecessaryMirrorPoints(
+			  const std::vector<int> & plane_indices,
+			  std::vector<int> & updated_plane_points);
+
+};
+
+
+// here follow some inline implementations of the simpler of the
+// functions defined above
+
+//----------------------------------------------------------------------
+/// Note: one of the difficulties of the 0--2pi mapping is that
+/// a point may have its mirror copy as its own nearest neighbour
+/// (if no other point is within a distance of 2pi). This does
+/// not matter for the kt_algorithm with
+/// reasonable values of radius, but might matter for a general use
+/// of this algorithm -- depending on whether or not the user has
+/// initialised the class with instructions to ignore this problem the
+/// program will detect and ignore it, or crash.
+inline int Dnn2piCylinder::NearestNeighbourIndex(const int & current) const {
+  int main_index = _mirror_info[current].main_index;
+  int mirror_index = _mirror_info[current].mirror_index;
+  int plane_index;
+  if (mirror_index == INEXISTENT_VERTEX ) {
+    plane_index = _DNN->NearestNeighbourIndex(main_index);
+  } else {
+    plane_index = (
+	_DNN->NearestNeighbourDistance(main_index) < 
+	_DNN->NearestNeighbourDistance(mirror_index)) ? 
+      _DNN->NearestNeighbourIndex(main_index) : 
+      _DNN->NearestNeighbourIndex(mirror_index) ; 
+  }
+  int this_cylinder_index = _cylinder_index_of_plane_vertex[plane_index];
+  // either the user has acknowledged the fact that they may get the
+  // mirror copy as the closest point, or crash if it should occur
+  // that mirror copy is the closest point.
+  assert(_ignore_nearest_is_mirror || this_cylinder_index != current);
+  //if (this_cylinder_index == current) {
+  //  cerr << "WARNING point "<<current<<
+  //    " has its mirror copy as its own nearest neighbour"<<endl;
+  //}
+  return this_cylinder_index;
+}
+
+inline double Dnn2piCylinder::NearestNeighbourDistance(const int & current) const {
+  int main_index = _mirror_info[current].main_index;
+  int mirror_index = _mirror_info[current].mirror_index;
+  if (mirror_index == INEXISTENT_VERTEX ) {
+    return _DNN->NearestNeighbourDistance(main_index);
+  } else {
+    return (
+	_DNN->NearestNeighbourDistance(main_index) < 
+	_DNN->NearestNeighbourDistance(mirror_index)) ? 
+      _DNN->NearestNeighbourDistance(main_index) : 
+      _DNN->NearestNeighbourDistance(mirror_index) ; 
+  }
+ 
+}
+
+inline bool Dnn2piCylinder::Valid(const int & index) const {
+  return (_DNN->Valid(_mirror_info[index].main_index));
+}
+
+
+inline Dnn2piCylinder::~Dnn2piCylinder() {
+  delete _DNN; 
+}
+
+
+FASTJET_END_NAMESPACE
+
+#endif //  __FASTJET_DNN2PICYLINDER_HH__
+#endif //DROP_CGAL 
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/Dnn3piCylinder.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/Dnn3piCylinder.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/Dnn3piCylinder.hh	(revision 5)
@@ -0,0 +1,259 @@
+//STARTHEADER
+// $Id: Dnn3piCylinder.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef DROP_CGAL // in case we do not have the code for CGAL
+#ifndef __FASTJET_DNN3PICYLINDER_HH__
+#define __FASTJET_DNN3PICYLINDER_HH__
+
+#include "fastjet/internal/DynamicNearestNeighbours.hh"
+#include "fastjet/internal/DnnPlane.hh"
+#include "fastjet/internal/numconsts.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+/// \if internal_doc
+/// @ingroup internal
+/// \class Dnn3piCylinder
+/// class derived from DynamicNearestNeighbours that provides an
+/// implementation for the surface of cylinder (using one 
+/// DnnPlane object spanning 0--3pi).
+/// \endif
+class Dnn3piCylinder : public DynamicNearestNeighbours {
+ public:
+  /// empty initaliser
+  Dnn3piCylinder() {}
+
+  /// Initialiser from a set of points on an Eta-Phi plane, where
+  /// eta can have an arbitrary ranges and phi must be in range
+  /// 0 <= phi < 2pi;
+  /// 
+  /// NB: this class is more efficient than the plain Dnn4piCylinder
+  /// class, but can give wrong answers when the nearest neighbour is
+  /// further away than 2pi (in this case a point's nearest neighbour
+  /// becomes itself, because it is considered to be a distance 2pi
+  /// away). For the kt-algorithm (e.g.) this is actually not a
+  /// problem (the distance need only be accurate when it is less than
+  /// R), so we can tell the routine to ignore this problem --
+  /// alternatively the routine will crash if it detects it occurring
+  /// (only when finding the nearest neighbour index, not its
+  /// distance).
+  Dnn3piCylinder(const std::vector<EtaPhi> &,
+		 const bool & ignore_nearest_is_mirror = false,
+		 const bool & verbose = false );
+
+  /// Returns the index of  the nearest neighbour of point labelled
+  /// by ii (assumes ii is valid)
+  int NearestNeighbourIndex(const int & ii) const ;
+
+  /// Returns the distance to the nearest neighbour of point labelled
+  /// by index ii (assumes ii is valid)
+  double NearestNeighbourDistance(const int & ii) const ;
+
+  /// Returns true iff the given index corresponds to a point that
+  /// exists in the DNN structure (meaning that it has been added, and
+  /// not removed in the meantime)
+  bool Valid(const int & index) const;
+
+  void RemoveAndAddPoints(const std::vector<int> & indices_to_remove,
+			  const std::vector<EtaPhi> & points_to_add,
+			  std::vector<int> & indices_added,
+			  std::vector<int> & indices_of_updated_neighbours);
+
+  ~Dnn3piCylinder();
+
+ private:
+
+  // our extras to help us navigate, find distance, etc.
+  const static int INEXISTENT_VERTEX=-3;
+
+  bool _verbose;
+
+  bool _ignore_nearest_is_mirror;
+
+  /// Picture of how things will work... Copy 0--pi part of the 0--2pi
+  /// cylinder into a region 2pi--3pi of a Euclidean plane. Below we
+  /// show points labelled by + that have a mirror image in this
+  /// manner, while points labelled by * do not have a mirror image.
+  ///      	 			  
+  ///      |           .     |		  
+  ///      |	       .     |		  
+  ///      |           .     |		  
+  ///      |           .     |		  
+  ///      |        2  .     |		  
+  ///      |        *  .     |		  
+  ///      | +         . +   |		  
+  ///      | 0         . 1   |
+  ///      |	       .     |
+  ///      0          2pi   3pi
+  ///   	     
+  /// Each "true" point has its true "cylinder" index (the index that
+  /// is known externally to this class) as well as euclidean plane
+  /// indices (main_index and mirror index in the MirrorVertexInfo
+  /// structure), which are private concepts of this class.
+  /// 
+  /// In above picture our structures would hold the following info
+  /// (the picture shows the euclidean-plane numbering)
+  ///
+  /// _mirror_info[cylinder_index = 0] = (0, 1)
+  /// _mirror_info[cylinder_index = 1] = (2, INEXISTENT_VERTEX)
+  ///
+  /// We also need to be able to go from the euclidean plane indices
+  /// back to the "true" cylinder index, and for this purpose we use
+  /// the vector _cylinder_index_of_plane_vertex[...], which in the above example has
+  /// the following contents
+  ///
+  /// _cylinder_index_of_plane_vertex[0] = 0
+  /// _cylinder_index_of_plane_vertex[1] = 0
+  /// _cylinder_index_of_plane_vertex[2] = 1
+  ///
+
+  /// 
+  struct MirrorVertexInfo {
+    /// index of the given point (appearing in the range 0--2pi) in the 
+    /// 0--3pi euclidean plane structure (position will coincide with
+    /// that on the 0--2pi cylinder, but index labelling it will be
+    /// different)
+    int main_index; 
+    /// index of the mirror point (appearing in the range 2pi--3pi) in the
+    /// 0--3pi euclidean plane structure
+    int mirror_index; 
+  };
+
+  // for each "true" vertex we have reference to indices in the euclidean
+  // plane structure
+  std::vector<MirrorVertexInfo> _mirror_info;
+  // for each index in the euclidean 0--3pi plane structure we want to
+  // be able to get back to the "true" vertex index on the overall
+  // 0--2pi cylinder structure
+  std::vector<int> _cylinder_index_of_plane_vertex;
+
+  // NB: we define POINTERS here because the initialisation gave
+  //     us problems (things crashed!), perhaps because in practice
+  //     we were making a copy without being careful and defining
+  //     a proper copy constructor.
+  DnnPlane * _DNN;
+
+  /// given a phi value in the 0--2pi range return one 
+  /// in the pi--3pi range.
+  inline EtaPhi _remap_phi(const EtaPhi & point) {
+    double phi = point.second;
+    if (phi < pi) { phi += twopi ;}
+    return EtaPhi(point.first, phi);}
+
+
+  //----------------------------------------------------------------------
+  /// What on earth does this do?
+  ///
+  /// Example: last true "cylinder" index was 15
+  ///          last plane index was 23
+  /// 
+  /// Then: _cylinder_index_of_plane_vertex.size() = 24 and 
+  ///       _mirror_info.size() = 16
+  ///
+  /// IF cylinder_point's phi < pi then
+  ///   create:  _mirror_info[16] = (main_index = 24, mirror_index=25) 
+  ///            _cylinder_index_of_plane_vertex[24] = 16
+  ///            _cylinder_index_of_plane_vertex[25] = 16
+  /// ELSE
+  ///  create: _mirror_info[16] = (main_index = 24, mirror_index=INEXISTENT..) 
+  ///          _cylinder_index_of_plane_vertex[24] = 16
+  ///
+  /// ADDITIONALLY push the cylinder_point (and if it exists the mirror
+  /// copy) onto the vector plane_points.
+  void _RegisterCylinderPoint (const EtaPhi & cylinder_point,
+			       std::vector<EtaPhi> & plane_points);
+};
+
+
+// here follow some inline implementations of the simpler of the
+// functions defined above
+
+//----------------------------------------------------------------------
+/// Note: one of the difficulties of the 0--3pi mapping is that
+/// a point may have its mirror copy as its own nearest neighbour
+/// (if no other point is within a distance of 2pi). This does
+/// not matter for the kt_algorithm with
+/// reasonable values of radius, but might matter for a general use
+/// of this algorithm -- depending on whether or not the user has
+/// initialised the class with instructions to ignore this problem the
+/// program will detect and ignore it, or crash.
+inline int Dnn3piCylinder::NearestNeighbourIndex(const int & current) const {
+  int main_index = _mirror_info[current].main_index;
+  int mirror_index = _mirror_info[current].mirror_index;
+  int plane_index;
+  if (mirror_index == INEXISTENT_VERTEX ) {
+    plane_index = _DNN->NearestNeighbourIndex(main_index);
+  } else {
+    plane_index = (
+	_DNN->NearestNeighbourDistance(main_index) < 
+	_DNN->NearestNeighbourDistance(mirror_index)) ? 
+      _DNN->NearestNeighbourIndex(main_index) : 
+      _DNN->NearestNeighbourIndex(mirror_index) ; 
+  }
+  int this_cylinder_index = _cylinder_index_of_plane_vertex[plane_index];
+  // either the user has acknowledged the fact that they may get the
+  // mirror copy as the closest point, or crash if it should occur
+  // that mirror copy is the closest point.
+  assert(_ignore_nearest_is_mirror || this_cylinder_index != current);
+  //if (this_cylinder_index == current) {
+  //  std::cerr << "WARNING point "<<current<<
+  //    " has its mirror copy as its own nearest neighbour"<<endl;
+  //}
+  return this_cylinder_index;
+}
+
+inline double Dnn3piCylinder::NearestNeighbourDistance(const int & current) const {
+  int main_index = _mirror_info[current].main_index;
+  int mirror_index = _mirror_info[current].mirror_index;
+  if (mirror_index == INEXISTENT_VERTEX ) {
+    return _DNN->NearestNeighbourDistance(main_index);
+  } else {
+    return (
+	_DNN->NearestNeighbourDistance(main_index) < 
+	_DNN->NearestNeighbourDistance(mirror_index)) ? 
+      _DNN->NearestNeighbourDistance(main_index) : 
+      _DNN->NearestNeighbourDistance(mirror_index) ; 
+  }
+ 
+}
+
+inline bool Dnn3piCylinder::Valid(const int & index) const {
+  return (_DNN->Valid(_mirror_info[index].main_index));
+}
+
+
+inline Dnn3piCylinder::~Dnn3piCylinder() {
+  delete _DNN; 
+}
+
+
+FASTJET_END_NAMESPACE
+
+#endif //  __FASTJET_DNN3PICYLINDER_HH__
+#endif //  DROP_CGAL 
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/Dnn4piCylinder.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/Dnn4piCylinder.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/Dnn4piCylinder.hh	(revision 5)
@@ -0,0 +1,128 @@
+//STARTHEADER
+// $Id: Dnn4piCylinder.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef DROP_CGAL // in case we do not have the code for CGAL
+#ifndef __FASTJET_DNN4PICYLINDER_HH__
+#define __FASTJET_DNN4PICYLINDER_HH__
+
+#include "fastjet/internal/DynamicNearestNeighbours.hh"
+#include "fastjet/internal/DnnPlane.hh"
+#include "fastjet/internal/numconsts.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+/// \if internal_doc
+/// @ingroup internal
+/// \class Dnn4piCylinder
+/// class derived from DynamicNearestNeighbours that provides an
+/// implementation for the surface of cylinder (using two copies of
+/// DnnPlane, one running from 0--2pi, the other from pi--3pi).
+/// \endif
+class Dnn4piCylinder : public DynamicNearestNeighbours {
+ public:
+  /// empty initaliser
+  Dnn4piCylinder() {}
+
+  /// Initialiser from a set of points on an Eta-Phi plane, where
+  /// eta can have an arbitrary ranges and phi must be in range
+  /// 0 <= phi < 2pi
+  Dnn4piCylinder(const std::vector<EtaPhi> &, const bool & verbose = false );
+
+  /// Returns the index of  the nearest neighbour of point labelled
+  /// by ii (assumes ii is valid)
+  int NearestNeighbourIndex(const int & ii) const ;
+
+  /// Returns the distance to the nearest neighbour of point labelled
+  /// by index ii (assumes ii is valid)
+  double NearestNeighbourDistance(const int & ii) const ;
+
+  /// Returns true iff the given index corresponds to a point that
+  /// exists in the DNN structure (meaning that it has been added, and
+  /// not removed in the meantime)
+  bool Valid(const int & index) const;
+
+  void RemoveAndAddPoints(const std::vector<int> & indices_to_remove,
+			  const std::vector<EtaPhi> & points_to_add,
+			  std::vector<int> & indices_added,
+			  std::vector<int> & indices_of_updated_neighbours);
+
+  ~Dnn4piCylinder();
+
+ private:
+
+  bool _verbose;
+
+  // NB: we define POINTERS here because the initialisation gave
+  //     us problems (things crashed!), perhaps because in practice
+  //     we were making a copy without being careful and defining
+  //     a proper copy constructor.
+  DnnPlane * _DNN1, * _DNN2;
+
+  /// given a phi value in the 0--2pi range return one 
+  /// in the pi--3pi range.
+  inline EtaPhi _remap_phi(const EtaPhi & point) {
+    double phi = point.second;
+    if (phi < pi) { phi += twopi ;}
+    return EtaPhi(point.first, phi);}
+
+};
+
+
+// here follow some inline implementations of the simpler of the
+// functions defined above
+
+inline int Dnn4piCylinder::NearestNeighbourIndex(const int & current) const {
+  return (_DNN1->NearestNeighbourDistance(current) < 
+	  _DNN2->NearestNeighbourDistance(current)) ? 
+    _DNN1->NearestNeighbourIndex(current) : 
+    _DNN2->NearestNeighbourIndex(current) ; 
+}
+
+inline double Dnn4piCylinder::NearestNeighbourDistance(const int & current) const {
+  return (_DNN1->NearestNeighbourDistance(current) < 
+	  _DNN2->NearestNeighbourDistance(current)) ? 
+    _DNN1->NearestNeighbourDistance(current) : 
+    _DNN2->NearestNeighbourDistance(current) ; 
+}
+
+inline bool Dnn4piCylinder::Valid(const int & index) const {
+  return (_DNN1->Valid(index) && _DNN2->Valid(index));
+}
+
+
+inline Dnn4piCylinder::~Dnn4piCylinder() {
+  delete _DNN1; 
+  delete _DNN2;
+}
+
+
+FASTJET_END_NAMESPACE
+
+#endif //  __FASTJET_DNN4PICYLINDER_HH__
+#endif //  DROP_CGAL 
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/DnnPlane.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/DnnPlane.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/DnnPlane.hh	(revision 5)
@@ -0,0 +1,165 @@
+//STARTHEADER
+// $Id: DnnPlane.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef DROP_CGAL // in case we do not have the code for CGAL
+
+#ifndef __FASTJET_DNNPLANE_HH__
+#define __FASTJET_DNNPLANE_HH__
+
+#include "fastjet/internal/Triangulation.hh"
+#include "fastjet/internal/DynamicNearestNeighbours.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+
+/// \if internal_doc
+/// @ingroup internal
+/// \class DnnPlane
+/// class derived from DynamicNearestNeighbours that provides an
+/// implementation for the Euclidean plane
+/// \endif
+class DnnPlane : public DynamicNearestNeighbours {
+ public:
+  /// empty initaliser
+  DnnPlane() {}
+
+  /// Initialiser from a set of points on an Eta-Phi plane, where both
+  /// eta and phi can have arbitrary ranges
+  DnnPlane(const std::vector<EtaPhi> &, const bool & verbose = false );
+
+
+  /// Returns the index of  the nearest neighbour of point labelled
+  /// by ii (assumes ii is valid)
+  int NearestNeighbourIndex(const int & ii) const ;
+
+  /// Returns the distance to the nearest neighbour of point labelled
+  /// by index ii (assumes ii is valid)
+  double NearestNeighbourDistance(const int & ii) const ;
+
+  /// Returns true iff the given index corresponds to a point that
+  /// exists in the DNN structure (meaning that it has been added, and
+  /// not removed in the meantime)
+  bool Valid(const int & index) const;
+
+  void RemoveAndAddPoints(const std::vector<int> & indices_to_remove,
+			  const std::vector<EtaPhi> & points_to_add,
+			  std::vector<int> & indices_added,
+			  std::vector<int> & indices_of_updated_neighbours);
+
+  /// returns the EtaPhi of point with index i.
+  EtaPhi etaphi(const int i) const;
+  /// returns the eta point with index i.
+  double eta(const int i) const;
+  /// returns the phi point with index i.
+  double phi(const int i) const;
+
+ private:
+
+  /// Structure containing a vertex_handle and cached information on
+  /// the nearest neighbour.
+  struct SuperVertex {
+    Vertex_handle vertex; // NULL indicates inexistence...
+    double NNdistance;
+    int NNindex;
+    // later on for cylinder put a second vertex?
+  };
+
+  std::vector<SuperVertex> _supervertex;
+  //set<Vertex_handle> _vertex_set;
+  bool _verbose;
+
+  static const bool _crash_on_coincidence = true;
+  //static const bool _crash_on_coincidence = false;
+
+  Triangulation _TR; /// CGAL object for dealing with triangulations
+
+  /// calculates and returns the euclidean distance between points p1
+  /// and p2
+  inline double _euclid_distance(const Point& p1, const Point& p2) const {
+    double distx= p1.x()-p2.x();
+    double disty= p1.y()-p2.y();
+    return distx*distx+disty*disty;
+  }
+
+  //---------------------------------------------------------------------- 
+  /// Determines the index and distance of the nearest neighbour to 
+  /// point j and puts the information into the _supervertex entry for j
+  void _SetNearest(const int & j);
+
+  //----------------------------------------------------------------------
+  /// Determines and stores the nearest neighbour of j.
+  ///
+  /// For each voronoi neighbour D of j if the distance between j and D
+  /// is less than D's own nearest neighbour, then update the
+  /// nearest-neighbour info in D; push D's index onto 
+  /// indices_of_updated_neighbours
+  ///
+  /// Note that j is NOT pushed onto indices_of_updated_neighbours --
+  /// if you want it there, put it there yourself.
+  void _SetAndUpdateNearest(const int & j, 
+			    std::vector<int> & indices_of_updated_neighbours);
+
+  /// given a vertex_handle returned by CGAL on insertion of a new
+  /// points, crash if it turns out that it corresponds to a vertex
+  /// that we already knew about (usually because two points coincide)
+  void _CrashIfVertexPresent(const Vertex_handle & vertex, 
+			     const int & its_index);
+
+};
+
+
+// here follow some inline implementations of the simpler of the
+// functions defined above
+
+inline int DnnPlane::NearestNeighbourIndex(const int & ii) const {
+  return _supervertex[ii].NNindex;}
+
+inline double DnnPlane::NearestNeighbourDistance(const int & ii) const {
+  return _supervertex[ii].NNdistance;}
+
+inline bool DnnPlane::Valid(const int & index) const {
+  if (index >= 0 && index < static_cast<int>(_supervertex.size())) {
+    return (_supervertex[index].vertex != NULL);} else {return false;} }
+
+inline EtaPhi DnnPlane::etaphi(const int i) const {
+  Point * p = & (_supervertex[i].vertex->point());
+  return EtaPhi(p->x(),p->y()); }
+
+inline double DnnPlane::eta(const int i) const {
+  return _supervertex[i].vertex->point().x(); }
+
+inline double DnnPlane::phi(const int i) const {
+  return _supervertex[i].vertex->point().y(); }
+
+
+FASTJET_END_NAMESPACE
+
+#endif //  __FASTJET_DNNPLANE_HH__
+
+#endif // DROP_CGAL
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/DynamicNearestNeighbours.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/DynamicNearestNeighbours.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/DynamicNearestNeighbours.hh	(revision 5)
@@ -0,0 +1,183 @@
+//STARTHEADER
+// $Id: DynamicNearestNeighbours.hh 2687 2011-11-14 11:17:51Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_DYNAMICNEARESTNEIGHBOURS_HH__
+#define __FASTJET_DYNAMICNEARESTNEIGHBOURS_HH__
+
+#include<vector>
+#include<string>
+#include<iostream>
+#include<sstream>
+#include<cassert>
+#include "fastjet/internal/numconsts.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+/// Shortcut for dealing with eta-phi coordinates.
+//typedef std::pair<double,double> EtaPhi;
+
+/// \if internal_doc
+/// @ingroup internal
+/// \class EtaPhi
+/// use a class instead of a pair so that phi can be sanitized
+/// and put into proper range on initialization.
+/// \endif
+class EtaPhi {
+public:
+  double first, second;
+  EtaPhi() {}
+  EtaPhi(double a, double b) {first = a; second = b;}
+  /// put things into the desired range.
+  void sanitize() {    
+    if (second <  0)     second += twopi; 
+    if (second >= twopi) second -= twopi;
+  }
+
+};
+
+/// \if internal_doc
+/// @ingroup internal
+/// \class DnnError
+/// class corresponding to errors that will be thrown by Dynamic
+/// Nearest Neighbours code
+/// \endif
+class DnnError {
+public:
+  // constructors
+  DnnError() {;};
+  DnnError(const std::string & message_in) {
+    _message = message_in; std::cerr << message_in << std::endl;};
+
+  std::string message() const {return _message;};
+
+private:
+  std::string _message;
+};
+
+
+/// \if internal_doc
+/// @ingroup internal
+/// \class DynamicNearestNeighbours
+/// Abstract base class for quick location of nearest neighbours in a set of
+/// points.
+///
+/// Abstract base class for quick location of nearest neighbours in a set of
+/// points, with facilities for adding and removing points from the
+/// set after initialisation. Derived classes will be
+/// named according to the convention DnnSomeName (e.g. DnnPlane).
+///
+/// The main purpose of this abstract base class is to define the
+/// general interface of a whole set of classes that deal with
+/// nearest-neighbour location on different 2-d geometries and with
+/// various underlying data structures and algorithms.
+///
+/// \endif
+class DynamicNearestNeighbours {
+
+public:
+  /// Dummy initialiser --- does nothing!
+  //virtual DynamicNearestNeighbours() {};
+   
+  /// Initialiser --- sets up the necessary structures to allow efficient
+  /// nearest-neighbour finding on the std::vector<EtaPhi> of input points
+  //virtual DynamicNearestNeighbours(const std::vector<EtaPhi> &, 
+  //				   const bool & verbose = false ) = 0;
+
+  /// Returns the index of the nearest neighbour of point labelled
+  /// by ii (assumes ii is valid)
+  virtual int NearestNeighbourIndex(const int & ii) const = 0;
+
+  /// Returns the distance to the nearest neighbour of point labelled
+  /// by index ii (assumes ii is valid)
+  virtual double NearestNeighbourDistance(const int & ii) const = 0;
+
+  /// Returns true iff the given index corresponds to a point that
+  /// exists in the DNN structure (meaning that it has been added, and
+  /// not removed in the meantime)
+  virtual bool Valid(const int & index) const = 0;
+
+  /// remove the points labelled by the std::vector indices_to_remove, and
+  /// add the points specified by the std::vector points_to_add
+  /// (corresponding indices will be calculated automatically); the
+  /// idea behind this routine is that the points to be added will
+  /// somehow be close to the one or other of the points being removed
+  /// and this can be used by the implementation to provide hints for
+  /// inserting the new points in whatever structure it is using.  In a
+  /// kt-algorithm the points being added will be a result of a
+  /// combination of the points to be removed -- hence the proximity
+  /// is (more or less) guaranteed.
+  virtual void RemoveAndAddPoints(const std::vector<int> & indices_to_remove,
+			  const std::vector<EtaPhi> & points_to_add,
+			  std::vector<int> & indices_added,
+			  std::vector<int> & indices_of_updated_neighbours) = 0;
+
+
+  /// Remove the point labelled by index and return the list of
+  /// points whose nearest neighbours have changed in the process
+  inline void RemovePoint (const int & index,
+			   std::vector<int> & indices_of_updated_neighbours) {
+    std::vector<int> indices_added;
+    std::vector<EtaPhi> points_to_add;
+    std::vector<int> indices_to_remove(1);
+    indices_to_remove[0] = index;
+    RemoveAndAddPoints(indices_to_remove, points_to_add, indices_added,
+		       indices_of_updated_neighbours
+		       );};
+
+
+  /// Removes the two points labelled by index1, index2 and adds in the
+  /// a point with coordinates newpoint; it returns an index for the new 
+  /// point (index 3) and a std::vector of indices of neighbours whose
+  /// nearest neighbour has changed (the list includes index3, i.e. the new
+  /// point).
+  inline void RemoveCombinedAddCombination(
+			const int & index1, const int & index2,
+			const EtaPhi & newpoint,
+			int & index3,
+			std::vector<int> & indices_of_updated_neighbours) {
+    std::vector<int> indices_added(1);
+    std::vector<EtaPhi> points_to_add(1);
+    std::vector<int> indices_to_remove(2);
+    indices_to_remove[0] = index1;
+    indices_to_remove[1] = index2;
+    points_to_add[0] = newpoint;
+    RemoveAndAddPoints(indices_to_remove, points_to_add, indices_added,
+		       indices_of_updated_neighbours
+		       );
+    index3 = indices_added[0];
+  };
+
+  /// destructor -- here it is now implemented
+  virtual ~DynamicNearestNeighbours () {}
+};
+  
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_DYNAMICNEARESTNEIGHBOURS_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/IsBase.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/IsBase.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/IsBase.hh	(revision 5)
@@ -0,0 +1,172 @@
+//STARTHEADER
+// $Id: IsBase.hh 2622 2011-10-05 22:13:23Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_INTERNAL_IS_BASE_HH__
+#define __FASTJET_INTERNAL_IS_BASE_HH__
+
+#include "fastjet/internal/numconsts.hh"
+
+FASTJET_BEGIN_NAMESPACE
+
+//---------------------------------------------------
+// define a true and a false 'type'
+// Note: 
+//  we could actually template the type and recover 
+//  the TR1 integral_constant type. This also 
+//  includes adding a typedef for the type and a
+//  typedef for the struct in the struct below
+//
+// This is going to be helpful to "split" a given 
+// call into 2 options based on a type constraint
+// at compilation-time (rather than doing an "if" 
+// which would only be resolved at runtime and could
+// thus resutl in compilation errors. 
+//---------------------------------------------------
+
+/// \if internal_doc
+/// \class integral_type 
+/// a generic construct that promotes a generic value of a generic type
+/// as a type
+///
+/// this has 2 template parameters: T, the considered type, and _t, a
+/// value of type T
+/// This object is a basic construct in type traits
+/// \endif
+template<typename T, T _t>
+struct integral_type{
+  static const T value = _t;         ///< the value (only member carrying info)
+  typedef T value_type;		     ///< a typedef for the type T
+  typedef integral_type<T,_t> type;  ///< a typedef for the whole structure
+};
+
+// definition of the static member in integral_type
+template<typename T, T _t>
+const T integral_type<T, _t>::value;
+
+// shortcuts
+typedef integral_type<bool, true>  true_type;  ///< the bool 'true'  value promoted to a type
+typedef integral_type<bool, false> false_type; ///< the bool 'false' value promoted to a type
+
+
+//---------------------------------------------------
+// define a yes and a no type (based on their size)
+//---------------------------------------------------
+typedef char (&__yes_type)[1]; //< the yes type
+typedef char (&__no_type) [2]; //< the no type
+
+
+//---------------------------------------------------
+// Now deal with inheritance checks
+//
+// We want to provide a IsBaseAndDerived<B,D> type 
+// trait that contains a value that is true if D
+// is derived from B and false otherwise.
+//
+// For an explanation of how the code below works, 
+// have a look at 
+//   http://groups.google.com/group/comp.lang.c++.moderated/msg/dd6c4e4d5160bd83
+// and the links therein
+//
+// WARNING: according to 'boost', this may have some
+//   issues with MSVC7.1. See their code for a description
+//   of the workaround used below
+//---------------------------------------------------
+
+/// \if internal_doc
+/// \class __inheritance_helper
+/// helper for IsBasedAndDerived<B,D>
+/// \endif
+template<typename B, typename D>
+struct __inheritance_helper{
+#if !((_MSC_VER !=0 ) && (_MSC_VER == 1310))   // MSVC 7.1
+  template <typename T>
+  static __yes_type check_sig(D const volatile *, T);
+#else
+  static __yes_type check_sig(D const volatile *, long);
+#endif
+  static __no_type  check_sig(B const volatile *, int);
+};
+
+/// \if internal_doc
+/// \class IsBaseAndDerived
+/// check if the second template argument is derived from the first one
+/// 
+/// this class has 2 template dependencies: B and D. It contains a
+/// static boolean value that will be true if D is derived from B and
+/// false otherwise.
+///
+/// Note: This construct may have a problem with MSVC7.1. See the
+/// boost implementation for a description and workaround
+/// \endif
+template<typename B, typename D>
+struct IsBaseAndDerived{
+#if ((_MSC_FULL_VER != 0) && (_MSC_FULL_VER >= 140050000))
+#pragma warning(push)
+#pragma warning(disable:6334)
+#endif
+
+
+  /// \if internal_doc
+  /// a helper structure that will pick between a casting to B*const
+  /// or D.
+  ///
+  /// precisely how this structure works involves advanced C++
+  /// conversion rules
+  /// \endif
+  struct Host{
+#if !((_MSC_VER !=0 ) && (_MSC_VER == 1310))
+    operator B const volatile *() const;
+#else
+    operator B const volatile * const&() const;
+#endif
+    operator D const volatile *();
+  };
+
+  /// the boolean value being true if D is derived from B
+  static const bool value = ((sizeof(B)!=0) && 
+			     (sizeof(D)!=0) && 
+			     (sizeof(__inheritance_helper<B,D>::check_sig(Host(), 0)) == sizeof(__yes_type)));
+
+#if ((_MSC_FULL_VER != 0) && (_MSC_FULL_VER >= 140050000))
+#pragma warning(pop)
+#endif
+};
+
+
+/// a little helper that returns a pointer to d of type B* if D is
+/// derived from B and NULL otherwise
+template<class B, class D>
+B* cast_if_derived(D* d){
+  return IsBaseAndDerived<B,D>::value ? (B*)(d) : NULL;
+}
+
+
+FASTJET_END_NAMESPACE
+
+
+#endif  // __IS_BASE_OF_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/LimitedWarning.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/LimitedWarning.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/LimitedWarning.hh	(revision 5)
@@ -0,0 +1,42 @@
+#ifndef __FASTJET_INTERNALLIMITEDWARNING_HH__
+#define __FASTJET_INTERNALLIMITEDWARNING_HH__
+
+//STARTHEADER
+// $Id: LimitedWarning.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+
+// we have moved LimitedWarning.hh one directory up; still allow
+// old form of access
+#include "fastjet/LimitedWarning.hh"
+
+#warning *** You have included fastjet/internal/LimitedWarning.hh. \
+Access to LimitedWarning through this header is deprecated as of FJ3.0. \
+Please instead use fastjet/LimitedWarning.hh
+
+#endif // __FASTJET_INTERNALLIMITEDWARNING_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/MinHeap.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/MinHeap.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/MinHeap.hh	(revision 5)
@@ -0,0 +1,92 @@
+//STARTHEADER
+// $Id: MinHeap.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_MINHEAP__HH__
+#define __FASTJET_MINHEAP__HH__
+
+#include<vector>
+#include<cassert>
+#include<memory>
+#include<limits>
+#include "fastjet/internal/base.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//======================================================================
+/// \if internal_doc
+/// @ingroup internal
+/// \class MinHeap
+/// A class which provides a "heap"-like structure that allows
+/// access to a the minimal value of a dynamically changing set of numbers
+/// \endif
+class MinHeap {
+public:
+  /// construct a MinHeap from the vector of values, allowing future
+  /// expansion to a maximum size max_size;
+  MinHeap (const std::vector<double> & values, unsigned int max_size) :
+    _heap(max_size) {_initialise(values);};
+
+  /// constructor in which the the maximum size is the size of the values array
+  MinHeap (const std::vector<double> & values) :
+    _heap(values.size()) {_initialise(values);};
+  
+  /// return the location of the minimal value on the heap
+  inline unsigned int minloc() const {
+    return (_heap[0].minloc) - &(_heap[0]);};
+  
+  /// return the minimal value on the heap
+  inline double       minval() const {return _heap[0].minloc->value;};
+
+  inline double operator[](int i) const {return _heap[i].value;};
+
+  /// remove the value at the specified location (i.e. replace it with
+  /// the largest possible value).
+  void remove(unsigned int loc) {
+    update(loc,std::numeric_limits<double>::max());};
+
+  /// update the value at the specified location
+  void update(unsigned int, double);
+
+private:
+
+  struct ValueLoc{
+    double value;
+    ValueLoc * minloc;
+  };
+      
+  std::vector<ValueLoc> _heap;
+
+  void _initialise(const std::vector<double> & values);
+
+
+};
+
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_MINHEAP__HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/SearchTree.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/SearchTree.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/SearchTree.hh	(revision 5)
@@ -0,0 +1,770 @@
+//STARTHEADER
+// $Id: SearchTree.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_SEARCHTREE_HH__
+#define __FASTJET_SEARCHTREE_HH__
+
+#include<vector>
+#include<cassert>
+#include<cstddef>
+#include "fastjet/internal/base.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+
+//======================================================================
+/// \if internal_doc
+/// @ingroup internal
+/// \class SearchTree
+/// Efficient class for a search tree
+///
+/// This is the class for a search tree designed to be especially efficient
+/// when looking for successors and predecessors (to be used in Chan's
+/// CP algorithm). It has the requirement that the maximum size of the
+/// search tree must be known in advance.
+/// \endif
+template<class T> class SearchTree {
+public:
+
+  class Node;
+  class circulator;
+  class const_circulator;
+
+  /// constructor for a search tree from an ordered vector
+  SearchTree(const std::vector<T> & init);
+
+  /// constructor for a search tree from an ordered vector allowing
+  /// for future growth beyond the current size, up to max_size
+  SearchTree(const std::vector<T> & init, unsigned int max_size);
+
+  /// remove the node corresponding to node_index from the search tree
+  void remove(unsigned node_index);
+  void remove(typename SearchTree::Node * node);
+  void remove(typename SearchTree::circulator & circ);
+
+  /// insert the supplied value into the tree and return a pointer to
+  /// the relevant SearchTreeNode.
+  //Node * insert(const T & value);
+  circulator insert(const T & value);
+
+  const Node & operator[](int i) const {return _nodes[i];};
+
+  /// return the number of elements currently in the search tree
+  unsigned int size() const {return _nodes.size() - _available_nodes.size();}
+
+  /// check that the structure we've obtained makes sense...
+  void verify_structure();
+  void verify_structure_linear() const;
+  void verify_structure_recursive(const Node * , const Node * , const Node * ) const;
+
+  /// print out all elements...
+  void print_elements();
+
+  // tracking the depth may have some speed overhead -- so leave it 
+  // out for the time being...
+#ifdef TRACK_DEPTH
+  /// the max depth the tree has ever reached
+  inline unsigned int max_depth() const {return _max_depth;};
+#else
+  inline unsigned int max_depth() const {return 0;};
+#endif
+
+  int loc(const Node * node) const ;
+
+  /// return predecessor by walking through the tree
+  Node * _find_predecessor(const Node *);
+  /// return successor by walking through the tree
+  Node * _find_successor(const Node *);
+
+  const Node & operator[](unsigned int i) const {return _nodes[i];};
+
+  /// return a circulator to some place in the tree (with a circulator
+  /// you don't care where...)
+  const_circulator somewhere() const;
+  circulator somewhere();
+
+private:
+  
+  void _initialize(const std::vector<T> & init);
+
+  std::vector<Node> _nodes;
+  std::vector<Node *> _available_nodes;
+  Node * _top_node;
+  unsigned int _n_removes;
+
+  
+  /// recursive routine for doing the initial connections assuming things
+  /// are ordered. Assumes this_one's parent is labelled, and was
+  /// generated at a scale "scale" -- connections will be carried out
+  /// including left edge and excluding right edge
+  void _do_initial_connections(unsigned int this_one, unsigned int scale,
+			       unsigned int left_edge, unsigned int right_edge,
+			       unsigned int depth);
+
+  
+#ifdef TRACK_DEPTH
+  unsigned int _max_depth;
+#endif
+
+};
+
+
+//======================================================================
+/// \if internal_doc
+/// @ingroup internal
+/// \class SearchTree::Node
+/// A node in the search tree
+/// \endif
+template<class T> class SearchTree<T>::Node{
+public:
+  Node() {}; /// default constructor
+  
+  
+  /// returns tree if all the tree-related links are set to null for this node
+  bool treelinks_null() const {
+    return ((parent==0) && (left==0) && (right==0));};
+  
+  /// set all the tree-related links are set to null for this node
+  inline void nullify_treelinks() {
+    parent = NULL; 
+    left   = NULL; 
+    right  = NULL;
+  };
+  
+  /// if my parent exists, determine whether I am it's left or right
+  /// node and set the relevant link equal to XX.
+  void reset_parents_link_to_me(Node * XX);
+  
+  T      value;
+  Node * left;
+  Node * right;
+  Node * parent;
+  Node * successor;
+  Node * predecessor;
+};
+
+//----------------------------------------------------------------------
+template<class T> void SearchTree<T>::Node::reset_parents_link_to_me(typename SearchTree<T>::Node * XX) {
+  if (parent == NULL) {return;}
+  if (parent->right == this) {parent->right = XX;}
+  else {parent->left = XX;}
+}
+
+
+
+//======================================================================
+/// \if internal_doc
+/// @ingroup internal
+/// \class SearchTree::circulator
+/// circulator for the search tree
+/// \endif
+template<class T> class SearchTree<T>::circulator{
+public:
+
+  // so that it can access out _node object;
+  friend class SearchTree<T>::const_circulator;
+  friend class SearchTree<T>;
+
+  circulator() : _node(NULL) {}
+
+  circulator(Node * node) : _node(node) {}
+
+  const T * operator->() const {return &(_node->value);}
+  T * operator->() {return &(_node->value);}
+  const T & operator*() const {return _node->value;}
+  T & operator*() {return _node->value;}
+
+  /// prefix increment (structure copied from stl_bvector.h)
+  circulator & operator++() {
+    _node = _node->successor; 
+    return *this;}
+
+  /// postfix increment ["int" argument tells compiler it's postfix]
+  /// (structure copied from stl_bvector.h)
+  circulator operator++(int) {
+    circulator tmp = *this;
+    _node = _node->successor; 
+    return tmp;}
+
+  /// prefix decrement (structure copied from stl_bvector.h)
+  circulator & operator--() {
+    _node = _node->predecessor; 
+    return *this;}
+
+  /// postfix decrement ["int" argument tells compiler it's postfix]
+  /// (structure copied from stl_bvector.h)
+  circulator operator--(int) {
+    circulator tmp = *this;
+    _node = _node->predecessor; 
+    return tmp;}
+
+  /// return a circulator referring to the next node
+  circulator next() const {
+    return circulator(_node->successor);}
+
+  /// return a circulator referring to the previous node
+  circulator previous() const {
+    return circulator(_node->predecessor);}
+
+  bool operator!=(const circulator & other) const {return other._node != _node;}
+  bool operator==(const circulator & other) const {return other._node == _node;}
+
+private:
+  Node * _node;
+};
+
+
+//======================================================================
+/// \if internal_doc
+/// @ingroup internal
+/// \class SearchTree::const_circulator
+/// A const_circulator for the search tree
+/// \endif
+template<class T> class SearchTree<T>::const_circulator{
+public:
+
+  const_circulator() : _node(NULL) {}
+
+  const_circulator(const Node * node) : _node(node) {}
+  const_circulator(const circulator & circ) :_node(circ._node) {}
+
+  const T * operator->() {return &(_node->value);}
+  const T & operator*() const {return _node->value;}
+
+  /// prefix increment (structure copied from stl_bvector.h)
+  const_circulator & operator++() {
+    _node = _node->successor; 
+    return *this;}
+
+  /// postfix increment ["int" argument tells compiler it's postfix]
+  /// (structure copied from stl_bvector.h)
+  const_circulator operator++(int) {
+    const_circulator tmp = *this;
+    _node = _node->successor; 
+    return tmp;}
+
+
+  /// prefix decrement (structure copied from stl_bvector.h)
+  const_circulator & operator--() {
+    _node = _node->predecessor; 
+    return *this;}
+
+  /// postfix decrement ["int" argument tells compiler it's postfix]
+  /// (structure copied from stl_bvector.h)
+  const_circulator operator--(int) {
+    const_circulator tmp = *this;
+    _node = _node->predecessor; 
+    return tmp;}
+
+  /// return a circulator referring to the next node
+  const_circulator next() const {
+    return const_circulator(_node->successor);}
+
+  /// return a circulator referring to the previous node
+  const_circulator previous() const {
+    return const_circulator(_node->predecessor);}
+
+
+
+  bool operator!=(const const_circulator & other) const {return other._node != _node;}
+  bool operator==(const const_circulator & other) const {return other._node == _node;}
+
+private:
+  const Node * _node;
+};
+
+
+
+
+//----------------------------------------------------------------------
+/// initialise from a sorted initial array allowing for a larger
+/// maximum size of the array...
+template<class T> SearchTree<T>::SearchTree(const std::vector<T> & init,
+					    unsigned int max_size) :
+  _nodes(max_size) {
+
+  _available_nodes.reserve(max_size);
+  _available_nodes.resize(max_size - init.size());
+  for (unsigned int i = init.size(); i < max_size; i++) {
+    _available_nodes[i-init.size()] = &(_nodes[i]);
+  }
+
+  _initialize(init);
+}
+
+//----------------------------------------------------------------------
+/// initialise from a sorted initial array
+template<class T> SearchTree<T>::SearchTree(const std::vector<T> & init) :
+  _nodes(init.size()), _available_nodes(0) {
+
+  // reserve space for the list of available nodes
+  _available_nodes.reserve(init.size());
+  _initialize(init);
+}
+
+//----------------------------------------------------------------------
+/// do the actual hard work of initialization
+template<class T> void SearchTree<T>::_initialize(const std::vector<T> & init) {
+
+  _n_removes = 0;
+  unsigned n = init.size();
+  assert(n>=1);
+
+  // reserve space for the list of available nodes
+  //_available_nodes.reserve();
+
+#ifdef TRACK_DEPTH
+  _max_depth     = 0;
+#endif
+
+
+  // validate the input
+  for (unsigned int i = 1; i<n; i++) {
+    assert(!(init[i] < init[i-1]));
+  }
+  
+  // now initialise the vector; link neighbours in the sequence
+  for(unsigned int i = 0; i < n; i++) {
+    _nodes[i].value = init[i];
+    _nodes[i].predecessor = (& (_nodes[i])) - 1;
+    _nodes[i].successor   = (& (_nodes[i])) + 1;
+    _nodes[i].nullify_treelinks();
+  }
+  // make a loop structure so that we can circulate...
+  _nodes[0].predecessor = (& (_nodes[n-1]));
+  _nodes[n-1].successor = (& (_nodes[0]));
+
+  // now label the rest of the nodes
+  unsigned int scale = (n+1)/2;
+  unsigned int top   = std::min(n-1,scale);
+  _nodes[top].parent = NULL;
+  _top_node = &(_nodes[top]);
+  _do_initial_connections(top, scale, 0, n, 0);
+
+  // make sure things are sensible...
+  //verify_structure();
+}
+
+
+
+//----------------------------------------------------------------------
+template<class T> inline  int SearchTree<T>::loc(const Node * node) const {return node == NULL? 
+      -999 : node - &(_nodes[0]);}
+
+
+//----------------------------------------------------------------------
+/// Recursive creation of connections, assuming the _nodes vector is
+/// completely filled and ordered
+template<class T> void SearchTree<T>::_do_initial_connections(
+                                         unsigned int this_one, 
+					 unsigned int scale,
+					 unsigned int left_edge,
+					 unsigned int right_edge,
+					 unsigned int depth
+					 ) {
+
+#ifdef TRACK_DEPTH
+  // keep track of tree depth for checking things stay reasonable...
+  _max_depth = max(depth, _max_depth);
+#endif
+
+  //std::cout << this_one << " "<< scale<< std::endl;
+  unsigned int ref_new_scale = (scale+1)/2;
+
+  // work through children to our left
+  unsigned new_scale = ref_new_scale;
+  bool     did_child  = false;
+  while(true) {
+    int left = this_one - new_scale; // be careful here to use signed int...
+    // if there is something unitialised to our left, link to it
+    if (left >= static_cast<int>(left_edge) 
+	                && _nodes[left].treelinks_null() ) {
+      _nodes[left].parent = &(_nodes[this_one]);
+      _nodes[this_one].left = &(_nodes[left]);
+      // create connections between left_edge and this_one
+      _do_initial_connections(left, new_scale, left_edge, this_one, depth+1);
+      did_child = true;
+      break;
+    }
+    // reduce the scale so as to try again
+    unsigned int old_new_scale = new_scale;
+    new_scale = (old_new_scale + 1)/2;
+    // unless we've reached end of tree
+    if (new_scale == old_new_scale) break;
+  }
+  if (!did_child) {_nodes[this_one].left = NULL;}
+
+
+  // work through children to our right
+  new_scale = ref_new_scale;
+  did_child  = false;
+  while(true) {
+    unsigned int right = this_one + new_scale;
+    if (right < right_edge  && _nodes[right].treelinks_null()) {
+      _nodes[right].parent = &(_nodes[this_one]);
+      _nodes[this_one].right = &(_nodes[right]);
+      // create connections between this_one+1 and right_edge
+      _do_initial_connections(right, new_scale, this_one+1,right_edge,depth+1);
+      did_child = true;
+      break;
+    }
+    // reduce the scale so as to try again
+    unsigned int old_new_scale = new_scale;
+    new_scale = (old_new_scale + 1)/2;
+    // unless we've reached end of tree
+    if (new_scale == old_new_scale) break;
+  }
+  if (!did_child) {_nodes[this_one].right = NULL;}
+
+}
+
+
+
+//----------------------------------------------------------------------
+template<class T> void SearchTree<T>::remove(unsigned int node_index) {
+  remove(&(_nodes[node_index]));
+}
+
+//----------------------------------------------------------------------
+template<class T> void SearchTree<T>::remove(circulator & circ) {
+  remove(circ._node);
+}
+
+//----------------------------------------------------------------------
+// Useful reference for this:
+//   http://en.wikipedia.org/wiki/Binary_search_tree#Deletion
+template<class T> void SearchTree<T>::remove(typename SearchTree<T>::Node * node) {
+
+  // we don't remove things from the tree if we've reached the last
+  // elements... (is this wise?)
+  assert(size() > 1); // switch this to throw...?
+  assert(!node->treelinks_null());
+
+  // deal with relinking predecessor and successor
+  node->predecessor->successor = node->successor;
+  node->successor->predecessor = node->predecessor;
+
+  if (node->left == NULL && node->right == NULL) {
+    // node has no children, so remove it by nullifying the pointer 
+    // from the parent
+    node->reset_parents_link_to_me(NULL); 
+
+  } else if (node->left != NULL && node->right == NULL){
+    // make parent point to my child
+    node->reset_parents_link_to_me(node->left);
+    // and child to parent
+    node->left->parent = node->parent;         
+    // sort out the top node...
+    if (_top_node == node) {_top_node = node->left;}
+
+  } else if (node->left == NULL && node->right != NULL){
+    // make parent point to my child
+    node->reset_parents_link_to_me(node->right);
+    // and child to parent
+    node->right->parent = node->parent;   
+    // sort out the top node...
+    if (_top_node == node) {_top_node = node->right;}
+
+  } else {
+    // we have two children; we will put a replacement in our place
+    Node * replacement;
+    //SearchTree<T>::Node * replacements_child;
+    // chose predecessor or successor (one, then other, then first, etc...)
+    bool use_predecessor = (_n_removes % 2 == 1);
+    if (use_predecessor) {
+      // Option 1: put predecessor in our place, and have its parent
+      // point to its left child (as a predecessor it has no right child)
+      replacement = node->predecessor;
+      assert(replacement->right == NULL); // guaranteed if it's our predecessor
+      // we have to be careful of replacing certain links when the 
+      // replacement is this node's child
+      if (replacement != node->left) {
+	if (replacement->left != NULL) {
+	  replacement->left->parent = replacement->parent;}
+	replacement->reset_parents_link_to_me(replacement->left);
+	replacement->left   = node->left;
+      }
+      replacement->parent = node->parent;
+      replacement->right  = node->right;
+    } else {
+      // Option 2: put successor in our place, and have its parent
+      // point to its right child (as a successor it has no left child)
+      replacement = node->successor;
+      assert(replacement->left == NULL); // guaranteed if it's our successor
+      if (replacement != node->right) {
+	if (replacement->right != NULL) {
+	  replacement->right->parent = replacement->parent;}
+	replacement->reset_parents_link_to_me(replacement->right);
+	replacement->right  = node->right;
+      }
+      replacement->parent = node->parent;
+      replacement->left   = node->left;
+    }
+    node->reset_parents_link_to_me(replacement);
+
+    // make sure node's original children now point to the replacement
+    if (node->left  != replacement) {node->left->parent  = replacement;}
+    if (node->right != replacement) {node->right->parent = replacement;}
+
+    // sort out the top node...
+    if (_top_node == node) {_top_node = replacement;}
+  }
+
+  // make sure we leave something nice and clean...
+  node->nullify_treelinks();
+  node->predecessor = NULL;
+  node->successor   = NULL;
+
+  // for bookkeeping (and choosing whether to use pred. or succ.)
+  _n_removes++;
+  // for when we next need access to a free node...
+  _available_nodes.push_back(node);
+}
+
+
+//----------------------------------------------------------------------
+//template<class T> typename SearchTree<T>::Node * SearchTree<T>::insert(const T & value) {
+
+//----------------------------------------------------------------------
+template<class T> typename SearchTree<T>::circulator SearchTree<T>::insert(const T & value) {
+  // make sure we don't exceed allowed number of nodes...
+  assert(_available_nodes.size() > 0);
+
+  Node * node = _available_nodes.back();
+  _available_nodes.pop_back();
+  node->value = value;
+
+  Node * location = _top_node;
+  Node * old_location = NULL;
+  bool             on_left = true; // (init not needed -- but soothes g++4)
+  // work through tree until we reach its end
+#ifdef TRACK_DEPTH
+  unsigned int depth = 0;
+#endif
+  while(location != NULL) {
+#ifdef TRACK_DEPTH
+    depth++;
+#endif
+    old_location = location;
+    on_left = value < location->value;
+    if (on_left) {location = location->left;}
+    else {location = location->right;}
+  }
+#ifdef TRACK_DEPTH
+  _max_depth = max(depth, _max_depth);
+#endif
+  // now create tree links
+  node->parent = old_location;
+  if (on_left) {node->parent->left = node;} 
+  else {node->parent->right = node;}
+  node->left = NULL;
+  node->right = NULL;
+  // and create predecessor / successor links
+  node->predecessor = _find_predecessor(node);
+  if (node->predecessor != NULL) {
+    // it exists, so make use of its info (will include a cyclic case,
+    // when successor is round the bend)
+    node->successor = node->predecessor->successor;
+    node->predecessor->successor = node;
+    node->successor->predecessor = node;
+  } else {
+    // deal with case when we are left-most edge of tree (then successor
+    // will exist...)
+    node->successor = _find_successor(node);
+    assert(node->successor != NULL); // can only happen if we're sole element 
+                                     // (but not allowed, since tree size>=1)
+    node->predecessor = node->successor->predecessor;
+    node->successor->predecessor = node;
+    node->predecessor->successor = node;
+  }
+
+  return circulator(node);
+}
+
+
+//----------------------------------------------------------------------
+template<class T> void SearchTree<T>::verify_structure() {
+  
+  // do a check running through all elements
+  verify_structure_linear();
+
+  // do a recursive check down tree from top
+
+  // first establish the extremities
+  const Node * left_limit = _top_node;
+  while (left_limit->left != NULL) {left_limit = left_limit->left;}
+  const Node * right_limit = _top_node;
+  while (right_limit->right != NULL) {right_limit = right_limit->right;}
+
+  // then actually do recursion
+  verify_structure_recursive(_top_node, left_limit, right_limit);
+}
+
+
+//----------------------------------------------------------------------
+template<class T> void SearchTree<T>::verify_structure_recursive(
+		      const typename SearchTree<T>::Node * element, 
+		      const typename SearchTree<T>::Node * left_limit,
+		      const typename SearchTree<T>::Node * right_limit)  const {
+
+  assert(!(element->value < left_limit->value));
+  assert(!(right_limit->value < element->value));
+
+  const Node * left = element->left;
+  if (left != NULL) {
+    assert(!(element->value < left->value));
+    if (left != left_limit) {
+      // recurse down the tree with this element as the right-hand limit
+      verify_structure_recursive(left, left_limit, element);}
+  }
+  
+  const Node * right = element->right;
+  if (right != NULL) {
+    assert(!(right->value < element->value));
+    if (right != right_limit) {
+      // recurse down the tree with this element as the left-hand limit
+      verify_structure_recursive(right, element, right_limit);}
+  }
+}
+
+//----------------------------------------------------------------------
+template<class T> void SearchTree<T>::verify_structure_linear() const {
+
+  //print_elements();
+
+  unsigned n_top = 0;
+  unsigned n_null = 0;
+  for(unsigned i = 0; i < _nodes.size(); i++) {
+    const typename SearchTree<T>::Node * node = &(_nodes[i]);
+    // make sure node is defined
+    if (node->treelinks_null()) {n_null++; continue;}
+
+    // make sure of the number of "top" nodes 
+    if (node->parent == NULL) {
+      n_top++;
+      //assert(node->left != NULL);
+      //assert(node->right != NULL);
+    } else {
+      // make sure that I am a child of my parent...
+      //assert((node->parent->left == node) || (node->parent->right == node));
+      assert((node->parent->left == node) ^ (node->parent->right == node));
+    }
+
+    // when there is a left child make sure it's value is ordered
+    // (note use of !(b<a), to allow for a<=b while using just the <
+    // operator)
+    if (node->left != NULL) {
+      assert(!(node->value < node->left->value ));}
+
+    // when there is a right child make sure it's value is ordered
+    if (node->right != NULL) {
+      assert(!(node->right->value < node->value ));}
+
+  }
+  assert(n_top == 1 || (n_top == 0 && size() <= 1) );
+  assert(n_null == _available_nodes.size() ||
+	 (n_null == _available_nodes.size() + 1 && size() == 1));
+}
+
+
+//----------------------------------------------------------------------
+template<class T> typename SearchTree<T>::Node * SearchTree<T>::_find_predecessor(const typename SearchTree<T>::Node * node) {
+
+  typename SearchTree<T>::Node * newnode;
+  if (node->left != NULL) {
+    // go down left, and then down right as far as possible.
+    newnode = node->left;
+    while(newnode->right != NULL) {newnode = newnode->right;}
+    return newnode;
+  } else {
+    const typename SearchTree<T>::Node * lastnode = node;
+    newnode = node->parent;
+    // go up the tree as long as we're going right (when we go left then
+    // we've found something smaller, so stop)
+    while(newnode != NULL) {
+      if (newnode->right == lastnode) {return newnode;}
+      lastnode = newnode;
+      newnode = newnode->parent;
+    }
+    return newnode;
+  }
+}
+
+
+//----------------------------------------------------------------------
+template<class T> typename SearchTree<T>::Node * SearchTree<T>::_find_successor(const typename SearchTree<T>::Node * node) {
+
+  typename SearchTree<T>::Node * newnode;
+  if (node->right != NULL) {
+    // go down right, and then down left as far as possible.
+    newnode = node->right;
+    while(newnode->left != NULL) {newnode = newnode->left;}
+    return newnode;
+  } else {
+    const typename SearchTree<T>::Node * lastnode = node;
+    newnode = node->parent;
+    // go up the tree as long as we're going left (when we go right then
+    // we've found something larger, so stop)
+    while(newnode != NULL) {
+      if (newnode->left == lastnode) {return newnode;}
+      lastnode = newnode;
+      newnode = newnode->parent;
+    }
+    return newnode;
+  }
+}
+
+
+//----------------------------------------------------------------------
+// print out all the elements for visual checking...
+template<class T> void SearchTree<T>::print_elements() {
+  typename SearchTree<T>::Node * base_node = &(_nodes[0]);
+  typename SearchTree<T>::Node * node = base_node;
+  
+  int n = _nodes.size();
+  for(; node - base_node < n ; node++) {
+    printf("%4d parent:%4d left:%4d right:%4d pred:%4d succ:%4d value:%10.6f\n",loc(node), loc(node->parent), loc(node->left), loc(node->right), loc(node->predecessor),loc(node->successor),node->value);
+  }
+}
+
+//----------------------------------------------------------------------
+template<class T> typename SearchTree<T>::circulator SearchTree<T>::somewhere() {
+  return circulator(_top_node);
+}
+
+
+//----------------------------------------------------------------------
+template<class T> typename SearchTree<T>::const_circulator SearchTree<T>::somewhere() const {
+  return const_circulator(_top_node);
+}
+
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_SEARCHTREE_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/Triangulation.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/Triangulation.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/Triangulation.hh	(revision 5)
@@ -0,0 +1,106 @@
+#ifndef DROP_CGAL // in case we do not have the code for CGAL
+#ifndef __FASTJET_TRIANGULATION__
+#define __FASTJET_TRIANGULATION__
+
+//STARTHEADER
+// $Id: Triangulation.hh 2595 2011-09-23 09:05:04Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+// file: examples/Triangulation_2/Voronoi.C
+#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
+#include <CGAL/Delaunay_triangulation_2.h>
+#include <CGAL/Triangulation_hierarchy_2.h>
+#include <CGAL/Triangulation_vertex_base_with_info_2.h>
+#include "fastjet/internal/base.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+/// \if internal_doc
+/// @ingroup internal
+/// \struct K
+/// the basic geometrical kernel that lies at the base of all CGAL
+/// operations
+/// \endif
+#ifdef CGAL_SIMPLE_KERNEL
+struct K : CGAL::Simple_cartesian<double> {};
+#else
+struct K : CGAL::Exact_predicates_inexact_constructions_kernel {};
+#endif // CGAL_SIMPLE_KERNEL
+
+// our extras to help us navigate, find distance, etc.
+const int INFINITE_VERTEX=-1;
+const int NEW_VERTEX=-2;
+const double HUGE_DOUBLE=1e300;
+
+/// \if internal_doc
+/// @ingroup internal
+/// \struct InitialisedInt
+/// A class to provide an "int" with an initial value.
+/// \endif
+class InitialisedInt {
+ private:
+  int _val;
+ public:
+  inline InitialisedInt () {_val=NEW_VERTEX;};
+  inline InitialisedInt& operator= (int value) {_val = value; return *this;};
+  inline int val() const {return _val;};
+};
+
+
+// We can have triangulations with and without hierarchies -- those with 
+// are able to guarantee N ln N time for the construction of a large
+// triangulation, whereas those without go as N^{3/2} for points
+// sufficiently uniformly distributed in a plane.
+//
+//#define NOHIERARCHY
+#ifdef NOHIERARCHY
+typedef CGAL::Triangulation_vertex_base_with_info_2<InitialisedInt,K> Vb;
+typedef CGAL::Triangulation_face_base_2<K> Fb;
+typedef CGAL::Triangulation_data_structure_2<Vb,Fb> Tds;
+typedef CGAL::Delaunay_triangulation_2<K,Tds>  Triangulation;
+#else
+typedef CGAL::Triangulation_vertex_base_with_info_2<InitialisedInt,K> Vbb;
+typedef CGAL::Triangulation_hierarchy_vertex_base_2<Vbb> Vb;
+typedef CGAL::Triangulation_face_base_2<K> Fb;
+typedef CGAL::Triangulation_data_structure_2<Vb,Fb> Tds;
+typedef CGAL::Delaunay_triangulation_2<K,Tds>  Dt;
+typedef CGAL::Triangulation_hierarchy_2<Dt> Triangulation;
+#endif
+
+typedef Triangulation::Vertex_handle  Vertex_handle;
+typedef Triangulation::Point          Point; /// CGAL Point structure
+typedef Triangulation::Vertex_circulator Vertex_circulator;
+typedef Triangulation::Face_circulator Face_circulator;
+typedef Triangulation::Face_handle Face_handle;
+
+
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_TRIANGULATION__
+#endif //  DROP_CGAL 
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/Voronoi.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/Voronoi.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/Voronoi.hh	(revision 5)
@@ -0,0 +1,386 @@
+#ifndef __FASTJET__VORONOI_H__
+#define __FASTJET__VORONOI_H__
+
+//STARTHEADER
+// $Id: Voronoi.hh 2686 2011-11-14 09:28:22Z soyez $
+//
+// Copyright (c) 1994 by AT&T Bell Laboratories (see below)
+//
+//
+//----------------------------------------------------------------------
+// This file is included as part of FastJet but was mostly written by
+// S. Fortune in C, put into C++ with memory management by S
+// O'Sullivan, and with further interface and memeory management
+// modifications by Gregory Soyez.
+//
+// Permission to use, copy, modify, and distribute this software for
+// any purpose without fee is hereby granted, provided that this
+// entire notice is included in all copies of any software which is or
+// includes a copy or modification of this software and in all copies
+// of the supporting documentation for such software. THIS SOFTWARE IS
+// BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTY.
+// IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY REPRESENTATION
+// OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS
+// SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+//
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+/*
+* The author of this software is Steven Fortune.  
+* Copyright (c) 1994 by AT&T Bell Laboratories.
+* Permission to use, copy, modify, and distribute this software for any
+* purpose without fee is hereby granted, provided that this entire notice
+* is included in all copies of any software which is or includes a copy
+* or modification of this software and in all copies of the supporting
+* documentation for such software.
+* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY
+* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+*/
+
+/* 
+* This code was originally written by Stephan Fortune in C code.  I,
+* Shane O'Sullivan, have since modified it, encapsulating it in a C++
+* class and, fixing memory leaks and adding accessors to the Voronoi
+* Edges.  Permission to use, copy, modify, and distribute this
+* software for any purpose without fee is hereby granted, provided
+* that this entire notice is included in all copies of any software
+* which is or includes a copy or modification of this software and in
+* all copies of the supporting documentation for such software.  THIS
+* SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY
+* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
+* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+* PURPOSE.
+*/
+
+/*
+ * This code, included in the FastJet distribution, was originally
+ * written by Stephan Fortune in C and adapted to C++ by Shane
+ * O'Sullivan under the terms repported above.
+ *
+ * Below are the list of changes implemented by the FastJet authors:
+ *
+ * 2011-11-14  Gregory Soyez  <soyez@fastjet.fr>
+ * 
+ *      * removed 'plot' and 'triangulate' (were always 0)
+ *      * removed unused plot functions (openpl, circle, range, 
+ *        out_bisector, out_ep, out_vertex, out_site, out_triple)
+ *      * removed unused 'VPoint p' in 'intersect'
+ * 
+ * 
+ * 2011-07-22  Gregory Soyez  <soyez@fastjet.fr>
+ * 
+ *      * replaced Point by VPoint (to avoid any potential conflict
+ *        with an already existing class Point in FastJet
+ * 
+ * 
+ * 2008-04-01  Gregory Soyez  <soyez@fastjet.fr>
+ * 
+ *      * declared ystar volatile in HalfEdge (apparently fixes a bug
+ *        related to VD computations with points on a grid)
+ * 
+ * 
+ * 2007-05-07  Gregory Soyez  <soyez@fastjet.fr>
+ * 
+ *      * put the code in the fastjet namespace
+ * 
+ *      * replaced float by double
+ * 
+ *      * generateVoronoi() takes a vector of Point instead of 2
+ *        pointers
+ * 
+ *      * added info about the parent sites to GraphEdge
+ * 
+ *      * removed condition on minimal distance between sites
+ * 
+ */
+
+#include "fastjet/LimitedWarning.hh"
+#include <vector>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define DELETED -2
+#define le 0
+#define re 1
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+/**
+ * \if internal_doc
+ * @ingroup internal
+ * \class VPoint
+ * class to handle a 2d point
+ * \endif
+ */
+class VPoint{
+public:
+  /// defailt ctor
+  VPoint() : x(0.0), y(0.0) {}
+
+  /// ctor with initialisation
+  VPoint(double _x, double _y) : x(_x), y(_y) {}
+
+  /// addition
+  inline VPoint operator + (const VPoint &p) const{
+    return VPoint(x+p.x, y+p.y);
+  }
+
+  /// subtraction
+  inline VPoint operator - (const VPoint &p) const{
+    return VPoint(x-p.x, y-p.y);
+  }
+
+  /// scalar multiplication
+  inline VPoint operator * (const double t) const{
+    return VPoint(x*t, y*t);
+  }
+
+  /// vector coordinates
+  double x,y;
+};
+
+
+/// norm of a vector
+inline double norm(const VPoint p){
+  return p.x*p.x+p.y*p.y;
+}
+
+
+/// 2D vector product
+inline double vector_product(const VPoint &p1, const VPoint &p2){
+  return p1.x*p2.y-p1.y*p2.x;
+}
+
+
+/// scalar product
+inline double scalar_product(const VPoint &p1, const VPoint &p2){
+  return p1.x*p2.x+p1.y*p2.y;
+}
+
+
+/**
+ * \if internal_doc
+ * @ingroup internal
+ * \class GraphEdge
+ * handle an edge of the Voronoi Diagram.
+ * \endif
+ */
+class GraphEdge{
+public:
+  /// coordinates of the extreme points
+  double x1,y1,x2,y2;
+
+  /// indices of the parent sites that define the edge
+  int point1, point2;
+
+  /// pointer to the next edge
+  GraphEdge* next;
+};
+
+
+/**
+ * \if internal_doc
+ * @ingroup internal
+ * \class Site
+ * structure used both for particle sites and for vertices.
+ * \endif
+ */
+class Site{
+ public:
+  VPoint	coord;
+  int sitenbr;
+  int refcnt;
+};
+
+
+
+class Freenode{
+public:
+  Freenode *nextfree;
+};
+
+
+class FreeNodeArrayList{
+public:
+  Freenode* memory;
+  FreeNodeArrayList* next;
+};
+
+
+class Freelist{
+public:
+  Freenode *head;
+  int nodesize;
+};
+
+class Edge{
+public:
+  double a,b,c;
+  Site *ep[2];
+  Site *reg[2];
+  int edgenbr;
+};
+
+
+class Halfedge{
+public:
+  Halfedge *ELleft, *ELright;
+  Edge *ELedge;
+  int ELrefcnt;
+  char ELpm;
+  Site *vertex;
+  volatile double ystar;
+  Halfedge *PQnext;
+};
+
+/**
+ * \if internal_doc
+ * @ingroup internal
+ * \class VoronoiDiagramGenerator
+ * Shane O'Sullivan C++ version of Stephan Fortune Voronoi diagram
+ * generator
+ * \endif
+ */
+class VoronoiDiagramGenerator{
+public:
+  VoronoiDiagramGenerator();
+  ~VoronoiDiagramGenerator();
+
+  bool generateVoronoi(std::vector<VPoint> *_parent_sites,
+		       double minX, double maxX, double minY, double maxY, 
+		       double minDist=0);
+
+  inline void resetIterator(){
+    iteratorEdges = allEdges;
+  }
+
+  bool getNext(GraphEdge **e){
+    if(iteratorEdges == 0)
+      return false;
+    
+    *e = iteratorEdges;
+    iteratorEdges = iteratorEdges->next;
+    return true;
+  }
+  
+  std::vector<VPoint> *parent_sites;
+  int n_parent_sites;
+
+private:
+  void cleanup();
+  void cleanupEdges();
+  char *getfree(Freelist *fl);	
+  Halfedge *PQfind();
+  int PQempty();
+	
+  Halfedge **ELhash;
+  Halfedge *HEcreate(), *ELleft(), *ELright(), *ELleftbnd();
+  Halfedge *HEcreate(Edge *e,int pm);
+  
+  VPoint PQ_min();
+  Halfedge *PQextractmin();	
+  void freeinit(Freelist *fl,int size);
+  void makefree(Freenode *curr,Freelist *fl);
+  void geominit();
+  void plotinit();
+
+  // GS: removed the unused (always ==0) argument
+  bool voronoi(/*int triangulate*/);
+  void ref(Site *v);
+  void deref(Site *v);
+  void endpoint(Edge *e,int lr,Site * s);
+
+  void ELdelete(Halfedge *he);
+  Halfedge *ELleftbnd(VPoint *p);
+  Halfedge *ELright(Halfedge *he);
+  void makevertex(Site *v);
+  
+  void PQinsert(Halfedge *he,Site * v, double offset);
+  void PQdelete(Halfedge *he);
+  bool ELinitialize();
+  void ELinsert(Halfedge *lb, Halfedge *newHe);
+  Halfedge * ELgethash(int b);
+  Halfedge *ELleft(Halfedge *he);
+  Site *leftreg(Halfedge *he);
+  bool PQinitialize();
+  int PQbucket(Halfedge *he);
+  void clip_line(Edge *e);
+  char *myalloc(unsigned n);
+  int right_of(Halfedge *el,VPoint *p);
+
+  Site *rightreg(Halfedge *he);
+  Edge *bisect(Site *s1, Site *s2);
+  double dist(Site *s,Site *t);
+
+  // GS: 'p' is unused and always ==0 (see also comment by
+  //     S. O'Sullivan in the source file), so we remove it
+  Site *intersect(Halfedge *el1, Halfedge *el2 /*, VPoint *p=0*/);
+
+  Site *nextone();
+
+  void pushGraphEdge(double x1, double y1, double x2, double y2, 
+		     Site *s1, Site *s2);
+
+  // Gregory Soyez: unused plotting methods
+  // void openpl();
+  // void circle(double x, double y, double radius);
+  // void range(double minX, double minY, double maxX, double maxY);
+  // 
+  // void out_bisector(Edge *e);
+  // void out_ep(Edge *e);
+  // void out_vertex(Site *v);
+  // void out_site(Site *s);
+  // 
+  // void out_triple(Site *s1, Site *s2,Site * s3);
+
+  Freelist hfl;
+  Halfedge *ELleftend, *ELrightend;
+  int ELhashsize;
+  
+  int sorted, debug;
+  double xmin, xmax, ymin, ymax, deltax, deltay;
+  
+  Site *sites;
+  int nsites;
+  int siteidx;
+  int sqrt_nsites;
+  int nvertices;
+  Freelist sfl;
+  Site *bottomsite;
+  
+  int nedges;
+  Freelist efl;
+  int PQhashsize;
+  Halfedge *PQhash;
+  int PQcount;
+  int PQmin;
+  
+  int ntry, totalsearch;
+  double pxmin, pxmax, pymin, pymax, cradius;
+  int total_alloc;
+  
+  double borderMinX, borderMaxX, borderMinY, borderMaxY;
+  
+  FreeNodeArrayList* allMemoryList;
+  FreeNodeArrayList* currentMemoryBlock;
+  
+  GraphEdge* allEdges;
+  GraphEdge* iteratorEdges;
+  
+  double minDistanceBetweenSites;
+
+  static LimitedWarning _warning_degeneracy;
+};
+
+int scomp(const void *p1,const void *p2);
+
+
+FASTJET_END_NAMESPACE
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/base.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/base.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/base.hh	(revision 5)
@@ -0,0 +1,43 @@
+
+//STARTHEADER
+// $Id: base.hh 2717 2011-11-17 14:15:46Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_FASTJET_BASE_HH__
+#define __FASTJET_FASTJET_BASE_HH__
+
+/// \namespace fastjet
+/// the FastJet namespace
+/// 
+/// all the fastjet-related material is put under that namespace
+
+// define this for easier readability (and obfuscation?) in
+// a range of places
+#define FASTJET_BEGIN_NAMESPACE namespace fastjet {
+#define FASTJET_END_NAMESPACE   }
+
+#endif // __FASTJET_FASTJET_BASE_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/numconsts.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/numconsts.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/internal/numconsts.hh	(revision 5)
@@ -0,0 +1,51 @@
+//STARTHEADER
+// $Id: numconsts.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+
+#ifndef __FASTJET_NUMCONSTS__
+#define __FASTJET_NUMCONSTS__
+
+#include "fastjet/internal/base.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+// some common useful constants!
+
+const double pi = 3.141592653589793238462643383279502884197;
+const double twopi = 6.283185307179586476925286766559005768394;
+const double pisq  = 9.869604401089358618834490999876151135314;
+const double zeta2 = 1.644934066848226436472415166646025189219;
+const double zeta3 = 1.202056903159594285399738161511449990765;
+const double eulergamma = 0.577215664901532860606512090082402431042;
+const double ln2   = 0.693147180559945309417232121458176568076;
+
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_NUMCONSTS__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/ATLASConePlugin.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/ATLASConePlugin.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/ATLASConePlugin.cc	(revision 5)
@@ -0,0 +1,178 @@
+//STARTHEADER
+// $Id: ATLASConePlugin.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2007-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+// fastjet stuff
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/ATLASConePlugin.hh"
+
+// SpartyJet stuff
+#include "CommonUtils.hh"
+#include "JetConeFinderTool.hh"
+#include "JetSplitMergeTool.hh"
+
+// other stuff
+#include <vector>
+#include <sstream>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+
+bool ATLASConePlugin::_first_time = true;
+
+string ATLASConePlugin::description () const {
+  ostringstream desc;
+  desc << "ATLASCone plugin with R = "<< _radius 
+       << ", seed threshold = " << _seedPt
+       << ", overlap threshold f = " << _f;
+  return desc.str();
+}
+
+void ATLASConePlugin::run_clustering(ClusterSequence & clust_seq) const {
+  // print a banner if we run this for the first time
+  _print_banner(clust_seq.fastjet_banner_stream());
+
+
+  // transfer the list of PseudoJet into a atlas::Jet::jet_list_t
+  //  jet_list_t is a vector<Jet*>
+  // We set the index of the 4-vect to trace the constituents at the end
+  //------------------------------------------------------------------
+  // cout << "ATLASConePlugin: transferring vectors from ClusterSequence" << endl;
+  atlas::JetConeFinderTool::jetcollection_t jets_ptr;
+  vector<atlas::Jet*> particles_ptr;
+
+  for (unsigned int i=0 ; i<clust_seq.jets().size() ; i++) {
+    const PseudoJet & mom = clust_seq.jets()[i];
+    
+    // first create the particle
+    atlas::Jet *particle = new atlas::Jet(mom.px(), mom.py(), mom.pz(), mom.E(), i);
+    particles_ptr.push_back(particle);
+
+    // then add it to the list of particles we'll use for the clustering
+    atlas::Jet *jet = new atlas::Jet;
+    jet->set_index(particle->index());
+    jet->addConstituent(particle);
+
+    // and finally add that one to the list of jets
+    jets_ptr.push_back(jet);
+  }
+  // cout << "ATLASCone: " << jets_ptr.size() << " particles to cluster" << endl;
+
+  // search the stable cones
+  //------------------------------------------------------------------
+  // cout << "ATLASConePlugin: searching for stable cones" << endl;
+  atlas::JetConeFinderTool stable_cone_finder;
+
+  // set the parameters
+  stable_cone_finder.m_coneR  = _radius;
+  stable_cone_finder.m_seedPt = _seedPt;
+
+  // really do the search.
+  // Note that the list of protocones is returned 
+  // through the argument
+  stable_cone_finder.execute(jets_ptr);
+  // cout << "ATLASCone: " << jets_ptr.size() << " stable cones found" << endl;
+
+  // perform the split-merge
+  //------------------------------------------------------------------
+  // cout << "ATLASConePlugin: running the split-merge" << endl;
+  atlas::JetSplitMergeTool split_merge;
+  
+  // set the parameters
+  split_merge.m_f = _f;
+
+  // do the work
+  // again, the list of jets is returned through the argument
+  split_merge.execute(&jets_ptr);
+  // cout << "ATLASCone: " << jets_ptr.size() << " jets after split--merge" << endl;
+
+  // build the FastJet jets (a la SISConePlugin)
+  //------------------------------------------------------------------
+  // cout << "ATLASConePlugin: backporting jets to the ClusterSequence" << endl;
+  for (atlas::Jet::jet_list_t::iterator jet_it = jets_ptr.begin() ;
+	 jet_it != jets_ptr.end(); jet_it++){
+    // iterate over the constituents, starting from the first one
+    // that we just take as a reference
+    atlas::Jet::constit_vect_t::iterator constit_it = (*jet_it)->firstConstituent();
+    // cout << " atlas: jet has " << (*jet_it)->getConstituentNum() << " constituents" << endl;
+    int jet_k = (*constit_it)->index();
+    constit_it++;
+    
+    // loop over the remaining particles
+    while (constit_it != (*jet_it)->lastConstituent()){
+      // take the last result of the merge
+      int jet_i = jet_k;
+      // and the next element of the jet
+      int jet_j = (*constit_it)->index();
+      // and merge them (with a fake dij)
+      double dij = 0.0;
+
+      // create the new jet by hand so that we can adjust its user index
+      // Note again the use of the E-scheme recombination here!
+      PseudoJet newjet = clust_seq.jets()[jet_i] + clust_seq.jets()[jet_j];
+      clust_seq.plugin_record_ij_recombination(jet_i, jet_j, dij, newjet, jet_k);
+
+      // jump to the next constituent
+      constit_it++;
+    }
+
+    // we have merged all the jet's particles into a single object, so now
+    // "declare" it to be a beam (inclusive) jet.
+    // [NB: put a sensible looking d_iB just to be nice...]
+    double d_iB = clust_seq.jets()[jet_k].perp2();
+    clust_seq.plugin_record_iB_recombination(jet_k, d_iB);
+  }
+    
+  // cout << "ATLASConePlugin: Bye" << endl;
+  clear_list(particles_ptr);
+  clear_list(jets_ptr);
+}
+
+// print a banner for reference to the 3rd-party code
+void ATLASConePlugin::_print_banner(ostream *ostr) const{
+  if (! _first_time) return;
+  _first_time=false;
+
+  // make sure the user has not set the banner stream to NULL
+  if (!ostr) return;  
+
+  (*ostr) << "#-------------------------------------------------------------------------" << endl;
+  (*ostr) << "# You are running the ATLAS Cone plugin for FastJet                       " << endl;
+  (*ostr) << "# Original code from SpartyJet; interface by the FastJet authors          " << endl;
+  (*ostr) << "# If you use this plugin, please cite                                     " << endl;
+  (*ostr) << "#   P.A. Delsart, K. Geerlings, J. Huston, B. Martin and C. Vermilion,    " << endl;
+  (*ostr) << "#   SpartyJet, http://projects.hepforge.org/spartyjet                     " << endl;
+  (*ostr) << "# in addition to the usual FastJet reference.                             " << endl;
+  (*ostr) << "#-------------------------------------------------------------------------" << endl;
+
+  // make sure we really have the output done.
+  ostr->flush();
+}
+
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/CommonUtils.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/CommonUtils.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/CommonUtils.hh	(revision 5)
@@ -0,0 +1,93 @@
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from SpartyJet
+// v2.20.0 by Pierre-Antoine Delsart, Kurtis L. Geerlings, Joey
+// Huston, Brian T. Martin and Chris Vermilion
+// For details, see http://www.pa.msu.edu/~huston/SpartyJet/
+//                  http://projects.hepforge.org/spartyjet/
+//
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+// History of changes from the original CommonUtils.hh file in
+// SpartyJet v2.20
+//  
+// 2009-01-15  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::atlas namespace
+
+#ifndef _JETCOMMONUTILS_HH_
+#define _JETCOMMONUTILS_HH_
+
+#include <ctime>
+#include <algorithm>
+#include <cmath>
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace atlas{
+
+// **************************************************************
+// phi conversions 
+// **************************************************************
+inline  float to_minusPI_PI(float phi){
+  while(phi < -M_PI) phi += 2*M_PI;
+  while(phi >= M_PI) phi -= 2*M_PI;
+  return phi;
+}
+inline  float to_zero_2PI(float phi){
+  while(phi < 0) phi += 2*M_PI;
+  while(phi >= 2*M_PI) phi -= 2*M_PI;
+  return phi;
+}
+
+
+
+// **************************************************************
+// List utils
+// **************************************************************
+// Destroy all pointers in a container, and clear it
+// T must be a container of pointers ex. list<T2*>
+template<class T>
+void clear_list(T & list){
+  typedef typename T::iterator it_t;
+  it_t it = list.begin();
+  it_t itE = list.end();
+  for(; it != itE; ++it){
+    delete *it;
+  }
+  list.clear();
+}
+
+
+
+
+
+// **************************************************************
+// timing
+// **************************************************************
+class stopwatch {
+public :
+  stopwatch() : m_total(0){};
+  void start(){m_last = std::clock();};
+  void resume(){m_last = std::clock();};
+  float pause() {
+    std::clock_t now=std::clock();
+    m_total = m_total +  now - m_last;
+    m_last = now;
+    return convert();
+  }
+  float stop(){float t=pause(); m_total = std::clock_t(0); return t;}
+protected:
+  std::clock_t m_last;
+  std::clock_t m_total;
+  
+  float convert(){ return float(m_total)*1000/CLOCKS_PER_SEC;}
+};
+
+
+}  // namespace atlas
+
+FASTJET_END_NAMESPACE
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/Jet.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/Jet.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/Jet.cc	(revision 5)
@@ -0,0 +1,76 @@
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from SpartyJet
+// v2.20.0 by Pierre-Antoine Delsart, Kurtis L. Geerlings, Joey
+// Huston, Brian T. Martin and Chris Vermilion
+// For details, see http://www.pa.msu.edu/~huston/SpartyJet/
+//                  http://projects.hepforge.org/spartyjet/
+//
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+// History of changes from the original Jet.cc file in SpartyJet v2.20
+//  
+// 2009-01-15  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::atlas namespace
+
+#include "Jet.hh"
+#include <iostream>
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace atlas { 
+
+Jet::Jet(Jet &jet) : LorentzVector(0,0,0,0){
+  add(jet);
+  m_index = jet.index();
+  m_constituents = jet.m_constituents;
+  //  m_area = jet.area();
+  //  m_area_error = jet.area_error();
+}
+Jet::Jet(Jet* j){
+  add(*j);
+  m_index = j->index();
+  m_constituents = j->m_constituents;
+//   m_area = j->area();
+//   m_area_error = j->area_error();
+}
+
+void Jet::addJet(Jet& j){
+  add(j);
+  m_constituents.insert(m_constituents.end(), j.firstConstituent(), j.lastConstituent() );
+}
+
+void Jet::addJet(Jet* j){
+  add(*j) ;
+  m_constituents.insert(m_constituents.end(), j->firstConstituent(), j->lastConstituent() );
+}
+
+
+void Jet::addConstituent(constit_vect_t::iterator first, constit_vect_t::iterator last){
+  m_constituents.insert(m_constituents.end(), first, last); 
+  for(; first!=last;++first) this->add( **first);
+}
+
+
+
+Jet* jet_from_overlap(Jet* j1, Jet* j2){
+  Jet *j = new Jet();
+  Jet::constit_vect_t::iterator it1 = j1->firstConstituent();
+  Jet::constit_vect_t::iterator it1E = j1->lastConstituent();
+  for(;it1!= it1E; ++it1){
+    Jet::constit_vect_t::iterator it2 = j2->firstConstituent();
+    Jet::constit_vect_t::iterator it2E = j2->lastConstituent();
+    for(;it2!= it2E; ++it2){
+      if( *it1 == *it2) j->addConstituent(*it1);
+    }
+    
+  }
+  return j;
+}
+}  // namespace atlas
+
+FASTJET_END_NAMESPACE
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/Jet.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/Jet.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/Jet.hh	(revision 5)
@@ -0,0 +1,147 @@
+#ifndef _JET_HH_
+#define _JET_HH_
+
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from SpartyJet
+// v2.20.0 by Pierre-Antoine Delsart, Kurtis L. Geerlings, Joey
+// Huston, Brian T. Martin and Chris Vermilion
+// For details, see http://www.pa.msu.edu/~huston/SpartyJet/
+//                  http://projects.hepforge.org/spartyjet/
+//
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+// History of changes from the original Jet.hh file in SpartyJet v2.20
+//  
+// 2011-11-14  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * removed some harmless warnings coming with the -Wshadow gcc option
+// 
+// 2011-06-28  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * used stable_sort instead of sort to fix some ordering issues
+// 
+// 2009-01-15  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::atlas namespace
+
+#include "LorentzVector.hh"
+#include <list>
+#include <vector>
+#include <algorithm>
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace atlas { 
+
+class Jet : public LorentzVector {
+public :
+  
+  typedef std::list<Jet*> constit_vect_t;
+  typedef std::vector<Jet*> jet_list_t;
+  
+  Jet(): LorentzVector(0,0,0,0) {}
+  Jet(double p1, double p2, double p3, double p0, int index_in=0): LorentzVector(p1,p2,p3,p0), m_index(index_in){}
+  Jet(LorentzVector v): LorentzVector(v)  {m_index = 0;}
+  Jet(Jet &j);
+  Jet(Jet *j);
+  
+  
+  /// The standard way of merging jets
+  void addJet(Jet& j);
+  void addJet(Jet* j);
+
+ 
+  /// Access jet constituents
+  int getConstituentNum(){return m_constituents.size();}
+  constit_vect_t::iterator firstConstituent(){ return m_constituents.begin();};
+  constit_vect_t::iterator lastConstituent(){ return m_constituents.end();};
+
+  
+
+  // convenience methods 
+  void addConstituent(Jet* jet) {m_constituents.push_back(jet);this->add(*jet);};
+  void addConstituent(constit_vect_t::iterator first, constit_vect_t::iterator last);
+  void removeConstituent(Jet* jet) {m_constituents.remove(jet);this->subtract(*jet);};
+
+  void addConstituent_notMoment(Jet* jet){m_constituents.push_back(jet);}
+  //void removeConstituent(constit_vect_t::iterator first, constit_vect_t::iterator last);
+
+
+  // return position in intial collection
+  int index() const {return m_index;}  
+  void set_index(int i){m_index= i;}
+
+
+  /// Atlas compatibility code :
+  LorentzVector hlv() {return *this;}
+
+
+  //bool split_merged;   // from siscone/jetclu/midpoint algorithms
+
+protected :
+  int m_index;  /// position in a jet list (used for constituents positions)
+  constit_vect_t m_constituents;
+
+};
+
+
+ 
+void find_jet_in_list(Jet* j);
+
+// using functors is supposed to be faster... (??)
+class JetSorter_Et {
+public:
+  bool operator()(Jet* j1, Jet* j2){
+    // deal with numerical uncertainty : 
+    if(fabs( j1->et() - j2->et())<0.001 ) return 0;
+    else return j1->et() > j2->et();
+    //return (j1->et() > j2->et());    
+  }
+};
+
+class JetSorter_Pt {
+public:
+  bool operator()(Jet* j1, Jet* j2){
+    return (j1->pt() > j2->pt());
+  }
+};
+
+class JetSorter_Eta {
+public:
+  bool operator()(Jet* j1, Jet* j2){
+    return (j1->eta() > j2->eta());
+  }
+};
+
+class JetSorter_E {
+public:
+  bool operator()(Jet* j1, Jet* j2){
+    return (j1->e() > j2->e());
+  }
+};
+
+
+
+template<class T>
+inline void sort_jet_list(Jet::jet_list_t &list){
+  std::stable_sort(list.begin(),list.end(), T());
+}
+inline void sort_list_et(Jet::jet_list_t &list){
+  //std::sort(list.begin(),list.end(),et_compare);
+  std::stable_sort(list.begin(),list.end(), JetSorter_Et());
+}
+inline void sort_list_pt(Jet::jet_list_t &list){
+  std::stable_sort(list.begin(),list.end(),JetSorter_Pt());
+}
+
+Jet* jet_from_overlap(Jet* j1, Jet* j2);
+
+}  // namespace atlas
+
+FASTJET_END_NAMESPACE
+#endif
+
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/JetConeFinderTool.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/JetConeFinderTool.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/JetConeFinderTool.cc	(revision 5)
@@ -0,0 +1,259 @@
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from SpartyJet
+// v2.20.0 by Pierre-Antoine Delsart, Kurtis L. Geerlings, Joey
+// Huston, Brian T. Martin and Chris Vermilion
+// For details, see http://www.pa.msu.edu/~huston/SpartyJet/
+//                  http://projects.hepforge.org/spartyjet/
+//
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+//*******************************************************************************
+// Filename : JetConeFinderTool.cc 
+// Author   : Ambreesh Gupta
+// Created  : Nov, 2000
+//
+// Jan 2004: Use CLHEP units. Use phi = (-pi,pi].
+//*******************************************************************************
+
+// History of changes from the original JetConeFinder.cc file in
+// SpartyJet v2.20
+//  
+// 2009-01-15  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::atlas namespace
+//
+// 2009-02-14  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * imported into FastJet
+//        * removed the string name in the ctor
+//        * removed the message logs
+//        * replaced StatusCode by int
+//        * cleaned the comments
+
+#include <iostream>
+
+#include "JetConeFinderTool.hh"
+#include "Jet.hh"
+#include "JetDistances.hh"
+#include "CommonUtils.hh"
+
+#include <vector>
+#include <math.h>
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace atlas { 
+
+// set the default energy scale
+  double GeV = 1.0; //1000;
+
+JetConeFinderTool::JetConeFinderTool() :m_coneR(0.7)
+  , m_ptcut(0.0*GeV)
+  , m_eps(0.05)
+  , m_seedPt(2.0*GeV)
+  , m_etaMax(5.0)
+{}
+
+JetConeFinderTool::~JetConeFinderTool()
+{}
+
+/////////////////////////////////////////////////////////////////////////////////
+//Execution                                                                     /
+/////////////////////////////////////////////////////////////////////////////////
+int JetConeFinderTool::execute(jetcollection_t & theJets)
+{
+  sort_jet_list<JetSorter_Et>(theJets);
+
+  m_pjetV = &theJets;
+
+  if(theJets.size()==0) return 0;
+
+  // Initiale ctr/dctr counter for object counting.
+  m_ctr = 0;
+  m_dctr = 0;
+
+  //////////////////////
+  // Reconstruct Jets // 
+  //////////////////////
+  this->reconstruct();
+
+  //////////////////////////
+  // ReFill JetCollection //
+  //////////////////////////
+  clear_list(theJets);
+  jetcollection_t::iterator it = m_jetOV->begin();
+  jetcollection_t::iterator itE = m_jetOV->end();
+  for(; it!=itE; ++it){
+    theJets.push_back(*it);
+  }
+
+
+  delete m_jetOV;
+  return 1;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Reconstruction algorithm specific methods                                  /
+///////////////////////////////////////////////////////////////////////////////
+
+void
+JetConeFinderTool::reconstruct()
+{
+  m_jetOV = new jetcollection_t();
+
+  jetcollection_t::iterator tItr;
+  jetcollection_t::iterator tItr_begin = m_pjetV->begin();
+  jetcollection_t::iterator tItr_end   = m_pjetV->end();
+
+  // order towers in pt
+
+  for ( tItr=tItr_begin; tItr!=tItr_end; ++tItr ) {    
+
+    // Seed Cut
+    double tEt = (*tItr)->et();
+    if ( tEt < m_seedPt ) break;
+
+    // Tower eta, phi
+    double etaT = (*tItr)->eta();
+    double phiT = (*tItr)->phi();    
+    
+    // Iteration logic
+    bool stable = false;
+    bool inGeom = true;
+    
+    Jet* preJet;
+    
+    int count = 1;
+    do { // Iteration Loop
+
+      // Make cone  
+      preJet = calc_cone(etaT,phiT);
+      double etaC = preJet->eta();
+      double phiC = preJet->phi();
+      
+      double deta = fabs(etaT - etaC);
+      double dphi = fabs(JetDistances::deltaPhi(phiT,phiC));
+
+      // Is Stable ?
+      if ( deta < m_eps && dphi < m_eps ) 
+	stable = true;
+      
+      // In Geometry ?
+      if ( fabs(etaC) > m_etaMax ) 
+	inGeom = false;	
+
+      etaT = etaC;
+      phiT = phiC;
+
+      if ( !stable && inGeom ) {
+	delete preJet;
+	m_dctr +=1;
+      }
+      ++count;
+
+    }while ( !stable && inGeom && count < 10  );      
+  
+    if ( count > 9 && (!stable && inGeom) ) continue;  // FIXME 9 ?
+
+    // If iteration was succesfull -- check if this is a new jet and 
+    // add it to OV.
+
+    if ( stable && inGeom ) {
+      jetcollection_t::iterator pItr   = m_jetOV->begin();
+      jetcollection_t::iterator pItrE  = m_jetOV->end();
+    
+      bool newJet = true;
+      double etaT = preJet->eta();
+      double phiT = preJet->phi();
+
+      for ( ; pItr != pItrE ; ++pItr ) {
+	double etaC = (*pItr)->eta();
+	double phiC = (*pItr)->phi();
+
+	double deta = fabs(etaT - etaC);
+	double dphi = fabs(JetDistances::deltaPhi(phiT,phiC));
+
+	if ( deta < 0.05  && dphi < 0.05 ) { 
+	  // Debugging done by Gregory Soyez:
+	  //
+	  // Becase of the cut on the Et difference imposed on the
+	  // ordering (line 80 of Jet.hh), the ordering of the input
+	  // particles in Et is not robust agains different
+	  // implementations of sort (which has an undefined behaviour
+	  // if 2 particles are equal). A consequence of this is that
+	  // stable cone search will consider these 2 seeds in an
+	  // undefined order. If the 2 resulting stable cones are too
+	  // close (deta<0.05, dphi<0.05) one will be accepted and the
+	  // other rejected. Which one depends on the ordering and is
+	  // thus undefined. If the 2 stable cones do not have the
+	  // same number of constituents this could affect the result
+	  // of the clustering.
+	  //
+	  // The line below helps debugging these cases by printing
+	  // the rejected stable cones
+	  //std::cout << "rejecting " << etaT << " " << phiT << " " << preJet->et() << (*tItr)->eta() << " " << (*tItr)->phi() << " " << (*tItr)->et() << std::endl;
+	  newJet = false;
+	  break;
+	}
+      }
+      if ( newJet ) {
+	m_jetOV->push_back( preJet );
+	// Debugging done by Gregory Soyez:
+	//
+	// Becase of the cut on the Et difference imposed on the
+	// ordering (line 80 of Jet.hh), the ordering of the input
+	// particles in Et is not robust agains different
+	// implementations of sort (which has an undefined behaviour
+	// if 2 particles are equal). A consequence of this is that
+	// stable cone search will consider these 2 seeds in an
+	// undefined order. If the 2 resulting stable cones are too
+	// close (deta<0.05, dphi<0.05) one will be accepted and the
+	// other rejected. Which one depends on the ordering and is
+	// thus undefined. If the 2 stable cones do not have the
+	// same number of constituents this could affect the result
+	// of the clustering.
+	//
+	// The line below helps debugging these cases by printing
+	// the accepted stable cones
+	//std::cout << "accepting " << etaT << " " << phiT << " " << preJet->et() << (*tItr)->eta() << " " << (*tItr)->phi() << " " << (*tItr)->et() << std::endl;
+      }
+      else {
+	delete preJet;
+	m_dctr +=1;
+      }
+    }
+    else {
+      delete preJet;
+      m_dctr +=1;
+    }
+  }    
+}
+
+Jet* JetConeFinderTool::calc_cone(double eta, double phi)
+{
+  // Create a new Jet   
+  Jet* j = new Jet();
+  m_ctr +=1; 
+
+  // Add all ProtoJet within m_coneR to this Jet  
+  jetcollection_t::iterator itr  = m_pjetV->begin();
+  jetcollection_t::iterator itrE = m_pjetV->end();
+
+  for ( ; itr!=itrE; ++itr ) {
+    double dR = JetDistances::deltaR(eta,phi,(*itr)->eta(),(*itr)->phi());
+    if ( dR < m_coneR ) {
+      j->addJet( (*itr) );
+    }
+  }    
+
+  return j;
+}
+
+
+
+}  // namespace atlas
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/JetConeFinderTool.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/JetConeFinderTool.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/JetConeFinderTool.hh	(revision 5)
@@ -0,0 +1,115 @@
+#ifndef JETREC_JETCONEFINDERTOOL_H
+#define JETREC_JETCONEFINDERTOOL_H
+
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from SpartyJet
+// v2.20.0 by Pierre-Antoine Delsart, Kurtis L. Geerlings, Joey
+// Huston, Brian T. Martin and Chris Vermilion
+// For details, see http://www.pa.msu.edu/~huston/SpartyJet/
+//                  http://projects.hepforge.org/spartyjet/
+//
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+//******************************************************************************
+// Filename :  JetConeFinderTool
+// Author   :  Ambreesh Gupta
+// Created  :  September, 2002
+//
+// DESCRIPTION:
+//  TESTING cone algorithm created from JetSeedLessCone algorithm. The algorithm
+//  only lookps over seed of certain Pt that is configurable trought the 
+//  jobOption file.
+//
+// PROPERTIES (JobOption Parameters):
+//
+//  declareProperty("ConeParam",m_coneR);
+//    ProtoJetContainerLoc  string "Default"   Key for ProtoJet input.
+//    JetContainerLoc       string "Default"   Key for Jet list to output.
+//    ConeR                 double 0.5         Cone radius
+//    PtCut                 double 0.0         Pt Cut applied on ProtoJet.
+//    Epsilon               double 0.05        
+//    SeedPt                double 2.0         Pt Cut for ProtoJet to be a seed.
+//
+// HISTORY
+//
+// BUGS
+//*****************************************************************************
+
+// History of changes from the original JetConeFinder.hh file in
+// SpartyJet v2.20
+//  
+// 2009-01-15  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::atlas namespace
+//
+// 2009-02-14  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * imported into FastJet
+//        * removed the message logs
+//        * replaced StatusCode by int
+
+//Library Includes
+#include <string>
+#include <vector>
+#include <list>
+
+//#include "JetCore/CustomMessage.hh"
+//typedef int StatusCode;
+
+// class JetCollection;
+#include "Jet.hh"
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace atlas{
+
+class JetConeFinderTool 
+{
+public:
+  typedef Jet::jet_list_t jetcollection_t;
+  
+
+  JetConeFinderTool();
+
+  virtual ~JetConeFinderTool();
+
+  virtual int execute(jetcollection_t &theJets);
+
+
+  //private:
+    void  reconstruct();   
+    Jet*  calc_cone(double, double); 
+
+    // Configured through jobOption
+    std::string m_protoJetContainerLoc;
+    std::string m_jetContainerLoc;
+
+    double      m_coneR; // Cone Radius
+    double      m_ptcut; // Pt Cut
+    double      m_eps;   // Arbitrary parameter
+    double      m_seedPt;
+    double      m_etaMax;
+
+    // Internals 
+    //std::list<Jet*>*       m_pjetV;
+    jetcollection_t*       m_pjetV;
+    jetcollection_t*       m_jetOV;
+
+    int             m_cone_in_tower;
+
+    std::vector<double>*     m_veta;
+    std::vector<double>*     m_vphi;
+
+    int m_ctr;
+    int m_dctr;
+
+  //Message m_log;
+};
+
+}  // namespace atlas
+
+FASTJET_END_NAMESPACE 
+#endif // JETREC_JETCONEFINDERTOOL_H
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/JetDistances.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/JetDistances.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/JetDistances.hh	(revision 5)
@@ -0,0 +1,100 @@
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from SpartyJet
+// v2.20.0 by Pierre-Antoine Delsart, Kurtis L. Geerlings, Joey
+// Huston, Brian T. Martin and Chris Vermilion
+// For details, see http://www.pa.msu.edu/~huston/SpartyJet/
+//                  http://projects.hepforge.org/spartyjet/
+//
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+// History of changes from the original JetDistance.hh file in
+// SpartyJet v2.20
+//  
+// 2009-01-15  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::atlas namespace
+
+#ifndef JETUTIL_JETDISTANCES_H
+#define JETUTIL_JETDISTANCES_H
+
+
+#include "Jet.hh"
+
+#include <cmath>
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace atlas { 
+
+struct JetDistances {
+
+
+  // distance in eta
+  inline static double deltaEta(const Jet& jet1, const Jet& jet2)
+  { return jet1.eta() - jet2.eta(); }
+  inline static double deltaEta(const Jet* jet1,
+				const Jet* jet2)
+  { return jet1->eta() - jet2->eta(); }
+  inline static double deltaEta(const double eta1,
+				const double eta2)
+  { return (eta1 - eta2); }
+
+
+
+  inline static double deltaPhi(const Jet& jet1, 
+				const Jet& jet2)
+  { 
+    return fixedPhi(jet1.phi() - jet2.phi());
+  }
+  inline static double deltaPhi(const Jet* jet1,
+				const Jet* jet2)
+  { 
+    return fixedPhi(jet1->phi()-jet2->phi());
+  }
+  inline static double deltaPhi(const double phi1,
+				const double phi2)
+  { 
+    return fixedPhi( phi1 - phi2 );
+  }
+
+
+  // distance in (eta,phi)
+  inline static double deltaR(const Jet& jet1, 
+			      const Jet& jet2)
+  { return sqrt( deltaEta(jet1,jet2) * deltaEta(jet1,jet2) + 
+		 deltaPhi(jet1,jet2) * deltaPhi(jet1,jet2) ); }
+  inline static double deltaR(const Jet* jet1,
+			      const Jet* jet2)
+  { return sqrt( deltaEta(jet1,jet2) * deltaEta(jet1,jet2) +
+		 deltaPhi(jet1,jet2) * deltaPhi(jet1,jet2) ); }
+  
+  inline static double deltaR(const double eta1, const double phi1,
+			      const double eta2, const double phi2 )
+  { return sqrt( deltaEta(eta1,eta2) * deltaEta(eta1,eta2) +
+		 deltaPhi(phi1,phi2) * deltaPhi(phi1,phi2) ); }
+  
+
+  
+  // phi convention enforcement
+  inline static double fixedPhi(double aPhi)
+  {
+    while ( aPhi < -M_PI )
+      {
+	aPhi += 2.*M_PI;
+      }
+    while ( aPhi > M_PI )
+      {
+	aPhi -= 2.*M_PI;
+      }
+    return aPhi;
+  }
+
+};
+
+}  // namespace atlas
+
+FASTJET_END_NAMESPACE
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/JetSplitMergeTool.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/JetSplitMergeTool.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/JetSplitMergeTool.cc	(revision 5)
@@ -0,0 +1,226 @@
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from SpartyJet
+// v2.20.0 by Pierre-Antoine Delsart, Kurtis L. Geerlings, Joey
+// Huston, Brian T. Martin and Chris Vermilion
+// For details, see http://www.pa.msu.edu/~huston/SpartyJet/
+//                  http://projects.hepforge.org/spartyjet/
+//
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+//*******************************************************************************
+// Filename : JetSplitMergeTool.cxx 
+// Author   : Ambreesh Gupta
+// Created  : Nov, 2001
+//
+// File taken from SpartyJet v2.20.0
+// Modifications:
+//   removed the string name in the ctor
+//   removed the Message m_log
+//   replaced px() -> px, ... in the LorentzVector calls
+//   cleaned the comments
+//*******************************************************************************
+
+// History of changes from the original JetSplitMergeTool.cc file in
+// SpartyJet v2.20
+// 
+// 2009-01-15  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::atlas namespace
+// 
+// 2009-02-14  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * imported into FastJet
+//        * removed the string name in the ctor
+//        * removed the Message m_log
+//        * replaced px() -> px, ... in the LorentzVector calls
+//        * cleaned the comments
+
+#include <iostream>
+
+#include "JetSplitMergeTool.hh"
+#include "Jet.hh"
+#include "JetDistances.hh"
+#include "CommonUtils.hh"
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace atlas { 
+
+JetSplitMergeTool::JetSplitMergeTool()
+  :  m_f( 0.5 )
+{}
+
+JetSplitMergeTool::~JetSplitMergeTool()
+{}
+
+/////////////////////////////////////////////////////////////////////////////////
+//Execution                                                                     /
+/////////////////////////////////////////////////////////////////////////////////
+int JetSplitMergeTool::execute( jetcollection_t* theJets )
+{
+  m_ctr = 0;
+  m_dctr = 0;
+
+  ////////////////////////////////////////////////////
+  // From the input, collection create a list of Jet//
+  ////////////////////////////////////////////////////
+  m_preJet.clear();
+  m_jet.clear();
+
+  jetcollection_t::iterator itrB = theJets->begin();
+  jetcollection_t::iterator itrE = theJets->end(); 
+
+  double etot =0.;
+  for (;itrB!=itrE;itrB++) {
+    Jet* j = new Jet(); j->addJet(*itrB);
+    m_ctr +=1;
+    m_preJet.push_back(j);    
+
+    etot += j->e();    
+  }
+
+  /////////////////////
+  // Split Merge Jets//
+  /////////////////////
+  this->split_merge();
+ 
+  /////////////////////////////////////////////
+  // Empty and re-fill input jetcollection_t //
+  /////////////////////////////////////////////
+  clear_list(*theJets);
+  jetcollection_t::iterator it = m_jet.begin();
+  jetcollection_t::iterator itE = m_jet.end();
+  for(; it!=itE; ++it){    
+    theJets->push_back(*it);
+  }
+
+  return 1;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Reconstruction algorithm specific methods                                  /
+///////////////////////////////////////////////////////////////////////////////
+
+void JetSplitMergeTool::split_merge()
+{
+  if ( m_preJet.size() >= 2 ) {
+    do {
+      sort_list_et(m_preJet);
+      
+      jetcollection_t::iterator itr;
+      jetcollection_t::iterator first = m_preJet.begin();
+      jetcollection_t::iterator last  = m_preJet.end();
+      
+      itr=first;
+      ++itr;
+      bool overlap = false;
+  
+      for (;itr != last;++itr) {      
+	double etaF = (*first)->eta();
+	double phiF = (*first)->phi();
+	double etaS = (*itr)->eta();
+	double phiS = (*itr)->phi();
+	
+	Jet* oJet = jet_from_overlap( (*first),*itr);   
+	m_ctr +=1; 
+
+	Jet::constit_vect_t::iterator itro  = oJet->firstConstituent();
+	Jet::constit_vect_t::iterator itroE = oJet->lastConstituent();
+	
+	if ( oJet->getConstituentNum() != 0 ) {
+	  overlap = true;
+	  
+	  // fraction
+	  double f = sqrt(pow(oJet->px,2)+pow(oJet->py,2))/
+	    sqrt(pow((*itr)->px,2)+pow((*itr)->py,2));
+	  
+	  // merge
+	  if ( f > m_f) {
+	    // we need to remove constituents !
+	    Jet *j = (*first);
+	    for ( ;itro != itroE; ++itro ) j->removeConstituent(*itro);
+	    (*first)->addJet(*itr);
+	    //m_preJet.remove(*itr);
+	    delete *itr;
+	    m_preJet.erase(itr);
+	    m_dctr +=1;
+	  }	
+	  
+	  // split	
+	  if ( f <= m_f) {	  
+	    for ( ;itro != itroE; ++itro ) {	      
+	      // Distance of first jet from ProtoJet
+	      double deta1 = etaF - (*itro)->eta();
+	      double dphi1 = fabs(JetDistances::deltaPhi(phiF,(*itro)->phi()));
+	      double dist1 = pow( deta1 , 2 ) + pow( dphi1 , 2 );
+	      
+	      // Distance of second jet from ProtoJet
+	      double deta2 = etaS - (*itro)->eta();
+	      double dphi2 = fabs(JetDistances::deltaPhi(phiS,(*itro)->phi()));
+	      double dist2 = pow( deta2 , 2 ) + pow( dphi2 , 2 );
+	      
+	      // Remove protojet from farther Jet	    	      
+	      if ( dist1 > dist2 ) (*first)->removeConstituent(*itro);
+	      if ( dist1 <= dist2 ) (*itr)->removeConstituent(*itro);	
+	    }
+	  }
+	  // Delete overlap jet     
+	  delete oJet;     
+	  m_dctr +=1;
+	  break; 
+	}  
+	else {
+	  // Delete overlap jet     
+	  delete oJet;     
+	  m_dctr +=1;
+	}    
+      }
+      
+      if ( overlap == false ) {
+	m_jet.push_back(*first);
+	//m_preJet.remove(*first);      
+	m_preJet.erase(first);      
+      }
+      
+    } while ( m_preJet.size() != 0 );    
+  }
+  else if ( m_preJet.size() == 1) {
+    m_jet.push_back( *(m_preJet.begin()) );
+  }
+
+}
+
+//////////////////////////////////////////////////////////////////////
+
+// "True" eta and phi ASSUMING the 4-vector is filled as
+// ex -> e * sin(theta) * cos(phi)
+// ey -> e * sin(theta) * sin(phi)
+// ez -> e * cos(theta)
+// e  -> e 
+// Jet phi range is (-pi,pi].
+
+
+double JetSplitMergeTool::etaTrue(Jet::constit_vect_t::iterator pj)
+{
+  double s = ((*pj)->e() > 0) ? +1.0 : -1.0;
+  double px = (*pj)->px;
+  double py = (*pj)->py;
+  double pz = (*pj)->pz;
+  double theta = acos(pz*s/sqrt(px*px+py*py+pz*pz));
+  return -log(tan(theta/2.0));
+}
+
+double JetSplitMergeTool::phiTrue(Jet::constit_vect_t::iterator pj)
+{
+  double s = ((*pj)->e() > 0) ? +1.0 : -1.0;
+  double px = (*pj)->px;
+  double py = (*pj)->py;
+  return atan2(py*s,px*s);
+}
+
+}  // namespace atlas
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/JetSplitMergeTool.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/JetSplitMergeTool.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/JetSplitMergeTool.hh	(revision 5)
@@ -0,0 +1,116 @@
+#ifndef JETREC_JETSPLITMERGETOOL_H
+#define JETREC_JETSPLITMERGETOOL_H
+
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from SpartyJet
+// v2.20.0 by Pierre-Antoine Delsart, Kurtis L. Geerlings, Joey
+// Huston, Brian T. Martin and Chris Vermilion
+// For details, see http://www.pa.msu.edu/~huston/SpartyJet/
+//                  http://projects.hepforge.org/spartyjet/
+//
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+//******************************************************************************
+// Filename :  JetSplitMergeTool   
+// Author   :  Ambreesh Gupta
+// Created  :  November, 2001
+//
+// DESCRIPTION:
+//
+// Cone algorithms generally produce overlapping jets. These jets are then
+// passed through a Split Merge algorithm to create seperated jets. This
+// is an implementation of one such algorithm.
+// 
+// The steps of the algorithm are:
+//          - <to be written>
+//
+// PROPERTIES (JobOption Parameters):
+//
+//    ProtoJetContainerLoc  string "Default"   Key for ProtoJet input.
+//    JetContainerLoc       string "Default"   Key for Jet list to output.
+//    OverlapFraction       double 0.5
+//
+// HISTORY
+//   05Nov01 agupta.  First version
+//   15Aug02 agupta.  Fix phi-wrapping. 
+//*****************************************************************************
+
+
+// History of changes from the original JetSplitMergeTool.hh file in
+// SpartyJet v2.20
+// 
+// 2009-01-15  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::atlas namespace
+// 
+// 2009-02-14  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * imported into FastJet
+//        * removed the message logs
+//        * replaced StatusCode by int
+
+
+//class StoreGateSvc;
+
+//Includes
+#include "Jet.hh"
+
+#include <vector>
+#include <list>
+
+//#include "JetCore/CustomMessage.hh"
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace atlas { 
+
+//typedef int StatusCode ;
+
+class JetSplitMergeTool 
+{
+public:
+  typedef Jet::jet_list_t jetcollection_t;
+    //Constructors
+    JetSplitMergeTool();
+
+    //Destructor
+    virtual ~JetSplitMergeTool();
+
+    virtual int execute( jetcollection_t* theJets );
+
+    //Handle negative energy ProtoJets:
+    double etaTrue(Jet::constit_vect_t::iterator pj);
+    double phiTrue(Jet::constit_vect_t::iterator pj);
+
+    //private:
+    void                                     split_merge();   
+    double                                             m_f;
+    jetcollection_t                               m_preJet;
+    jetcollection_t                                  m_jet;
+    jetcollection_t*                              m_jetVec;
+
+    int m_ctr;
+    int m_dctr;
+
+  //    Message m_log;
+};
+
+}  // namespace atlas
+
+FASTJET_END_NAMESPACE
+
+#endif // JETREC_JETSPLITMERGETOOL_H
+
+
+
+
+
+
+
+
+
+
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/LorentzVector.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/LorentzVector.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/LorentzVector.hh	(revision 5)
@@ -0,0 +1,83 @@
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from SpartyJet
+// v2.20.0 by Pierre-Antoine Delsart, Kurtis L. Geerlings, Joey
+// Huston, Brian T. Martin and Chris Vermilion
+// For details, see http://www.pa.msu.edu/~huston/SpartyJet/
+//                  http://projects.hepforge.org/spartyjet/
+//
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+// History of changes compared to the original LorentzVector.hh file
+// 
+// 2011-11-14  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * removed some harmless warnings coming with the -Wshadow gcc option
+// 
+// 2009-01-15  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * put the code in the fastjet::atlas namespace
+
+#ifndef _LORENTZ_VECTOR_HH_
+#define _LORENTZ_VECTOR_HH_
+
+#include <cmath>
+#include <fastjet/internal/base.hh>
+
+#ifndef M_PI
+#define M_PI  3.141592653589793238462643383279502884197 
+#endif
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace atlas{
+
+class LorentzVector
+{
+ public:
+
+  double px,py,pz,E;
+
+  LorentzVector(): px(0), py(0), pz(0), E(0) {}
+  LorentzVector(double p1, double p2, double p3, double p0): px(p1), py(p2), pz(p3), E(p0) {}
+  LorentzVector(const LorentzVector& lv): px(lv.px), py(lv.py), pz(lv.pz), E(lv.E) {}
+  double p()   const {return sqrt(px*px + py*py + pz*pz);}
+  double pt()  const {return sqrt(px*px + py*py);}
+  double mt()  const {return sqrt((E-pz)*(E+pz));}
+  double y()   const {return 0.5*log((E + pz)/(E - pz));}
+  double Et()  const {return E/p()*pt();}
+  inline double et()  const {return Et();}
+  inline double e()  const {return E;}
+  double eta() const {return 0.5*log((p() + pz)/(p() - pz));}
+  double phi() const
+  {
+    double r = atan2(py,px);
+    if(r < 0)
+      r += 2*M_PI;
+    return r;
+  }
+  void add(LorentzVector v)
+  {
+    px += v.px;
+    py += v.py;
+    pz += v.pz;
+    E  += v.E;
+  }
+  void subtract(LorentzVector v)
+  {
+    px -= v.px;
+    py -= v.py;
+    pz -= v.pz;
+    E  -= v.E;
+  }
+  bool isEqual(LorentzVector v)
+  {
+    return px == v.px && py == v.py && pz == v.pz && E == v.E;
+  }
+};
+
+} // namespace atlas
+
+FASTJET_END_NAMESPACE
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/README
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/README	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/README	(revision 5)
@@ -0,0 +1,39 @@
+This version of the ATLAS cone is coming from SpartyJet v2.20.0
+
+We have copied the following files
+  JetConeFinderTool.cxx
+  JetConeFinderTool.h
+  JetSplitMergeTool.cxx
+  JetSplitMergeTool.h
+that do the real work and based the coding in 
+ATLASConePlugin.{hh,cc} on ConeFinderTool.cxx by adapting
+to the ClusterSequence requirements.
+
+
+copied 
+  LorentzVector.{cc,hh} 
+from CDFCone/CDFcode in the FastJet plugin ... then,
+  - added et() == Et()
+  - added e() == E
+
+copied 
+  Jet.{cc,hh}, JetDistances.hh, CommonUtils.{cc,hh}
+from SpartyJet then
+  - added #include <algorithm> in Jet.hh
+
+
+
+- Cleaned a bit JetConeFinderTool.cc (mostly removed the m_log)
+- Check FIXME 9 !!! (related to maxiteration)
+- in #include directives, fixed the dirs
+- added "namespace SpartyJet" in JetConeFinderTool.hh
+- replaced StatusCode by int (as it was originally defined
+- removed the string argument in the JetConeFinderTool ctor
+
+- removed the string arg of the JetSplitMergeTool ctor
+- replaced 4-vect component access using a function (e.g. px())
+  with direct access (e.g. px)
+
+IMPORTANT:
+  - LorentzVector might conflict w its definition in CDFcode
+  - changed the GeV to 1.0 instead of 1000.0
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/fastjet/ATLASConePlugin.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/fastjet/ATLASConePlugin.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/ATLASCone/fastjet/ATLASConePlugin.hh	(revision 5)
@@ -0,0 +1,101 @@
+//STARTHEADER
+// $Id: ATLASConePlugin.hh 2758 2011-11-24 08:31:58Z soyez $
+//
+// Copyright (c) 2007-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+// Note on the implementation:
+//   this implementation of the ATLAS Cone is based on the SpartyJet
+//   v2.20.0 implementation. See README for details
+
+#ifndef __ATLASCONEPLUGIN_HH__
+#define __ATLASCONEPLUGIN_HH__
+
+#include "fastjet/JetDefinition.hh"
+
+// questionable whether this should be in fastjet namespace or not...
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+// forward declaration to reduce includes
+class PseudoJet;
+
+//----------------------------------------------------------------------
+//
+/// @ingroup plugins
+/// \class ATLASConePlugin
+/// Implementation of the ATLAS Cone (plugin for fastjet v2.4 upwards)
+class ATLASConePlugin : public JetDefinition::Plugin {
+public:
+  /// Main constructor for the ATLASCone Plugin class.
+  ///
+  /// Apparently the default parameters in the ATLAS software are the
+  /// ones used here. SpartyJet uses a radius of 0.7, a seed threshold
+  /// of 1 GeV and an overlap threshold of 0.75
+  /// For the ATLAS SW defaults, see
+  ///   http://atlas-sw.cern.ch/cgi-bin/viewcvs-atlas.cgi/groups/JetRoutines/SpartyJet/atlas/
+  /// in the JetdoneFinderTools.cxx (rev1.1) and JetSplitMergeTool.cxx (rev1.1)
+  /// For SpartyJet, see atlas/ConeFinderTool.h
+  ///
+  /// Finally, to agree with FastJet standards, we do not specify a default R,
+  /// that in the ATLAS code is 0.7
+  ATLASConePlugin (double radius, double seedPt_in=2.0, double f_in=0.5)
+    : _radius(radius), _seedPt(seedPt_in), _f(f_in){}
+
+  /// copy constructor
+  ATLASConePlugin (const ATLASConePlugin & plugin) {
+    *this = plugin;
+  }
+
+  // the things that are required by base class
+  virtual std::string description () const;
+  virtual void run_clustering(ClusterSequence &) const;
+
+  /// the plugin mechanism's standard way of accessing the jet radius
+  /// here we return the R of the last alg in the list
+  virtual double R() const {return _radius;}
+
+  // access to the other parameters
+  /// seed threshold
+  double seedPt() const {return _seedPt;}
+
+  /// split-merge overlap threshold
+  double f() const {return _f;}
+
+private:
+
+  double _radius;   ///< the cone radius
+  double _seedPt;   ///< the pt seed threshold used in stable-cone search
+  double _f;        ///< the overlap thresholod used in the split-merge
+
+  static bool _first_time;
+
+  /// print a banner for reference to the 3rd-party code
+  void _print_banner(std::ostream *ostr) const;
+};
+
+FASTJET_END_NAMESPACE        // defined in fastjet/internal/base.hh
+
+#endif // __ATLASCONEPLUGIN_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/CDFJetCluPlugin.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/CDFJetCluPlugin.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/CDFJetCluPlugin.cc	(revision 5)
@@ -0,0 +1,187 @@
+//STARTHEADER
+// $Id: CDFJetCluPlugin.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/CDFJetCluPlugin.hh"
+#include "fastjet/ClusterSequence.hh"
+#include <sstream>
+#include <cassert>
+
+// CDF stuff
+#include "JetCluAlgorithm.hh"
+#include "PhysicsTower.hh"
+#include "Cluster.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+using namespace cdf;
+
+bool CDFJetCluPlugin::_first_time = true;
+
+string CDFJetCluPlugin::description () const {
+  ostringstream desc;
+  
+  desc << "CDF JetClu jet algorithm with " 
+       << "seed_threshold = "     << seed_threshold    () << ", "
+       << "cone_radius = "        << cone_radius       () << ", "
+       << "adjacency_cut = "      << adjacency_cut     () << ", " 
+       << "max_iterations = "     << max_iterations    () << ", "
+       << "iratch = "             << iratch            () << ", "
+       << "overlap_threshold = "  << overlap_threshold () ;
+
+  return desc.str();
+}
+
+
+void CDFJetCluPlugin::run_clustering(ClusterSequence & clust_seq) const {
+  // print a banner if we run this for the first time
+  _print_banner(clust_seq.fastjet_banner_stream());
+ 
+  // create the physics towers needed by the CDF code
+  vector<PhysicsTower> towers;
+  towers.reserve(clust_seq.jets().size());
+
+  // create a map to identify jets (actually just the input particles)...
+  //map<double,int> jetmap;
+
+  for (unsigned i = 0; i < clust_seq.jets().size(); i++) {
+    PseudoJet particle(clust_seq.jets()[i]);
+    //_insert_unique(particle, jetmap);
+    LorentzVector fourvect(particle.px(), particle.py(),
+			   particle.pz(), particle.E());
+    PhysicsTower tower(fourvect);
+    // add tracking information for later
+    tower.fjindex = i;
+    towers.push_back(tower);
+  }
+
+  // prepare the CDF algorithm
+  JetCluAlgorithm j(seed_threshold(), cone_radius(), adjacency_cut(),
+                    max_iterations(), iratch(), overlap_threshold());
+    
+  // run the CDF algorithm
+  std::vector<Cluster> jets;
+  j.run(towers,jets);
+
+
+  // now transfer the jets back into our own structure -- we will
+  // mimic the cone code with a sequential recombination sequence in
+  // which the jets are built up by adding one particle at a time
+
+  // NB: with g++-4.0, the reverse iterator code gave problems, so switch
+  //     to indices instead
+  //for(vector<Cluster>::const_reverse_iterator jetIter = jets.rbegin(); 
+  //                                    jetIter != jets.rend(); jetIter++) {
+  //  const vector<PhysicsTower> & tower_list = jetIter->towerList;
+  //  int jet_k = jetmap[tower_list[0].fourVector.E];
+  //
+  //  int ntow = int(jetIter->towerList.size());
+
+  for(int iCDFjets = jets.size()-1; iCDFjets >= 0; iCDFjets--) {
+
+    const vector<PhysicsTower> & tower_list = jets[iCDFjets].towerList;
+    int ntow = int(tower_list.size());
+    
+    // 2008-09-04: sort the towerList (according to fjindex) so as
+    //             to have a consistent order for particles in jet
+    //             (necessary because addition of ultra-soft particles
+    //             sometimes often modifies the order, while maintaining
+    //             the same overall set)
+    vector<int>    jc_indices(ntow);
+    vector<double> fj_indices(ntow); // use double: benefit from existing routine
+    for (int itow = 0; itow < ntow; itow++) {
+      jc_indices[itow] = itow;
+      fj_indices[itow] = tower_list[itow].fjindex;
+    }
+    sort_indices(jc_indices, fj_indices);
+
+    int jet_k = tower_list[jc_indices[0]].fjindex;
+  
+    for (int itow = 1; itow < ntow; itow++) {
+      if (tower_list[jc_indices[itow]].Et() > 1e-50) {
+      }
+      int jet_i = jet_k;
+      // retrieve our index for the jet
+      int jet_j;
+      jet_j = tower_list[jc_indices[itow]].fjindex;
+
+      // safety check
+      assert (jet_j >= 0 && jet_j < int(towers.size()));
+
+      // do a fake recombination step with dij=0
+      double dij = 0.0;
+
+      // JetClu does E-scheme recombination so we can stick with the
+      // simple option
+      clust_seq.plugin_record_ij_recombination(jet_i, jet_j, dij, jet_k);
+
+    }
+  
+    // NB: put a sensible looking d_iB just to be nice...
+    double d_iB = clust_seq.jets()[jet_k].perp2();
+    clust_seq.plugin_record_iB_recombination(jet_k, d_iB);
+  }
+
+
+  // following code is for testing only
+  //cout << endl;
+  //for(vector<Cluster>::const_iterator jetIter = jets.begin(); 
+  //                                    jetIter != jets.end(); jetIter++) {
+  //  cout << jetIter->fourVector.pt() << " " << jetIter->fourVector.y() << endl;
+  //}
+  //cout << "-----------------------------------------------------\n";
+  //vector<PseudoJet> ourjets(clust_seq.inclusive_jets());
+  //for (vector<PseudoJet>::const_iterator ourjet = ourjets.begin();
+  //     ourjet != ourjets.end(); ourjet++) {
+  //  cout << ourjet->perp() << " " << ourjet->rap() << endl;
+  //}
+  //cout << endl;
+}
+
+
+// print a banner for reference to the 3rd-party code
+void CDFJetCluPlugin::_print_banner(ostream *ostr) const{
+  if (! _first_time) return;
+  _first_time=false;
+
+  // make sure the user has not set the banner stream to NULL
+  if (!ostr) return;  
+
+  (*ostr) << "#-------------------------------------------------------------------------" << endl;
+  (*ostr) << "# You are running the CDF JetClu plugin for FastJet                       " << endl;
+  (*ostr) << "# This is based on an implementation provided by Joey Huston.             " << endl;
+  (*ostr) << "# If you use this plugin, please cite                                     " << endl;
+  (*ostr) << "#   F. Abe et al. [CDF Collaboration], Phys. Rev. D 45 (1992) 1448.       " << endl;
+  (*ostr) << "# in addition to the usual FastJet reference.                             " << endl;
+  (*ostr) << "#-------------------------------------------------------------------------" << endl;
+
+  // make sure we really have the output done.
+  ostr->flush();
+}
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/CDFMidPointPlugin.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/CDFMidPointPlugin.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/CDFMidPointPlugin.cc	(revision 5)
@@ -0,0 +1,175 @@
+//STARTHEADER
+// $Id: CDFMidPointPlugin.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/CDFMidPointPlugin.hh"
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/Error.hh"
+#include <sstream>
+
+// CDF stuff
+#include "MidPointAlgorithm.hh"
+#include "PhysicsTower.hh"
+#include "Cluster.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+using namespace cdf;
+
+bool CDFMidPointPlugin::_first_time = true;
+
+string CDFMidPointPlugin::description () const {
+  ostringstream desc;
+  
+  string sm_scale_string = "split-merge uses ";
+  switch(_sm_scale) {
+  case SM_pt:
+    sm_scale_string += "pt";
+    break;
+  case SM_Et:
+    sm_scale_string += "Et";
+    break;
+  case SM_mt:
+    sm_scale_string += "mt";
+    break;
+  case SM_pttilde:
+    sm_scale_string += "pttilde (scalar sum of pts)";
+    break;
+  default:
+    ostringstream err;
+    err << "Unrecognized split-merge scale choice = " << _sm_scale;
+    throw Error(err.str());
+  }
+
+  
+  if (cone_area_fraction() == 1) {
+    desc << "CDF MidPoint jet algorithm, with " ;
+  } else {
+    desc << "CDF MidPoint+Searchcone jet algorithm, with ";
+  }
+  desc << "seed_threshold = "     << seed_threshold     () << ", "
+       << "cone_radius = "        << cone_radius        () << ", "
+       << "cone_area_fraction = " << cone_area_fraction () << ", " 
+       << "max_pair_size = "      << max_pair_size      () << ", "
+       << "max_iterations = "     << max_iterations     () << ", "
+       << "overlap_threshold  = " << overlap_threshold  () << ", "
+       << sm_scale_string ;
+
+  return desc.str();
+}
+
+
+void CDFMidPointPlugin::run_clustering(ClusterSequence & clust_seq) const {
+  // print a banner if we run this for the first time
+  _print_banner(clust_seq.fastjet_banner_stream());
+ 
+  // create the physics towers needed by the CDF code
+  vector<PhysicsTower> towers;
+  towers.reserve(clust_seq.jets().size());
+  for (unsigned i = 0; i < clust_seq.jets().size(); i++) {
+    LorentzVector fourvect(clust_seq.jets()[i].px(),
+			   clust_seq.jets()[i].py(),
+			   clust_seq.jets()[i].pz(),
+			   clust_seq.jets()[i].E());
+    PhysicsTower tower(fourvect);
+    // misuse one of the indices for tracking, since the MidPoint
+    // implementation doesn't seem to make use of these indices
+    tower.calTower.iEta = i;
+    towers.push_back(tower);
+  }
+
+  // prepare the CDF algorithm
+  MidPointAlgorithm m(_seed_threshold,_cone_radius,_cone_area_fraction,
+		      _max_pair_size,_max_iterations,_overlap_threshold,
+                      MidPointAlgorithm::SplitMergeScale(_sm_scale));
+    
+  // run the CDF algorithm
+  std::vector<Cluster> jets;
+  m.run(towers,jets);
+
+
+  // now transfer the jets back into our own structure -- we will
+  // mimic the cone code with a sequential recombination sequence in
+  // which the jets are built up by adding one particle at a time
+  for(vector<Cluster>::const_iterator jetIter = jets.begin(); 
+                                      jetIter != jets.end(); jetIter++) {
+    const vector<PhysicsTower> & tower_list = jetIter->towerList;
+    int jet_k = tower_list[0].calTower.iEta;
+  
+    int ntow = int(jetIter->towerList.size());
+    for (int itow = 1; itow < ntow; itow++) {
+      int jet_i = jet_k;
+      // retrieve our misappropriated index for the jet
+      int jet_j = tower_list[itow].calTower.iEta;
+      // do a fake recombination step with dij=0
+      double dij = 0.0;
+      clust_seq.plugin_record_ij_recombination(jet_i, jet_j, dij, jet_k);
+    }
+  
+    // NB: put a sensible looking d_iB just to be nice...
+    double d_iB = clust_seq.jets()[jet_k].perp2();
+    clust_seq.plugin_record_iB_recombination(jet_k, d_iB);
+  }
+
+
+  // following code is for testing only
+  //cout << endl;
+  //for(vector<Cluster>::const_iterator jetIter = jets.begin(); 
+  //                                    jetIter != jets.end(); jetIter++) {
+  //  cout << jetIter->fourVector.pt() << " " << jetIter->fourVector.y() << endl;
+  //}
+  //cout << "-----------------------------------------------------\n";
+  //vector<PseudoJet> ourjets(clust_seq.inclusive_jets());
+  //for (vector<PseudoJet>::const_reverse_iterator ourjet = ourjets.rbegin();
+  //     ourjet != ourjets.rend(); ourjet++) {
+  //  cout << ourjet->perp() << " " << ourjet->rap() << endl;
+  //}
+  //cout << endl;
+}
+
+// print a banner for reference to the 3rd-party code
+void CDFMidPointPlugin::_print_banner(ostream *ostr) const{
+  if (! _first_time) return;
+  _first_time=false;
+
+  // make sure the user has not set the banner stream to NULL
+  if (!ostr) return;  
+
+  (*ostr) << "#-------------------------------------------------------------------------" << endl;
+  (*ostr) << "# You are running the CDF MidPoint plugin for FastJet                     " << endl;
+  (*ostr) << "# This is based on an implementation provided by Joey Huston.             " << endl;
+  (*ostr) << "# If you use this plugin, please cite                                     " << endl;
+  (*ostr) << "#   G. C. Blazey et al., hep-ex/0005012.                                  " << endl;
+  (*ostr) << "# in addition to the usual FastJet reference.                             " << endl;
+  (*ostr) << "#-------------------------------------------------------------------------" << endl;
+
+  // make sure we really have the output done.
+  ostr->flush();
+}
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/CalTower.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/CalTower.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/CalTower.hh	(revision 5)
@@ -0,0 +1,94 @@
+#ifndef _CAL_TOWER_HH_
+#define _CAL_TOWER_HH_
+
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from
+// http://www.pa.msu.edu/~huston/Les_Houches_2005/JetClu+Midpoint-StandAlone.tgz
+//
+// Permission to distribute it with FastJet has been granted by Joey
+// Huston (see the COPYING file in the main FastJet directory for
+// details).
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+// History of changes compared to the original CalTower.hh file
+// 
+// 2011-11-14  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * added a few parentheses suggested by the -Wparentheses gcc option
+// 
+// 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::cdf namespace
+// 
+// 2008-01-15  Gregory Soyez  <soyez@fastjet.fr>
+// 
+// 	  * fixed issues with compilation under VC (definition of M_PI)
+// 
+// 2006-09-24  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added JetClu+MidPoint to FastJet
+
+#include <cmath>
+
+#ifndef M_PI
+#define M_PI  3.141592653589793238462643383279502884197 
+#endif
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace cdf{
+
+const double TOWER_THETA[23] = {  3.000,  5.700,  8.400, 11.100, 13.800, 16.500, 19.200, 21.900, 24.600, 27.300, 30.000, 33.524,
+				  36.822, 40.261, 43.614, 47.436, 51.790, 56.735, 62.310, 68.516, 75.297, 82.526, 90.000 };
+
+class CalTower
+{
+ public:
+
+  double Et,eta,phi;
+  int iEta,iPhi;
+
+  CalTower(): Et(0), eta(0), phi(0), iEta(-1), iPhi(-1) {}
+  CalTower(double Et0, double eta0, double phi0): Et(Et0), eta(eta0), phi(phi0)
+  {
+    if(fabs(eta) < -log(tan(TOWER_THETA[0]*M_PI/180/2))){
+      if(eta <= 0){
+	for(int i = 0; i < 22; i++)
+	  if(eta < -log(tan((180 - TOWER_THETA[i + 1])*M_PI/180/2))){
+	    iEta = 4 + i;
+	    break;
+	  }
+      }
+      else{
+	for(int i = 0; i < 22; i++)
+	  if(-eta < -log(tan((180 - TOWER_THETA[i + 1])*M_PI/180/2))){
+	    iEta = 47 - i;
+	    break;
+	  }
+      }
+      if ((iEta >= 8 && iEta < 14) || (iEta >= 38 && iEta < 44))
+	iPhi = int(phi/2/M_PI*48)%48;
+      else
+	iPhi = int(phi/2/M_PI*24)%24;
+    }
+    else{
+      iEta = -1;
+      iPhi = -1;
+    }
+  }
+  CalTower(double Et0, double eta0, double phi0, int iEta0, int iPhi0): Et(Et0), eta(eta0), phi(phi0), iEta(iEta0), iPhi(iPhi0) {}
+  CalTower(const CalTower& c): Et(c.Et), eta(c.eta), phi(c.phi), iEta(c.iEta), iPhi(c.iPhi) {}
+  bool isEqual(CalTower c)
+  {
+    return Et == c.Et && eta == c.eta && phi == c.phi && iEta == c.iEta && iPhi == c.iPhi;
+  }
+};
+
+}  // namespace cdf
+
+FASTJET_END_NAMESPACE
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/Centroid.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/Centroid.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/Centroid.hh	(revision 5)
@@ -0,0 +1,91 @@
+#ifndef _CENTROID_HH_
+#define _CENTROID_HH_
+
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from
+// http://www.pa.msu.edu/~huston/Les_Houches_2005/JetClu+Midpoint-StandAlone.tgz
+//
+// Permission to distribute it with FastJet has been granted by Joey
+// Huston (see the COPYING file in the main FastJet directory for
+// details).
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+// History of changes compared to the original Centroid.hh file
+// 
+// 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::cdf namespace
+// 
+// 2008-01-15  Gregory Soyez  <soyez@fastjet.fr>
+// 
+// 	  * fixed issues with compilation under VC (definition of M_PI)
+// 
+// 2006-09-24  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added JetClu+MidPoint to FastJet
+
+#include <cmath>
+
+#ifndef M_PI
+#define M_PI  3.141592653589793238462643383279502884197 
+#endif
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace cdf{
+
+class Centroid
+{
+ public:
+
+  double Et,eta,phi;
+
+  Centroid(): Et(0), eta(0), phi(0) {}
+  Centroid(double centroidEt, double centroidEta, double centroidPhi): Et(centroidEt), eta(centroidEta), phi(centroidPhi) {}
+  Centroid(const Centroid& c): Et(c.Et), eta(c.eta), phi(c.phi) {}
+  void add(Centroid c)
+  {
+    double newEt = Et + c.Et;
+    eta = (Et*eta + c.Et*c.eta)/newEt;
+    double dPhi = c.phi - phi;
+    if(dPhi > M_PI)
+      dPhi -= 2*M_PI;
+    else if(dPhi < -M_PI)
+      dPhi += 2*M_PI;
+    phi += dPhi*c.Et/newEt;
+    while(phi < 0)
+      phi += 2*M_PI;
+    while(phi >= 2*M_PI)
+      phi -= 2*M_PI;
+    Et = newEt;
+  }
+  void subtract(Centroid c)
+  {
+    double newEt = Et - c.Et;
+    eta = (Et*eta - c.Et*c.eta)/newEt;
+    double dPhi = c.phi - phi;
+    if(dPhi > M_PI)
+      dPhi -= 2*M_PI;
+    else if(dPhi < -M_PI)
+      dPhi += 2*M_PI;
+    phi -= dPhi*c.Et/newEt;
+    while(phi < 0)
+      phi += 2*M_PI;
+    while(phi >= 2*M_PI)
+      phi -= 2*M_PI;
+    Et = newEt;
+  }
+  bool isEqual(Centroid c)
+  {
+    return Et == c.Et && eta == c.eta && phi == c.phi;
+  }
+};
+
+}  // namespace cdf
+
+FASTJET_END_NAMESPACE
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/Cluster.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/Cluster.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/Cluster.hh	(revision 5)
@@ -0,0 +1,87 @@
+#ifndef _CLUSTER_HH_
+#define _CLUSTER_HH_
+
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from
+// http://www.pa.msu.edu/~huston/Les_Houches_2005/JetClu+Midpoint-StandAlone.tgz
+//
+// Permission to distribute it with FastJet has been granted by Joey
+// Huston (see the COPYING file in the main FastJet directory for
+// details).
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+// History of changes compared to the original Cluster.hh file
+// 
+// 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::cdf namespace
+// 
+// 2007-03-10  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added support for the pttilde scale choice in the CDF midpoint code
+// 
+// 2006-09-24  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added JetClu+MidPoint to FastJet
+
+#include "PhysicsTower.hh"
+#include "LorentzVector.hh"
+#include "Centroid.hh"
+#include <vector>
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace cdf{
+
+class Cluster
+{
+ public:
+  std::vector<PhysicsTower> towerList;
+  LorentzVector fourVector;
+  Centroid centroid;
+  // addition by G.P.Salam; pt_tilde = sum |p_{ti}|. Maintaining this
+  // seems to add about 1% (3%) to overall timings for midpoint
+  // (jetclu) but it is useful because it makes it easy to look at
+  // other scales in the split-merge procedure
+  double pt_tilde; 
+
+  Cluster()
+  {
+    clear();
+  }
+  void clear()
+  {
+    towerList.clear();
+    fourVector = LorentzVector();
+    centroid = Centroid();
+    pt_tilde = 0.0;
+  }
+  void addTower(PhysicsTower p)
+  {
+    towerList.push_back(p);
+    fourVector.add(p.fourVector);
+    centroid.add(Centroid(p.Et(),p.eta(),p.phi()));
+    pt_tilde += p.fourVector.pt();
+  }
+  void removeTower(PhysicsTower p)
+  {
+    for(std::vector<PhysicsTower>::iterator towerIter = towerList.begin(); towerIter != towerList.end(); towerIter++)
+      if(towerIter->isEqual(p)){
+	fourVector.subtract(towerIter->fourVector);
+	centroid.subtract(Centroid(towerIter->Et(),towerIter->eta(),towerIter->phi()));
+        pt_tilde -= towerIter->fourVector.pt();
+	towerList.erase(towerIter);
+	break;
+      }
+  }
+  int size(){return towerList.size();}
+};
+
+}  // namespace cdf
+
+FASTJET_END_NAMESPACE
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/ClusterComparisons.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/ClusterComparisons.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/ClusterComparisons.hh	(revision 5)
@@ -0,0 +1,90 @@
+#ifndef _CLUSTER_COMPARISONS_HH_
+#define _CLUSTER_COMPARISONS_HH_
+
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from
+// http://www.pa.msu.edu/~huston/Les_Houches_2005/JetClu+Midpoint-StandAlone.tgz
+//
+// Permission to distribute it with FastJet has been granted by Joey
+// Huston (see the COPYING file in the main FastJet directory for
+// details).
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+// History of changes compared to the original ClusterComparison.hh file
+// 
+// 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::cdf namespace
+// 
+// 2007-03-10  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added support for the pttilde scale choice in the CDF midpoint code
+// 
+// 2007-02-21  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added option of choosing the scale used in the split-merge
+//          procedure (pt [default], Et or mt)
+// 
+// 2006-09-24  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added JetClu+MidPoint to FastJet
+
+#include "Cluster.hh"
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace cdf{
+
+class ClusterFourVectorEtGreater
+{
+ public:
+  int operator()(const Cluster& c1, const Cluster& c2) const
+  {
+    return c1.fourVector.Et() > c2.fourVector.Et();
+  }
+};
+
+class ClusterCentroidEtGreater
+{
+ public:
+  int operator()(const Cluster& c1, const Cluster& c2) const
+  {
+    return c1.centroid.Et > c2.centroid.Et;
+  }
+};
+
+class ClusterPtGreater
+{
+ public:
+  int operator()(const Cluster& c1, const Cluster& c2) const
+  {
+    return c1.fourVector.pt() > c2.fourVector.pt();
+  }
+};
+
+class ClusterMtGreater
+{
+ public:
+  int operator()(const Cluster& c1, const Cluster& c2) const
+  {
+    return c1.fourVector.mt() > c2.fourVector.mt();
+  }
+};
+
+class ClusterPtTildeGreater
+{
+ public:
+  int operator()(const Cluster& c1, const Cluster& c2) const
+  {
+    return c1.pt_tilde > c2.pt_tilde;
+  }
+};
+
+}  // namespace cdf
+
+FASTJET_END_NAMESPACE
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/JetCluAlgorithm.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/JetCluAlgorithm.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/JetCluAlgorithm.cc	(revision 5)
@@ -0,0 +1,323 @@
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from
+// http://www.pa.msu.edu/~huston/Les_Houches_2005/JetClu+Midpoint-StandAlone.tgz
+//
+// Permission to distribute it with FastJet has been granted by Joey
+// Huston (see the COPYING file in the main FastJet directory for
+// details).
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+// History of changes compared to the original JetCluAlgorithm.cc file
+// 
+// 2011-11-14  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * added a few parentheses suggested by the -Wparentheses gcc option
+//
+// 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::cdf namespace
+// 
+// 2006-09-24  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added JetClu+MidPoint to FastJet
+
+#include "JetCluAlgorithm.hh"
+#include "ClusterComparisons.hh"
+#include "Centroid.hh"
+#include <algorithm>
+#include <cmath>
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace cdf{
+
+void JetCluAlgorithm::makeSeedTowers(std::vector<PhysicsTower>& towers, std::vector<Cluster>& seedTowers)
+{
+  for(int iEta = 4; iEta < 48; iEta++){
+    bool seg24 = true;
+    if ((iEta >= 8 && iEta < 14) || (iEta >= 38 && iEta < 44))
+      seg24 = false;
+    for(int iPhi = 0; iPhi < 24; iPhi++){
+      Cluster seed;
+      for(std::vector<PhysicsTower>::iterator towerIter = towers.begin(); towerIter != towers.end(); towerIter++)
+	if(towerIter->iEta() == iEta &&
+	   ((seg24 && towerIter->iPhi() == iPhi) || (!seg24 && (towerIter->iPhi() == 2*iPhi || towerIter->iPhi() == 2*iPhi + 1))))
+	  seed.addTower(*towerIter);
+      if(seed.centroid.Et > _seedThreshold)
+	seedTowers.push_back(seed);
+    }
+  }
+  sort(seedTowers.begin(),seedTowers.end(),ClusterCentroidEtGreater());
+}
+
+void JetCluAlgorithm::buildPreClusters(std::vector<Cluster>& seedTowers, std::vector<PhysicsTower>& towers,
+				       std::vector<Cluster>& preClusters)
+{
+  std::vector<Centroid> leadingSeedTowers;
+  for(std::vector<Cluster>::iterator seedTowerIter = seedTowers.begin(); seedTowerIter != seedTowers.end(); seedTowerIter++){
+    bool seedTowerAddedToPreCluster = false;
+    std::vector<Cluster>::iterator preClusterIter = preClusters.begin();
+    std::vector<Centroid>::iterator leadingSeedTowerIter = leadingSeedTowers.begin();
+    while(preClusterIter != preClusters.end() && !seedTowerAddedToPreCluster){
+      double dEta = fabs(seedTowerIter->centroid.eta - leadingSeedTowerIter->eta);
+      double dPhi = fabs(seedTowerIter->centroid.phi - leadingSeedTowerIter->phi);
+      if(dPhi > M_PI)
+	dPhi = 2*M_PI - dPhi;
+      if(dEta <= _coneRadius && dPhi <= _coneRadius){
+	int iEtaSeedTower = seedTowerIter->towerList.begin()->iEta();
+	int iPhiSeedTower = seedTowerIter->towerList.begin()->iPhi();
+	if ((iEtaSeedTower >= 8 && iEtaSeedTower < 14) || (iEtaSeedTower >= 38 && iEtaSeedTower < 44))
+	  iPhiSeedTower = iPhiSeedTower/2;
+ 	for(std::vector<PhysicsTower>::iterator preClusterTowerIter = preClusterIter->towerList.begin();
+	    preClusterTowerIter != preClusterIter->towerList.end() && !seedTowerAddedToPreCluster;
+	    preClusterTowerIter++){
+	  int iEtaPreClusterTower = preClusterTowerIter->iEta();
+	  int iPhiPreClusterTower = preClusterTowerIter->iPhi();
+	  if ((iEtaPreClusterTower >= 8 && iEtaPreClusterTower < 14) || (iEtaPreClusterTower >= 38 && iEtaPreClusterTower < 44))
+	    iPhiPreClusterTower = iPhiPreClusterTower/2;
+	  int dIEta = abs(iEtaSeedTower - iEtaPreClusterTower);
+	  int dIPhi = abs(iPhiSeedTower - iPhiPreClusterTower);
+	  if(dIPhi > 12)
+	    dIPhi = 24 - dIPhi;
+	  int adj = dIPhi*dIPhi + dIEta*dIEta;
+	  if(adj <= _adjacencyCut){
+	    for(std::vector<PhysicsTower>::iterator seedTowerTowerIter = seedTowerIter->towerList.begin();
+		seedTowerTowerIter != seedTowerIter->towerList.end();
+		seedTowerTowerIter++)
+	      preClusterIter->addTower(*seedTowerTowerIter);
+	    seedTowerAddedToPreCluster = true;
+	  }
+	}
+      }
+      preClusterIter++;
+      leadingSeedTowerIter++;
+    }
+    if(!seedTowerAddedToPreCluster){
+      Cluster newPreCluster;
+      for(std::vector<PhysicsTower>::iterator seedTowerTowerIter = seedTowerIter->towerList.begin();
+	  seedTowerTowerIter != seedTowerIter->towerList.end();
+	  seedTowerTowerIter++)
+	newPreCluster.addTower(*seedTowerTowerIter);
+      preClusters.push_back(newPreCluster);
+      leadingSeedTowers.push_back(Centroid(newPreCluster.centroid.Et,newPreCluster.centroid.eta,newPreCluster.centroid.phi));
+    }
+  }
+}
+
+void JetCluAlgorithm::findStableCones(std::vector<Cluster>& preClusters, std::vector<PhysicsTower>& towers,
+				      std::vector<Cluster>& stableCones)
+{
+  for(std::vector<Cluster>::iterator preClusterIter = preClusters.begin(); preClusterIter != preClusters.end(); preClusterIter++){
+    double startEt  = preClusterIter->centroid.Et;
+    double startEta = preClusterIter->centroid.eta;
+    double startPhi = preClusterIter->centroid.phi;
+    int nIterations = 0;
+    Cluster trialCone;
+    while(nIterations++ < _maxIterations){
+      trialCone.clear();
+      for(std::vector<PhysicsTower>::iterator towerIter = towers.begin(); towerIter != towers.end(); towerIter++){
+	double dEta = fabs(towerIter->eta() - startEta);
+	double dPhi = fabs(towerIter->phi() - startPhi);
+	if(dPhi > M_PI)
+	  dPhi = 2*M_PI - dPhi;
+	double dR = sqrt(dEta*dEta + dPhi*dPhi);
+	if(dR < _coneRadius)
+	  trialCone.addTower(*towerIter);
+      }
+      if(_iratch != 0)
+	for(std::vector<PhysicsTower>::iterator preClusterTowerIter = preClusterIter->towerList.begin();
+	    preClusterTowerIter != preClusterIter->towerList.end();
+	    preClusterTowerIter++){
+	  bool foundInTrialCone = false;
+	  for(std::vector<PhysicsTower>::iterator trialConeTowerIter = trialCone.towerList.begin();
+	      trialConeTowerIter != trialCone.towerList.end() && !foundInTrialCone;
+	      trialConeTowerIter++)
+	    if(trialConeTowerIter->isEqual(*preClusterTowerIter))
+	      foundInTrialCone = true;
+	  if(!foundInTrialCone)
+	    trialCone.addTower(*preClusterTowerIter);
+	}
+      if(nIterations <= _maxIterations){
+	double endEt  = trialCone.centroid.Et;
+	double endEta = trialCone.centroid.eta;
+	double endPhi = trialCone.centroid.phi;
+	if(endEt == startEt && endEta == startEta && endPhi == startPhi)
+	  nIterations = _maxIterations;
+	else{
+	  startEt  = endEt;
+	  startEta = endEta;
+	  startPhi = endPhi;
+	}
+      }
+    }
+//    bool foundIdentical = false;
+//    for(std::vector<Cluster>::iterator stableConeIter = stableCones.begin();
+//	stableConeIter != stableCones.end() && !foundIdentical;
+//	stableConeIter++)
+//      if(trialCone.centroid.isEqual(stableConeIter->centroid))
+//	foundIdentical = true;
+//    if(!foundIdentical)
+      stableCones.push_back(trialCone);
+  }
+  sort(stableCones.begin(),stableCones.end(),ClusterCentroidEtGreater());
+}
+
+void JetCluAlgorithm::splitAndMerge(std::vector<Cluster>& stableCones, std::vector<Cluster>& jets)
+{
+  std::vector<bool> isActive;
+  for(std::vector<Cluster>::iterator stableConeIter = stableCones.begin(); stableConeIter != stableCones.end(); stableConeIter++)
+    isActive.push_back(bool(true));
+  std::vector<bool>::iterator isActiveIter1 = isActive.begin();
+  for(std::vector<Cluster>::iterator stableConeIter1 = stableCones.begin();
+      stableConeIter1 != stableCones.end();
+      stableConeIter1++, isActiveIter1++){
+    std::vector<Cluster>::iterator stableConeIter2 = stableCones.begin();
+    std::vector<bool>::iterator isActiveIter2 = isActive.begin();
+    while(stableConeIter2 != stableConeIter1 && *isActiveIter1){
+      if(*isActiveIter2){
+	Cluster overlap;
+	for(std::vector<PhysicsTower>::iterator towerIter1 = stableConeIter1->towerList.begin();
+	    towerIter1 != stableConeIter1->towerList.end();
+	    towerIter1++)
+	  for(std::vector<PhysicsTower>::iterator towerIter2 = stableConeIter2->towerList.begin();
+	      towerIter2 != stableConeIter2->towerList.end();
+	      towerIter2++)
+	    if(towerIter1->isEqual(*towerIter2)){
+	      overlap.addTower(*towerIter1);
+	      break;
+	    }
+	if(overlap.size()){
+	  if(overlap.size() == stableConeIter2->size())
+	    *isActiveIter2 = false;
+	  else if(overlap.size() == stableConeIter1->size())
+	    *isActiveIter1 = false;
+	  else if(overlap.centroid.Et > _overlapThreshold*stableConeIter1->centroid.Et ||
+		  overlap.centroid.Et > _overlapThreshold*stableConeIter2->centroid.Et){
+	    for(std::vector<PhysicsTower>::iterator stableConeTowerIter2 = stableConeIter2->towerList.begin();
+		stableConeTowerIter2 != stableConeIter2->towerList.end();
+		stableConeTowerIter2++){
+	      bool isInOverlap = false;
+	      for(std::vector<PhysicsTower>::iterator overlapTowerIter = overlap.towerList.begin();
+		  overlapTowerIter != overlap.towerList.end() && !isInOverlap;
+		  overlapTowerIter++)
+		if(stableConeTowerIter2->isEqual(*overlapTowerIter))
+		  isInOverlap = true;
+	      if(!isInOverlap)
+		stableConeIter1->addTower(*stableConeTowerIter2);
+	    }
+	    *isActiveIter2 = false;
+	  }
+	  else{
+	    Cluster removeFromStableCone1,removeFromStableCone2,oldRemoveFromStableCone1,oldRemoveFromStableCone2;
+	    double etaStableCone1 = stableConeIter1->centroid.eta;
+	    double phiStableCone1 = stableConeIter1->centroid.phi;
+	    double etaStableCone2 = stableConeIter2->centroid.eta;
+	    double phiStableCone2 = stableConeIter2->centroid.phi;
+	    double dRstableCone1,dRstableCone2;
+	    int iterCount = 0;
+	    while(iterCount++ <= _maxIterations){
+	      oldRemoveFromStableCone1.clear();
+	      oldRemoveFromStableCone2.clear();
+	      if(iterCount > 1){
+		if(removeFromStableCone1.size()){
+		  Centroid stableConeCentroid1(stableConeIter1->centroid);
+		  Centroid removeCentroid1(removeFromStableCone1.centroid);
+		  stableConeCentroid1.subtract(removeCentroid1);
+		  etaStableCone1 = stableConeCentroid1.eta;
+		  phiStableCone1 = stableConeCentroid1.phi;
+		}
+		else{
+		  etaStableCone1 = stableConeIter1->centroid.eta;
+		  phiStableCone1 = stableConeIter1->centroid.phi;
+		}
+		if(removeFromStableCone2.size()){
+		  Centroid stableConeCentroid2(stableConeIter2->centroid);
+		  Centroid removeCentroid2(removeFromStableCone2.centroid);
+		  stableConeCentroid2.subtract(removeCentroid2);
+		  etaStableCone2 = stableConeCentroid2.eta;
+		  phiStableCone2 = stableConeCentroid2.phi;
+		}
+		else{
+		  etaStableCone2 = stableConeIter2->centroid.eta;
+		  phiStableCone2 = stableConeIter2->centroid.phi;
+		}
+		for(std::vector<PhysicsTower>::iterator removeTowerIter1 = removeFromStableCone1.towerList.begin();
+		    removeTowerIter1 != removeFromStableCone1.towerList.end();
+		    removeTowerIter1++)
+		  oldRemoveFromStableCone1.addTower(*removeTowerIter1);
+		for(std::vector<PhysicsTower>::iterator removeTowerIter2 = removeFromStableCone2.towerList.begin();
+		    removeTowerIter2 != removeFromStableCone2.towerList.end();
+		    removeTowerIter2++)
+		  oldRemoveFromStableCone2.addTower(*removeTowerIter2);
+	      }
+	      removeFromStableCone1.clear();
+	      removeFromStableCone2.clear();
+	      for(std::vector<PhysicsTower>::iterator overlapTowerIter = overlap.towerList.begin();
+		  overlapTowerIter != overlap.towerList.end();
+		  overlapTowerIter++){
+		double dEta1 = fabs(overlapTowerIter->eta() - etaStableCone1);
+		double dPhi1 = fabs(overlapTowerIter->phi() - phiStableCone1);
+		if(dPhi1 > M_PI)
+		  dPhi1 = 2*M_PI - dPhi1;
+		dRstableCone1 = dEta1*dEta1 + dPhi1*dPhi1;
+		double dEta2 = fabs(overlapTowerIter->eta() - etaStableCone2);
+		double dPhi2 = fabs(overlapTowerIter->phi() - phiStableCone2);
+		if(dPhi2 > M_PI)
+		  dPhi2 = 2*M_PI - dPhi2;
+		dRstableCone2 = dEta2*dEta2 + dPhi2*dPhi2;
+		if(dRstableCone1 < dRstableCone2)
+		  removeFromStableCone2.addTower(*overlapTowerIter);
+		else
+		  removeFromStableCone1.addTower(*overlapTowerIter);
+	      }
+	      if(iterCount > 1 &&
+		 removeFromStableCone1.size() == oldRemoveFromStableCone1.size() &&
+		 removeFromStableCone2.size() == oldRemoveFromStableCone2.size() &&
+		 (!removeFromStableCone1.size() || !removeFromStableCone2.size() ||
+		  (removeFromStableCone1.centroid.isEqual(oldRemoveFromStableCone1.centroid) &&
+		   removeFromStableCone2.centroid.isEqual(oldRemoveFromStableCone2.centroid))))
+		iterCount = _maxIterations + 1;
+	    }
+	    for(std::vector<PhysicsTower>::iterator removeTowerIter1 = removeFromStableCone1.towerList.begin();
+		removeTowerIter1 != removeFromStableCone1.towerList.end();
+		removeTowerIter1++)
+	      stableConeIter1->removeTower(*removeTowerIter1);
+	    for(std::vector<PhysicsTower>::iterator removeTowerIter2 = removeFromStableCone2.towerList.begin();
+		removeTowerIter2 != removeFromStableCone2.towerList.end();
+		removeTowerIter2++)
+	      stableConeIter2->removeTower(*removeTowerIter2);
+	  }
+	  overlap.clear();
+	}
+      }
+      stableConeIter2++;
+      isActiveIter2++;
+    }
+  }
+  jets.clear();
+  std::vector<bool>::iterator isActiveIter = isActive.begin();
+  for(std::vector<Cluster>::iterator stableConeIter = stableCones.begin();
+      stableConeIter != stableCones.end();
+      stableConeIter++, isActiveIter++)
+    if(*isActiveIter)
+      jets.push_back(*stableConeIter);
+  sort(jets.begin(),jets.end(),ClusterFourVectorEtGreater());
+}
+
+void JetCluAlgorithm::run(std::vector<PhysicsTower>& towers, std::vector<Cluster>& jets)
+{
+  std::vector<Cluster> seedTowers;
+  makeSeedTowers(towers,seedTowers);
+  std::vector<Cluster> preClusters;
+  buildPreClusters(seedTowers,towers,preClusters);
+  std::vector<Cluster> stableCones;
+  findStableCones(preClusters,towers,stableCones);
+  splitAndMerge(stableCones,jets);
+}
+
+}  // namespace cdf
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/JetCluAlgorithm.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/JetCluAlgorithm.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/JetCluAlgorithm.hh	(revision 5)
@@ -0,0 +1,72 @@
+#ifndef _JETCLU_ALGORITHM_HH_
+#define _JETCLU_ALGORITHM_HH_
+
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from
+// http://www.pa.msu.edu/~huston/Les_Houches_2005/JetClu+Midpoint-StandAlone.tgz
+//
+// Permission to distribute it with FastJet has been granted by Joey
+// Huston (see the COPYING file in the main FastJet directory for
+// details).
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+// History of changes compared to the original JetCluAlgorithm.hh file
+// 
+// 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::cdf namespace
+// 
+// 2006-09-24  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added JetClu+MidPoint to FastJet
+
+#include "PhysicsTower.hh"
+#include "Cluster.hh"
+#include <vector>
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace cdf{
+
+class JetCluAlgorithm
+{
+ private:
+  double _seedThreshold;
+  double _coneRadius;
+  int    _adjacencyCut;
+  int    _maxIterations;
+  int    _iratch;
+  double _overlapThreshold;
+
+ public:
+  JetCluAlgorithm():
+    _seedThreshold(1),
+    _coneRadius(0.7),
+    _adjacencyCut(2),
+    _maxIterations(100),
+    _iratch(1),
+    _overlapThreshold(0.75)
+  {}
+  JetCluAlgorithm(double st, double cr, int ac, int mi, int ir, double ot):
+    _seedThreshold(st),
+    _coneRadius(cr),
+    _adjacencyCut(ac),
+    _maxIterations(mi),
+    _iratch(ir),
+    _overlapThreshold(ot)
+  {}
+  void makeSeedTowers(std::vector<PhysicsTower>& towers, std::vector<Cluster>& seedTowers);
+  void buildPreClusters(std::vector<Cluster>& seedTowers, std::vector<PhysicsTower>& towers, std::vector<Cluster>& preClusters);
+  void findStableCones(std::vector<Cluster>& preClusters, std::vector<PhysicsTower>& towers, std::vector<Cluster>& stableCones);
+  void splitAndMerge(std::vector<Cluster>& stableCones, std::vector<Cluster>& jets);
+  void run(std::vector<PhysicsTower>& towers, std::vector<Cluster>& jets);
+};
+
+}  // namespace cdf
+
+FASTJET_END_NAMESPACE
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/LorentzVector.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/LorentzVector.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/LorentzVector.hh	(revision 5)
@@ -0,0 +1,95 @@
+#ifndef _LORENTZ_VECTOR_HH_
+#define _LORENTZ_VECTOR_HH_
+
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from
+// http://www.pa.msu.edu/~huston/Les_Houches_2005/JetClu+Midpoint-StandAlone.tgz
+//
+// Permission to distribute it with FastJet has been granted by Joey
+// Huston (see the COPYING file in the main FastJet directory for
+// details).
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+// History of changes compared to the original LorentzVector.hh file
+// 
+// 2011-11-14  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * removed some harmless warnings coming with the -Wshadow gcc option
+//
+// 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::cdf namespace
+// 
+// 2008-01-15  Gregory Soyez  <soyez@fastjet.fr>
+// 
+// 	  * fixed issues with compilation under VC (definition of M_PI)
+// 
+// 2007-02-21  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added option of choosing the scale used in the split-merge
+//          procedure (pt [default], Et or mt)
+// 
+// 2006-09-24  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added JetClu+MidPoint to FastJet
+
+#include <cmath>
+
+#ifndef M_PI
+#define M_PI  3.141592653589793238462643383279502884197 
+#endif
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace cdf{
+
+class LorentzVector
+{
+ public:
+
+  double px,py,pz,E;
+
+  LorentzVector(): px(0), py(0), pz(0), E(0) {}
+  LorentzVector(double p1, double p2, double p3, double p0): px(p1), py(p2), pz(p3), E(p0) {}
+  LorentzVector(const LorentzVector& lv): px(lv.px), py(lv.py), pz(lv.pz), E(lv.E) {}
+  double p()   const {return sqrt(px*px + py*py + pz*pz);}
+  double pt()  const {return sqrt(px*px + py*py);}
+  double mt()  const {return sqrt((E-pz)*(E+pz));}
+  double y()   const {return 0.5*log((E + pz)/(E - pz));}
+  double Et()  const {return E/p()*pt();}
+  double eta() const {return 0.5*log((p() + pz)/(p() - pz));}
+  double phi() const
+  {
+    double r = atan2(py,px);
+    if(r < 0)
+      r += 2*M_PI;
+    return r;
+  }
+  void add(LorentzVector v)
+  {
+    px += v.px;
+    py += v.py;
+    pz += v.pz;
+    E  += v.E;
+  }
+  void subtract(LorentzVector v)
+  {
+    px -= v.px;
+    py -= v.py;
+    pz -= v.pz;
+    E  -= v.E;
+  }
+  bool isEqual(LorentzVector v)
+  {
+    return px == v.px && py == v.py && pz == v.pz && E == v.E;
+  }
+};
+
+}  // namespace cdf
+
+FASTJET_END_NAMESPACE
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/MidPointAlgorithm.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/MidPointAlgorithm.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/MidPointAlgorithm.cc	(revision 5)
@@ -0,0 +1,365 @@
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from
+// http://www.pa.msu.edu/~huston/Les_Houches_2005/JetClu+Midpoint-StandAlone.tgz
+//
+// Permission to distribute it with FastJet has been granted by Joey
+// Huston (see the COPYING file in the main FastJet directory for
+// details).
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+// History of changes compared to the original MidPointAlgorithm.cc file
+// 
+// 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::cdf namespace
+// 
+// 2008-01-15  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * put in the volatile fix for midpoint with optimization;
+//          checked regression test, and that speed comes out OK
+// 
+// 
+// 2007-10-16  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added protection to midpoint for cases where no stable cones
+//          are found
+// 
+// 2007-03-10  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added support for the pttilde scale choice in the CDF midpoint code
+//
+// 2007-02-21  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added option of choosing the scale used in the split-merge
+//          procedure (pt [default], Et or mt)
+// 
+// 2006-09-24  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * removed the local_sort method
+// 
+// 2006-09-24  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added JetClu+MidPoint to FastJet
+
+#include "MidPointAlgorithm.hh"
+#include "ClusterComparisons.hh"
+#include <algorithm>
+#include <iostream>
+#include <cmath>
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace cdf{
+
+void MidPointAlgorithm::findStableConesFromSeeds(std::vector<PhysicsTower>& towers, std::vector<Cluster>& stableCones)
+{
+  bool reduceConeSize = true;
+  for(std::vector<PhysicsTower>::iterator towerIter = towers.begin(); towerIter != towers.end(); towerIter++)
+    if(towerIter->fourVector.pt() > _seedThreshold)
+      iterateCone(towerIter->fourVector.y(),towerIter->fourVector.phi(),0,towers,stableCones,reduceConeSize);
+}
+
+void MidPointAlgorithm::findStableConesFromMidPoints(std::vector<PhysicsTower>& towers, std::vector<Cluster>& stableCones)
+{
+  // distanceOK[i-1][j] = Is distance between stableCones i and j (i>j) less than 2*_coneRadius?
+  std::vector< std::vector<bool> > distanceOK;
+  distanceOK.resize(stableCones.size() - 1);
+  for(int nCluster1 = 1; nCluster1 < stableCones.size(); nCluster1++){
+    distanceOK[nCluster1 - 1].resize(nCluster1);
+    double cluster1Rapidity = stableCones[nCluster1].fourVector.y();
+    double cluster1Phi      = stableCones[nCluster1].fourVector.phi();
+    for(int nCluster2 = 0; nCluster2 < nCluster1; nCluster2++){
+      double cluster2Rapidity = stableCones[nCluster2].fourVector.y();
+      double cluster2Phi      = stableCones[nCluster2].fourVector.phi();
+      double dRapidity = fabs(cluster1Rapidity - cluster2Rapidity);
+      double dPhi      = fabs(cluster1Phi      - cluster2Phi);
+      if(dPhi > M_PI)
+        dPhi = 2*M_PI - dPhi;
+      double dR = sqrt(dRapidity*dRapidity + dPhi*dPhi);
+      distanceOK[nCluster1 - 1][nCluster2] = dR < 2*_coneRadius;
+    }
+  }
+
+  // Find all pairs (triplets, ...) of stableCones which are less than 2*_coneRadius apart from each other.
+  std::vector< std::vector<int> > pairs(0);
+  std::vector<int> testPair(0);
+  int maxClustersInPair = _maxPairSize;
+  if(!maxClustersInPair)
+    maxClustersInPair = stableCones.size();
+  addClustersToPairs(testPair,pairs,distanceOK,maxClustersInPair);
+
+  // Loop over all combinations. Calculate MidPoint. Make midPointClusters.
+  bool reduceConeSize = false;
+  for(int iPair = 0; iPair < pairs.size(); iPair++){
+    // Calculate rapidity, phi and pT of MidPoint.
+    LorentzVector midPoint(0,0,0,0);
+    for(int iPairMember = 0; iPairMember < pairs[iPair].size(); iPairMember++)
+      midPoint.add(stableCones[pairs[iPair][iPairMember]].fourVector);
+    iterateCone(midPoint.y(),midPoint.phi(),midPoint.pt(),towers,stableCones,reduceConeSize);
+  }
+
+  //sort(stableCones.begin(),stableCones.end(),ClusterPtGreater());
+  local_sort(stableCones);  // GPS mod. to allow split-merge with various scales
+}
+
+
+void MidPointAlgorithm::iterateCone(volatile double startRapidity, volatile double startPhi, volatile double startPt,
+				    std::vector<PhysicsTower>& towers, std::vector<Cluster>& stableCones, bool reduceConeSize)
+{
+  int nIterations = 0;
+  bool keepJet = true;
+  Cluster trialCone;
+  double iterationConeRadius = _coneRadius;
+  if(reduceConeSize)
+    iterationConeRadius *= sqrt(_coneAreaFraction);
+  while(nIterations++ < _maxIterations + 1 && keepJet){
+    trialCone.clear();
+    // Find particles which should go in the cone.
+    if(nIterations == _maxIterations + 1)
+      iterationConeRadius = _coneRadius;
+    for(std::vector<PhysicsTower>::iterator towerIter = towers.begin(); towerIter != towers.end(); towerIter++){
+      double dRapidity = fabs(towerIter->fourVector.y()   - startRapidity);
+      double dPhi      = fabs(towerIter->fourVector.phi() - startPhi);
+      if(dPhi > M_PI)
+	dPhi = 2*M_PI - dPhi;
+      double dR = sqrt(dRapidity*dRapidity + dPhi*dPhi);
+      if(dR < iterationConeRadius)
+	trialCone.addTower(*towerIter);
+    }
+    if(!trialCone.size())   // Empty cone?
+      keepJet = false;
+    else{
+      if(nIterations <= _maxIterations){
+	volatile double endRapidity = trialCone.fourVector.y();
+	volatile double endPhi      = trialCone.fourVector.phi();
+	volatile double endPt       = trialCone.fourVector.pt();
+	// Do we have a stable cone?
+	if(endRapidity == startRapidity && endPhi == startPhi && endPt == startPt){
+	  // If cone size is reduced, then do one more iteration.
+	  nIterations = _maxIterations;
+	  if(!reduceConeSize)
+	    nIterations++;
+	}
+	else{
+	  // Another iteration.
+	  startRapidity = endRapidity;
+	  startPhi      = endPhi;
+	  startPt       = endPt;
+	}
+      }
+    }
+  }
+
+  if(keepJet){
+    // We have a stable cone.
+    bool identical = false;
+    for(std::vector<Cluster>::iterator stableConeIter = stableCones.begin(); stableConeIter != stableCones.end(); stableConeIter++)
+      if(trialCone.fourVector.isEqual(stableConeIter->fourVector))
+	identical = true;
+    if(!identical)
+      stableCones.push_back(trialCone);
+  }
+}
+
+void MidPointAlgorithm::addClustersToPairs(std::vector<int>& testPair, std::vector< std::vector<int> >& pairs,
+					   std::vector< std::vector<bool> >& distanceOK, int maxClustersInPair)
+{
+  // Recursively adds clusters to pairs, triplets, ... whose mid-points are then calculated.
+
+  // Find StableCone number to start with (either 0 at the beginning or last element of testPair + 1).
+  int nextClusterStart = 0;
+  if(testPair.size())
+    nextClusterStart = testPair.back() + 1;
+  for(int nextCluster = nextClusterStart; nextCluster <= distanceOK.size(); nextCluster++){
+    // Is new SeedCone less than 2*_coneRadius apart from all clusters in testPair?
+    bool addCluster = true;
+    for(int iCluster = 0; iCluster < testPair.size() && addCluster; iCluster++)
+      if(!distanceOK[nextCluster - 1][testPair[iCluster]])
+	addCluster = false;
+    if(addCluster){
+      // Add it to the testPair.
+      testPair.push_back(nextCluster);
+      // If testPair is a pair, add it to pairs.
+      if(testPair.size() > 1)
+	pairs.push_back(testPair);
+      // If not bigger than allowed, find more clusters within 2*_coneRadius.
+      if(testPair.size() < maxClustersInPair)
+	addClustersToPairs(testPair,pairs,distanceOK,maxClustersInPair);
+      // All combinations containing testPair found. Remove last element.
+      testPair.pop_back();
+    }
+  }
+}
+
+void MidPointAlgorithm::splitAndMerge(std::vector<Cluster>& stableCones, std::vector<Cluster>& jets)
+{
+  bool mergingNotFinished = true;
+  while(mergingNotFinished){
+    // Sort the stable cones (highest pt first).
+    //sort(stableCones.begin(),stableCones.end(),ClusterPtGreater());
+    local_sort(stableCones);
+
+    // Start with the highest pt cone.
+    std::vector<Cluster>::iterator stableConeIter1 = stableCones.begin();
+    if(stableConeIter1 == stableCones.end())   // Stable cone list empty?
+      mergingNotFinished = false;
+    else{
+      bool coneNotModified = true;
+      // Determine whether highest pt cone has an overlap with other stable cones.
+      std::vector<Cluster>::iterator stableConeIter2 = stableConeIter1;
+      stableConeIter2++;   // 2nd highest pt cone.
+      while(coneNotModified && stableConeIter2 != stableCones.end()){
+	// Calculate overlap of the two cones.
+	Cluster overlap;
+	for(std::vector<PhysicsTower>::iterator towerIter1 = stableConeIter1->towerList.begin();
+	    towerIter1 != stableConeIter1->towerList.end();
+	    towerIter1++){
+	  bool isInCone2 = false;
+	  for(std::vector<PhysicsTower>::iterator towerIter2 = stableConeIter2->towerList.begin();
+	      towerIter2 != stableConeIter2->towerList.end();
+	      towerIter2++)
+	    if(towerIter1->isEqual(*towerIter2))
+	      isInCone2 = true;
+	  if(isInCone2)
+	    overlap.addTower(*towerIter1);
+	}
+	if(overlap.size()){   // non-empty overlap
+	  coneNotModified = false;
+          // GPS mod to allow various scale choices in split merge --------
+          double overlap_scale, jet2_scale;
+          switch(_smScale) {
+          case SM_pt:
+            overlap_scale = overlap.fourVector.pt();
+            jet2_scale    = stableConeIter2->fourVector.pt();
+            break;
+          case SM_Et:
+            overlap_scale = overlap.fourVector.Et();
+            jet2_scale    = stableConeIter2->fourVector.Et();
+            break;
+          case SM_mt:
+            overlap_scale = overlap.fourVector.mt();
+            jet2_scale    = stableConeIter2->fourVector.mt();
+            break;
+          case SM_pttilde:
+            overlap_scale = overlap.pt_tilde;
+            jet2_scale    = stableConeIter2->pt_tilde;
+            break;
+          default:
+            std::cerr << "Unrecognized value for _smScale: " 
+                      << _smScale << std::endl;
+            exit(-1);
+          }
+	  if(overlap_scale >= _overlapThreshold*jet2_scale){
+          // end of GPS modification ---------------------------
+          //if(overlap.fourVector.pt() >= _overlapThreshold*stableConeIter2->fourVector.pt()){
+	    // Merge the two cones.
+	    for(std::vector<PhysicsTower>::iterator towerIter2 = stableConeIter2->towerList.begin();
+		towerIter2 != stableConeIter2->towerList.end();
+		towerIter2++){
+	      bool isInOverlap = false;
+	      for(std::vector<PhysicsTower>::iterator overlapTowerIter = overlap.towerList.begin();
+		  overlapTowerIter != overlap.towerList.end();
+		  overlapTowerIter++)
+		if(towerIter2->isEqual(*overlapTowerIter))
+		  isInOverlap = true;
+	      if(!isInOverlap)
+		stableConeIter1->addTower(*towerIter2);
+	    }
+	    // Remove the second cone.
+	    stableCones.erase(stableConeIter2);
+	  }
+	  else{
+	    // Separate the two cones.
+	    // Which particle goes where?
+	    std::vector<PhysicsTower> removeFromCone1,removeFromCone2;
+	    for(std::vector<PhysicsTower>::iterator towerIter = overlap.towerList.begin();
+		towerIter != overlap.towerList.end();
+		towerIter++){
+	      double towerRapidity = towerIter->fourVector.y();
+	      double towerPhi      = towerIter->fourVector.phi();
+	      // Calculate distance from cone 1.
+	      double dRapidity1 = fabs(towerRapidity - stableConeIter1->fourVector.y());
+	      double dPhi1      = fabs(towerPhi      - stableConeIter1->fourVector.phi());
+	      if(dPhi1 > M_PI)
+		dPhi1 = 2*M_PI - dPhi1;
+	      double dRJet1 = sqrt(dRapidity1*dRapidity1 + dPhi1*dPhi1);
+	      // Calculate distance from cone 2.
+	      double dRapidity2 = fabs(towerRapidity - stableConeIter2->fourVector.y());
+	      double dPhi2      = fabs(towerPhi      - stableConeIter2->fourVector.phi());
+	      if(dPhi2 > M_PI)
+		dPhi2 = 2*M_PI - dPhi2;
+	      double dRJet2 = sqrt(dRapidity2*dRapidity2 + dPhi2*dPhi2);
+	      if(dRJet1 < dRJet2)
+		// Particle is closer to cone 1. To be removed from cone 2.
+		removeFromCone2.push_back(*towerIter);
+	      else
+		// Particle is closer to cone 2. To be removed from cone 1.
+		removeFromCone1.push_back(*towerIter);
+	    }
+	    // Remove particles in the overlap region from the cones to which they have the larger distance.
+	    for(std::vector<PhysicsTower>::iterator towerIter = removeFromCone1.begin();
+		towerIter != removeFromCone1.end();
+		towerIter++)
+	      stableConeIter1->removeTower(*towerIter);
+	    for(std::vector<PhysicsTower>::iterator towerIter = removeFromCone2.begin();
+		towerIter != removeFromCone2.end();
+		towerIter++)
+	      stableConeIter2->removeTower(*towerIter);
+	  }
+	}
+	stableConeIter2++;
+      }
+      if(coneNotModified){
+	// Cone 1 has no overlap with any of the other cones and can become a jet.
+	jets.push_back(*stableConeIter1);
+	stableCones.erase(stableConeIter1);
+      }
+    }
+  }
+
+  //sort(jets.begin(),jets.end(),ClusterPtGreater());
+  local_sort(jets); // GPS mod. to allow split-merge with various scales
+}
+
+
+
+void MidPointAlgorithm::local_sort(std::vector<Cluster>& clusters) {
+  switch(_smScale) {
+  case SM_pt:
+    sort(clusters.begin(),clusters.end(),ClusterPtGreater());
+    break;
+  case SM_Et:
+    sort(clusters.begin(),clusters.end(),ClusterFourVectorEtGreater());
+    break;
+  case SM_mt:
+    sort(clusters.begin(),clusters.end(),ClusterMtGreater());
+    break;
+  case SM_pttilde:
+    sort(clusters.begin(),clusters.end(),ClusterPtTildeGreater());
+    break;
+  default:
+    std::cerr << "Unrecognized value for _smScale: " << _smScale << std::endl;
+    exit(-1);
+  }
+}
+
+
+
+void MidPointAlgorithm::run(std::vector<PhysicsTower>& towers, std::vector<Cluster>& jets)
+{
+  std::vector<Cluster> stableCones;
+  findStableConesFromSeeds(towers,stableCones);
+  // GPS addition to prevent crashes if no stable cones
+  // are found (e.g. all particles below seed threshold)
+  if (stableCones.size() > 0) {
+    findStableConesFromMidPoints(towers,stableCones);
+    splitAndMerge(stableCones,jets);
+  }
+}
+
+}  // namespace cdf
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/MidPointAlgorithm.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/MidPointAlgorithm.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/MidPointAlgorithm.hh	(revision 5)
@@ -0,0 +1,99 @@
+#ifndef _MIDPOINT_ALGORITHM_HH_
+#define _MIDPOINT_ALGORITHM_HH_
+
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from
+// http://www.pa.msu.edu/~huston/Les_Houches_2005/JetClu+Midpoint-StandAlone.tgz
+//
+// Permission to distribute it with FastJet has been granted by Joey
+// Huston (see the COPYING file in the main FastJet directory for
+// details).
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+// History of changes compared to the original MidPointAlgorithm.hh file
+// 
+// 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::cdf namespace
+// 
+// 2007-03-10  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added support for the pttilde scale choice in the CDF midpoint code
+//
+// 2007-02-21  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added option of choosing the scale used in the split-merge
+//          procedure (pt [default], Et or mt)
+// 
+// 2006-09-24  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * removed the local_sort method
+// 
+// 2006-09-24  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added JetClu+MidPoint to FastJet
+
+
+#include "PhysicsTower.hh"
+#include "Cluster.hh"
+#include <vector>
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace cdf{
+
+class MidPointAlgorithm
+{
+ public:
+  enum SplitMergeScale {SM_pt, SM_Et, SM_mt, SM_pttilde};
+
+ private:
+  double _seedThreshold;
+  double _coneRadius;
+  double _coneAreaFraction;
+  int    _maxPairSize;
+  int    _maxIterations;
+  double _overlapThreshold;
+  SplitMergeScale _smScale;
+
+ public:
+  MidPointAlgorithm():
+    _seedThreshold(1),
+    _coneRadius(0.7),
+    _coneAreaFraction(0.25),
+    _maxPairSize(2),
+    _maxIterations(100),
+    _overlapThreshold(0.75),
+    _smScale(SM_pt)
+  {}
+  MidPointAlgorithm(double st, double cr, double caf, int mps, int mi, double ot, SplitMergeScale sm = SM_pt):
+    _seedThreshold(st),
+    _coneRadius(cr),
+    _coneAreaFraction(caf),
+    _maxPairSize(mps),
+    _maxIterations(mi),
+    _overlapThreshold(ot),
+    _smScale(sm)
+  {}
+  void findStableConesFromSeeds(std::vector<PhysicsTower>& particles, std::vector<Cluster>& stableCones);
+  void findStableConesFromMidPoints(std::vector<PhysicsTower>& particles, std::vector<Cluster>& stableCones);
+  void iterateCone(volatile double startRapidity, volatile double startPhi, volatile double startPt, std::vector<PhysicsTower>& particles,
+		   std::vector<Cluster>& stableCones, bool reduceConeSize);
+  void addClustersToPairs(std::vector<int>& testPair, std::vector< std::vector<int> >& pairs,
+			  std::vector< std::vector<bool> >& distanceOK, int maxClustersInPair);
+  void splitAndMerge(std::vector<Cluster>& stableCones, std::vector<Cluster>& jets);
+  void run(std::vector<PhysicsTower>& particles, std::vector<Cluster>& jets);
+
+  /// sort the clusters into whatever order is 
+  void local_sort(std::vector<Cluster>&);
+
+};
+
+}  // namespace cdf
+
+FASTJET_END_NAMESPACE
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/PhysicsTower.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/PhysicsTower.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/PhysicsTower.hh	(revision 5)
@@ -0,0 +1,74 @@
+#ifndef _PHYSICS_TOWER_HH_
+#define _PHYSICS_TOWER_HH_
+
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from
+// http://www.pa.msu.edu/~huston/Les_Houches_2005/JetClu+Midpoint-StandAlone.tgz
+//
+// Permission to distribute it with FastJet has been granted by Joey
+// Huston (see the COPYING file in the main FastJet directory for
+// details).
+// Changes from the original file are listed below.
+//----------------------------------------------------------------------
+
+// History of changes compared to the original PhysicsTower.hh file
+// 
+// 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * put the code in the fastjet::cdf namespace
+// 
+// 2008-08-15  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * switched JetClu plugin over to proper indexed tracking of
+//          jet contents rather than a (dodgy) map based on particle
+//          energies 
+// 
+// 2006-09-24  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * replaced the private m_index variable by a public fjindex
+//          one for tracking within FastJet
+// 
+// 2006-09-24  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added JetClu+MidPoint to FastJet
+
+#include "LorentzVector.hh"
+#include "CalTower.hh"
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace cdf{
+
+class PhysicsTower
+{
+ public:
+
+  LorentzVector fourVector;
+  CalTower calTower;
+
+  PhysicsTower(): fourVector(LorentzVector()), calTower(CalTower()), fjindex(-1) {}
+  PhysicsTower(LorentzVector v, CalTower c): fourVector(v), calTower(c), fjindex(-1) {}
+  PhysicsTower(const PhysicsTower& p): fourVector(p.fourVector), calTower(p.calTower), fjindex(p.fjindex) {}
+  PhysicsTower(CalTower c):
+    fourVector(LorentzVector(c.Et*cos(c.phi),c.Et*sin(c.phi),c.Et*sinh(c.eta),c.Et*cosh(c.eta))), calTower(c), fjindex(-1) {}
+  PhysicsTower(LorentzVector v): fourVector(v), calTower(CalTower(v.Et(),v.eta(),v.phi())), fjindex(-1) {}
+  double Et()   const {return calTower.Et;}
+  double eta()  const {return calTower.eta;}
+  double phi()  const {return calTower.phi;}
+  int    iEta() const {return calTower.iEta;}
+  int    iPhi() const {return calTower.iPhi;}
+  bool isEqual(PhysicsTower p)
+  {
+    return fourVector.isEqual(p.fourVector) && calTower.isEqual(p.calTower);
+  }
+  /// addition by GPS (2008-08-15) for tracking within fastjet
+  int fjindex;
+};
+
+} // namespace cdf
+
+FASTJET_END_NAMESPACE
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/fastjet/CDFJetCluPlugin.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/fastjet/CDFJetCluPlugin.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/fastjet/CDFJetCluPlugin.hh	(revision 5)
@@ -0,0 +1,109 @@
+//STARTHEADER
+// $Id: CDFJetCluPlugin.hh 2758 2011-11-24 08:31:58Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __CDFJETCLUPLUGIN_HH__
+#define __CDFJETCLUPLUGIN_HH__
+
+#include "fastjet/JetDefinition.hh"
+#include "fastjet/PseudoJet.hh"
+#include <map>
+
+// questionable whether this should be in fastjet namespace or not...
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+/// @ingroup plugins
+/// \class CDFJetCluPlugin
+/// Implementation of the JetClu algorithm from CDF (plugin for
+/// fastjet-v2.1 upwards)
+class CDFJetCluPlugin : public JetDefinition::Plugin {
+public:
+  /// a compact constructor
+  CDFJetCluPlugin (double   cone_radius_in, 
+		   double   overlap_threshold_in, 
+		   double   seed_threshold_in = 1.0,
+		   int      iratch_in = 1) : 
+    _seed_threshold    ( seed_threshold_in    ),    
+    _cone_radius       ( cone_radius_in       ),
+    _adjacency_cut     (   2                  ),
+    _max_iterations    ( 100                  ),
+    _iratch            ( iratch_in            ),
+    _overlap_threshold ( overlap_threshold_in )  {}
+
+  /// a constructor that looks like the one provided by CDF
+  CDFJetCluPlugin (double seed_threshold_in   ,	 
+		   double cone_radius_in      ,
+		   int    adjacency_cut_in    ,
+		   int    max_iterations_in   ,
+		   int    iratch_in           ,
+		   double overlap_threshold_in) :
+    _seed_threshold    (seed_threshold_in    ),    
+    _cone_radius       (cone_radius_in       ),
+    _adjacency_cut     (adjacency_cut_in     ),
+    _max_iterations    (max_iterations_in    ),
+    _iratch            (iratch_in            ),
+    _overlap_threshold (overlap_threshold_in )  {}
+
+  // some functions to return info about parameters
+  double seed_threshold    () const {return _seed_threshold    ;}
+  double cone_radius       () const {return _cone_radius       ;}
+  int    adjacency_cut     () const {return _adjacency_cut     ;}
+  int    max_iterations    () const {return _max_iterations    ;}
+  int    iratch            () const {return _iratch            ;}
+  double overlap_threshold () const {return _overlap_threshold ;}
+
+
+  // the things that are required by base class
+  virtual std::string description () const;
+  virtual void run_clustering(ClusterSequence &) const;
+  /// the plugin mechanism's standard way of accessing the jet radius
+  virtual double R() const {return cone_radius();}
+                      
+private:
+
+  double _seed_threshold   ;
+  double _cone_radius      ;
+  int    _adjacency_cut    ;
+  int    _max_iterations   ;
+  int    _iratch           ;
+  double _overlap_threshold;
+
+  /// given a jet try inserting its energy into the map -- if that
+  /// energy entry already exists, modify the jet infinitesimally so
+  /// as ensure that the jet energy is unique
+  void _insert_unique (PseudoJet & jet, std::map<double,int> & jetmap) const;
+
+  static bool _first_time;
+
+  /// print a banner for reference to the 3rd-party code
+  void _print_banner(std::ostream *ostr) const;
+};
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
+
+#endif // __CDFJETCLUPLUGIN_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/fastjet/CDFMidPointPlugin.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/fastjet/CDFMidPointPlugin.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CDFCones/fastjet/CDFMidPointPlugin.hh	(revision 5)
@@ -0,0 +1,180 @@
+//STARTHEADER
+// $Id: CDFMidPointPlugin.hh 2758 2011-11-24 08:31:58Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __CDFMIDPOINTPLUGIN_HH__
+#define __CDFMIDPOINTPLUGIN_HH__
+
+#include "fastjet/JetDefinition.hh"
+
+// questionable whether this should be in fastjet namespace or not...
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+//
+/// @ingroup plugins
+/// \class CDFMidPointPlugin
+/// Implementation of the MidPoint algorithm from CDF (plugin for
+/// fastjet-v2.1 upwards)
+///
+/// A plugin for fastjet-v2.1 that provides an interface to the CDF
+/// midpoint algorithm
+///
+/// CDFMidPointPlugin is a plugin for fastjet (v2.1 upwards) that
+/// provides an interface to the CDF version of Run-II iterative cone
+/// algorithm with midpoint seeds (also known as the Iterative Legacy
+/// Cone Algorithm, ILCA).
+///
+/// The CDF code has been taken from Joey Huston's webpage
+/// http://www.pa.msu.edu/~huston/Les_Houches_2005/Les_Houches_SM.html
+///
+/// Note that the CDF midpoint code contains options that go beyond
+/// those described in the Tevatron run-II document (hep-ex/0005012),
+/// notably search-cones, as described in hep-ph/0111434, and
+/// midpoints bewteen multiplets of stable cones.
+///
+/// Additionally, the version of the CDF midpoint code distributed
+/// here has been modified by the FastJet authors, so as to allow one
+/// to choose the scale used in the split-merge step.
+//
+//----------------------------------------------------------------------
+class CDFMidPointPlugin : public JetDefinition::Plugin {
+public:
+  /// the choice of scale to be used in the split-merge step
+  // NB: just replicates what we've added to the CDF midpoint code
+  enum SplitMergeScale {SM_pt, SM_Et, SM_mt, SM_pttilde};
+
+  ///
+  /// A CDFMidPointPlugin constructor that looks like the one provided
+  /// by CDF. Its arguments should have the following meaning:
+  ///
+  /// - seed_threshold: minimum pt for a particle to be considered 
+  ///   a seed of the iteration.
+  ///
+  /// - cone_radius: standard meaning
+  ///
+  /// - cone_area_fraction: stable-cones are searched for with a
+  ///   radius Rsearch = R * sqrt(cone_area_fraction), and then
+  ///   expanded to size R afterwards; note (hep-ph/0610012) that this
+  ///   introduces IR unsafety at NLO for X+2-jet observables (where X
+  ///   any hard object).
+  ///
+  /// - max_pair_size: "midpoints" can be added between pairs of
+  ///   stable cones, triplets of stable cones, etc.; max_pair_size
+  ///   indicates the maximum number of stable cones that are
+  ///   assembled when adding midpoints.
+  ///
+  /// - max_iterations: the maximum number of iterations to carry out
+  ///   when looking for a stable cone.
+  ///
+  /// - overlap_threshold: if
+  ///     (overlapping_Et)/(Et_of_softer_protojet) < overlap_threshold,
+  ///   overlapping jets are split, otherwise they are merged.
+  ///
+  /// - sm_scale: a choice for the scale to be used in the split-merge
+  ///   step (both for ordering the momenta and quantifying the
+  ///   overlap); the three options are
+  ///
+  ///    . SM_pt: pt (default -- source of small IR safety issue in purely
+  ///      hadronic events)
+  ///
+  ///    . SM_Et: Et (not boost invariant, reduces to mt at zero rapidity and
+  ///      to pt and infinite rapidity)
+  ///
+  ///    . SM_mt: transverse mass = sqrt(m^2+pt^2)
+  ///
+  CDFMidPointPlugin (
+                     double seed_threshold_in     ,	 
+		     double cone_radius_in        ,
+		     double cone_area_fraction_in ,
+		     int    max_pair_size_in      ,
+		     int    max_iterations_in     ,
+		     double overlap_threshold_in  ,
+                     SplitMergeScale sm_scale_in = SM_pt) :
+    _seed_threshold     (seed_threshold_in     ),    
+    _cone_radius        (cone_radius_in        ),
+    _cone_area_fraction (cone_area_fraction_in ),
+    _max_pair_size      (max_pair_size_in      ),
+    _max_iterations     (max_iterations_in     ),
+    _overlap_threshold  (overlap_threshold_in  ),
+    _sm_scale           (sm_scale_in)             {}
+
+  /// a compact constructor
+  ///
+  /// NB: as of version 2.4, the default value for the
+  /// overlap_threshold threshold has been removed, to avoid
+  /// misleading people into using the value of 0.5 without thinking,
+  /// which is known to have adverse effects in high-noise
+  /// environments. A recommended value is 0.75.
+  CDFMidPointPlugin (double   cone_radius_in, 
+		     double   overlap_threshold_in,// = 0.5, 
+		     double   seed_threshold_in = 1.0,	     
+		     double   cone_area_fraction_in = 1.0) : 
+    _seed_threshold     (seed_threshold_in     ),    
+    _cone_radius        (cone_radius_in        ),
+    _cone_area_fraction (cone_area_fraction_in ),
+    _max_pair_size      (2                     ),
+    _max_iterations     (100                   ),
+    _overlap_threshold  (overlap_threshold_in  ),
+    _sm_scale           (SM_pt)                {}
+
+
+  // some functions to return info about parameters
+  double seed_threshold     () const {return _seed_threshold     ;}
+  double cone_radius        () const {return _cone_radius        ;}
+  double cone_area_fraction () const {return _cone_area_fraction ;}
+  int    max_pair_size      () const {return _max_pair_size      ;}
+  int    max_iterations     () const {return _max_iterations     ;}
+  double overlap_threshold  () const {return _overlap_threshold  ;}
+
+
+  // the things that are required by base class
+  virtual std::string description () const;
+  virtual void run_clustering(ClusterSequence &) const;
+  /// the plugin mechanism's standard way of accessing the jet radius
+  virtual double R() const {return cone_radius();}
+                      
+private:
+
+  double _seed_threshold    ;
+  double _cone_radius       ;
+  double _cone_area_fraction;
+  int    _max_pair_size     ;
+  int    _max_iterations    ;
+  double _overlap_threshold ;
+  SplitMergeScale _sm_scale ;
+
+  static bool _first_time;
+
+  /// print a banner for reference to the 3rd-party code
+  void _print_banner(std::ostream *ostr) const;
+};
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
+
+#endif // __CDFMIDPOINTPLUGIN_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CMSIterativeCone/CMSIterativeConePlugin.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CMSIterativeCone/CMSIterativeConePlugin.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CMSIterativeCone/CMSIterativeConePlugin.cc	(revision 5)
@@ -0,0 +1,244 @@
+//STARTHEADER
+// $Id: CMSIterativeConePlugin.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2007-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+// Copyright (c) ????-????, CMS [for the iterative-cone code itself]
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet. It contains code that has been
+// obtained from the CMS collaboration, revision 1.14 of the
+// CMSIterativeConeAlgorithm.cc file in CMSSW, see
+//   http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/RecoJets/JetAlgorithms/src/CMSIterativeConeAlgorithm.cc?hideattic=0&revision=1.14&view=markup
+//
+// Permission has been granted by the CMS collaboration to release it
+// in FastJet under the terms of the GNU Public License(v2) (see the
+// COPYING file in the main FastJet directory for details).
+// Changes from the original file are listed below.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+// List of changes compared to the original CMS code (revision 1.14 of
+// CMSIterativeConeAlgorithm.cc)
+//
+// 2009-05-10  Gavin Salam  <salam@lpthe.jussieu.fr>
+//
+//        * added radius and seed threshold information in the plugin
+//          description
+//
+// 2009-01-06  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * Encapsulated the CMS code into a plugin for FastJet
+//        * inserted the deltaPhi and deltaR2 codes from 
+//            DataFormats/Math/interface/deltaPhi.h (rev 1.1)
+//            DataFormats/Math/interface/deltaR.h   (rev 1.2)
+//        * Adapted the code to use PseusoJet rather than 'InputItem'
+//          and 'InputCollection'
+//        * use the FastJet clustering history structures instead of
+//          the ProtoJet one used by CMS.
+
+
+// fastjet stuff
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/CMSIterativeConePlugin.hh"
+
+// other stuff
+#include <vector>
+#include <list>
+#include <sstream>
+#include "SortByEt.h"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+using namespace cms;
+
+//------------------------------------------------------
+// some tools
+//------------------------------------------------------
+template <class T> 
+T deltaPhi (T phi1, T phi2) { 
+  T result = phi1 - phi2;
+  while (result > M_PI) result -= 2*M_PI;
+  while (result <= -M_PI) result += 2*M_PI;
+  return result;
+}
+
+template <class T>
+T deltaR2 (T eta1, T phi1, T eta2, T phi2) {
+  T deta = eta1 - eta2;
+  T dphi = deltaPhi (phi1, phi2);
+  return deta*deta + dphi*dphi;
+}
+
+//------------------------------------------------------
+bool CMSIterativeConePlugin::_first_time = true;
+
+string CMSIterativeConePlugin::description () const {
+  ostringstream desc;
+  desc << "CMSIterativeCone plugin with R = " << theConeRadius << " and seed threshold = " << theSeedThreshold;
+  return desc.str();
+}
+
+void CMSIterativeConePlugin::run_clustering(ClusterSequence & clust_seq) const {
+  // print a banner if we run this for the first time
+  _print_banner(clust_seq.fastjet_banner_stream());
+
+  //make a list of input objects ordered by ET
+  //cout << "copying the list of particles" << endl;
+  list<PseudoJet> input;
+  for (unsigned int i=0 ; i<clust_seq.jets().size() ; i++) {
+    input.push_back(clust_seq.jets()[i]);
+  }
+  NumericSafeGreaterByEt<PseudoJet> compCandidate;
+  //cout << "sorting" << endl;
+  input.sort(compCandidate);
+
+  //find jets
+  //cout << "launching the main loop" << endl;
+  while( !input.empty() && (input.front().Et() > theSeedThreshold )) {
+    //cone centre 
+    double eta0=input.front().eta();
+    double phi0=input.front().phi();
+    //protojet properties
+    double eta=0;
+    double phi=0;
+    double et=0;
+    //list of towers in cone
+    list< list<PseudoJet>::iterator> cone;
+    for(int iteration=0;iteration<100;iteration++){
+      //cout << "iterating" << endl;
+      cone.clear();
+      eta=0;
+      phi=0;
+      et=0;
+      for(list<PseudoJet>::iterator inp=input.begin();
+	  inp!=input.end();inp++){
+	const PseudoJet tower = *inp;	
+	if( deltaR2(eta0,phi0,tower.eta(),tower.phi()) < 
+	    theConeRadius*theConeRadius) {
+	  double tower_et = tower.Et();	  
+          cone.push_back(inp);
+          eta+= tower_et*tower.eta();
+          double dphi=tower.phi()-phi0;
+          if(dphi>M_PI) dphi-=2*M_PI;
+          else if(dphi<=-M_PI) dphi+=2*M_PI;
+          phi+=tower_et*dphi;
+          et +=tower_et;
+        }
+      }
+      eta=eta/et;
+      phi=phi0+phi/et;
+      if(phi>M_PI)phi-=2*M_PI;
+      else if(phi<=-M_PI)phi+=2*M_PI;
+      
+      if(fabs(eta-eta0)<.001 && fabs(phi-phi0)<.001) break;//stable cone found
+      eta0=eta;
+      phi0=phi;
+    }
+
+    //cout << "make the jet final" << endl;
+
+    //make a final jet and remove the jet constituents from the input list 
+    //  InputCollection jetConstituents;     
+    //  list< list<InputItem>::iterator>::const_iterator inp;
+    //  for(inp=cone.begin();inp!=cone.end();inp++)  {
+    //    jetConstituents.push_back(**inp);
+    //    input.erase(*inp);
+    //  }
+    //  fOutput->push_back (ProtoJet (jetConstituents));
+    //
+    // IMPORTANT NOTE:
+    //   while the stability of the stable cone is tested using the Et
+    //   scheme recombination, the final jet uses E-scheme
+    //   recombination.
+    //
+    // The technique used here is the same as what we already used for
+    // SISCone except that we act on the 'cone' list.
+    // We successively merge the particles that make up the cone jet
+    // until we have all particles in it.  We start off with the zeroth
+    // particle.
+    list< list<PseudoJet>::iterator>::const_iterator inp;
+    inp = cone.begin();
+    int jet_k = (*inp)->cluster_hist_index();
+    // gps tmp
+    //float px=(*inp)->px(), py=(*inp)->py(), pz=(*inp)->pz(), E = (*inp)->E();
+
+    // remove the particle from the list and jump to the next one
+    input.erase(*inp);
+    inp++;
+
+    // now loop over the remaining particles
+    while (inp != cone.end()){
+      // take the last result of the merge
+      int jet_i = jet_k;
+      // and the next element of the jet
+      int jet_j = (*inp)->cluster_hist_index();
+      // and merge them (with a fake dij)
+      double dij = 0.0;
+
+      // create the new jet by hand so that we can adjust its user index
+      // Note again the use of the E-scheme recombination here!
+      PseudoJet newjet = clust_seq.jets()[jet_i] + clust_seq.jets()[jet_j];
+
+      // gps tmp to try out floating issues
+      //px+=(*inp)->px(), py+=(*inp)->py(), pz+=(*inp)->pz(), E += (*inp)->E();
+      //PseudoJet newjet(px,py,pz,E);
+        
+      clust_seq.plugin_record_ij_recombination(jet_i, jet_j, dij, newjet, jet_k);
+
+      // remove the particle from the list and jump to the next one
+      input.erase(*inp);
+      inp++;
+    }
+
+    // we have merged all the jet's particles into a single object, so now
+    // "declare" it to be a beam (inclusive) jet.
+    // [NB: put a sensible looking d_iB just to be nice...]
+    double d_iB = clust_seq.jets()[jet_k].perp2();
+    clust_seq.plugin_record_iB_recombination(jet_k, d_iB);
+
+
+  } //loop over seeds ended
+    
+}
+
+// print a banner for reference to the 3rd-party code
+void CMSIterativeConePlugin::_print_banner(ostream *ostr) const{
+  if (! _first_time) return;
+  _first_time=false;
+
+  // make sure the user has not set the banner stream to NULL
+  if (!ostr) return;  
+
+  (*ostr) << "#-------------------------------------------------------------------------" << endl;
+  (*ostr) << "# You are running the CMS Iterative Cone plugin for FastJet               " << endl;
+  (*ostr) << "# Original code by the CMS collaboration adapted by the FastJet authors   " << endl;
+  (*ostr) << "# If you use this plugin, please cite                                     " << endl;
+  (*ostr) << "#   G. L. Bayatian et al. [CMS Collaboration],                            " << endl;
+  (*ostr) << "#   CMS physics: Technical design report.                                 " << endl;
+  (*ostr) << "# in addition to the usual FastJet reference.                             " << endl;
+  (*ostr) << "#-------------------------------------------------------------------------" << endl;
+
+  // make sure we really have the output done.
+  ostr->flush();
+}
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CMSIterativeCone/README
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CMSIterativeCone/README	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CMSIterativeCone/README	(revision 5)
@@ -0,0 +1,32 @@
+Note on the implementation of the CMS Iterative Plugin
+
+The code is initially the CMSSW implementation in
+CMSIterativeConeAlgorithm.cc in /CMSSW/RecoJets/JetAlgorithms
+(more precisely, Revision 14 of the cc file)
+
+To avoid importing too many files from CMSSW, we did a couple of
+modifications starting from the CMSIterativeConeAlgorithm file:
+
+ - directly used the FastJet PseudoJet instead of the InputItem
+   present initially. Note that access to the info then has to be done
+   using . instead of -> which implies a few small modifications here
+   and there.
+
+ - added a small piece of code to compute Et. That peice of code is
+   the same as tracked down in the CMS code. It comes from the Root
+   Lorentzvector, more precisely, the PxPyPzE4D implementation.
+
+ - The ordering in Et, NumericSafeGreaterByEt, is imported from
+   EtComparator.h in PhysicsTools/Utilities/
+
+ - The DeltaR2 computation is imported from DeltaR.cc and DeltaPhi.cc
+   in CMSSW/DataFormats/Math
+
+ - finally, instead of the ProtoJet construction, we use the
+   ClusterSequence-compatible clustering. That one follows the line of
+   what is done in the SISCone plugin. Note that ve've checked in the
+   CMSSZ code that the protojet is indeed reconstructed using E-scheme
+   recombination (while the stability test is done using Et-scheme)
+
+Finally, we want to thank Andreas Oehler for pointing us to the CMS
+code.
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CMSIterativeCone/SortByEt.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CMSIterativeCone/SortByEt.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CMSIterativeCone/SortByEt.h	(revision 5)
@@ -0,0 +1,82 @@
+#ifndef __CMS_ITERATIVE_CONE__SORT_BY_ET_H__
+#define __CMS_ITERATIVE_CONE__SORT_BY_ET_H__
+
+//STARTHEADER
+// $Id: SortByEt.h 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) ????-????, CMS collaboration
+// Copyright (c) 2009-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez [for the changes listed below]
+//
+//----------------------------------------------------------------------
+// This file distributed with FastJet has been obtained from the CMS
+// collaboration, revision 1.2 of the EtComparator.h file in CMSSW,
+// see
+//   http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/Utilities/interface/EtComparator.h?hideattic=0&revision=1.2&view=markup
+//
+// Permission has been granted by the CMS collaboration to release it
+// in FastJet under the terms of the GNU Public License(v2) (see the
+// COPYING file in the main FastJet directory for details).
+// Changes from the original file are listed below.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+// List of changes compared to the original CMS code (revision 1.2 of
+// EtComparator.h)
+//
+// 2009-01-06  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * Extracted (only) NumericSafeGreaterByEt from the CMS code
+//          and adapted it to act on PseudoJet rather than CMS types
+//          for 4-momenta
+//        * Put the code in a fastjet::cms namespace
+
+#include <limits>
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace cms{
+
+template <class T>
+struct NumericSafeGreaterByEt {
+  typedef T first_argument_type;
+  typedef T second_argument_type;
+  bool operator()(const T& a1, const T& a2) {
+    // FastJet::PseudoJet does not provide a direct access to Et2
+    // Plus, we want it to be computed in the same way as in the CMS
+    // code (actually the Root code that is used by CMS)
+    double et1 = a1.Et();
+    double et2 = a2.Et();
+
+    // now we can come back to the CMS code
+    return
+      fabs (et1-et2) > std::numeric_limits<double>::epsilon() ? et1 > et2 :
+      fabs (a1.px()-a2.px()) > std::numeric_limits<double>::epsilon() ? a1.px() > a2.px() :
+      a1.pz() > a2.pz();
+  }
+};
+
+}  // namespace cms
+
+FASTJET_END_NAMESPACE
+
+
+#endif   // __CMS_ITERATIVE_CONE__SORT_BY_ET_H__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CMSIterativeCone/fastjet/CMSIterativeConePlugin.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CMSIterativeCone/fastjet/CMSIterativeConePlugin.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/CMSIterativeCone/fastjet/CMSIterativeConePlugin.hh	(revision 5)
@@ -0,0 +1,91 @@
+//STARTHEADER
+// $Id: CMSIterativeConePlugin.hh 1508 2009-04-10 22:46:49Z soyez $
+//
+// Copyright (c) 2007-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __CMSITERATIVECONEPLUGIN_HH__
+#define __CMSITERATIVECONEPLUGIN_HH__
+
+#include "fastjet/JetDefinition.hh"
+
+// questionable whether this should be in fastjet namespace or not...
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+// forward declaration to reduce includes
+class PseudoJet;
+
+//----------------------------------------------------------------------
+//
+
+/// @ingroup plugins
+/// \class CMSIterativeConePlugin
+/// Implementation of the CMS Iterative Cone (plugin for fastjet v2.4 upwards)
+class CMSIterativeConePlugin : public JetDefinition::Plugin {
+public:
+  /// Main constructor for the CMSIterativeCone Plugin class.  
+  ///
+  /// The arguments are
+  ///   ConeRadius      the radius of the cone
+  ///   SeedThreshold   a threshold for the seeds to iterate from
+  ///
+  /// NOTE: to be more coherent with all other fastjet plugins,
+  ///       we've put the radius before the seed threshold. 
+  ///       CMS does the opposite.
+  ///       In this way, we also put a default value of 0 for the 
+  ///       seed threshold.
+  CMSIterativeConePlugin (double ConeRadius, double SeedThreshold=1.0) :
+    theConeRadius(ConeRadius), theSeedThreshold(SeedThreshold){}
+
+  /// copy constructor
+  CMSIterativeConePlugin (const CMSIterativeConePlugin & plugin) {
+    *this = plugin;
+  }
+
+  // the things that are required by base class
+  virtual std::string description () const;
+  virtual void run_clustering(ClusterSequence &) const;
+
+  /// the plugin mechanism's standard way of accessing the jet radius
+  /// here we return the R of the last alg in the list
+  virtual double R() const {return theConeRadius;}
+
+  /// get the seed threshold
+  virtual double seed_threshold() const {return theSeedThreshold;}
+
+private:
+  double theConeRadius;     ///< cone radius
+  double theSeedThreshold;  ///< seed threshold
+
+  static bool _first_time;
+
+  /// print a banner for reference to the 3rd-party code
+  void _print_banner(std::ostream *ostr) const;
+};
+
+FASTJET_END_NAMESPACE        // defined in fastjet/internal/base.hh
+
+#endif // __CMSITERATIVECONEPLUGIN_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/ConeClusterAlgo.hpp
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/ConeClusterAlgo.hpp	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/ConeClusterAlgo.hpp	(revision 5)
@@ -0,0 +1,914 @@
+//////////////////////////////////////////////////////////////
+//  File: ConeClusterAlgo.hpp                                 
+//
+//  Author: G. Le Meur & F. Touze
+//
+//  Created: 15-JUNE-1998        
+//
+//  Purpose: make jet clusters using fixed cone like algorithm
+//           implemented in RUNI.
+//
+//  Modified: 
+//  28-OCT-1998 to use KinemUtil (S. Protopopescu)
+//   8-JAN-1999: Laurent Duflot
+//     . correct bugs in getItemsInCone and updateEtaPhiEt for jets
+//       overlapping the phi=0 line
+//     . change abs(float) to fabs(float)
+//   1-NOV-1999: Laurent Duflot
+//     . correct bug in makeCluster: when the temporary jet was emptied the eta
+//       and phi were not set again. The main effect was a nearly zero 
+//       efficiency for jets at phi=pi (as seen by Volker Buescher)
+//   25-JAN-2000: Francois Touze
+//     . change in updateEtaPhiEt : the method E() which returns energy doesn't
+//       exist in MCparticle classe,... so use the 4-momentum components
+//     . declare const the EnergyClusterCollection of seeds in makeClusters
+//   01-FEB-2000: Laurent Duflot
+//     . add a missing break statement in the removal of shared items. Caused
+//       an infinite loop on some events.
+//     . correct typo in variable name. Change a variable name that was in 
+//       French.
+//     . leave some debug printout (commented)
+//   15-Sep-2009 Lars Sonnenschein
+//   extracted from D0 software framework and modified to remove subsequent dependencies
+//
+//
+// This file is distributed with FastJet under the terms of the GNU
+// General Public License (v2). Permission to do so has been granted
+// by Lars Sonnenschein and the D0 collaboration (see COPYING for
+// details)
+//
+// History of changes in FastJet compared to the original version of
+// ConeClusterAlgo.hpp
+//
+// 2011-12-13  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * added license information
+//
+// 2011-10-06  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * put the code in the fastjet::d0runi namespace
+//
+//////////////////////////////////////////////////////////////
+
+//#ifndef CONECLUSTERALGO_H
+//#define CONECLUSTERALGO_H
+
+#ifndef  D0RunIconeJets_CONECLUSTERALGO_H
+#define  D0RunIconeJets_CONECLUSTERALGO_H
+
+
+//#include "EnergyClusterReco.hpp"
+#include <vector>
+#include <list>
+#include <utility>
+//#include "kinem_util/AnglesUtil.hpp"
+
+#include <algorithm>
+#include <iostream>
+
+#include "inline_maths.h"
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace d0runi{
+
+using namespace std;
+
+//some utility functions
+inline float R2(float eta1, float phi1, float eta2, float phi2) {
+  return (eta1-eta2)*(eta1-eta2)+(phi1-phi2)*(phi1-phi2); }
+
+inline float R2_bis(float eta1, float phi1, float eta2, float phi2) {
+  //float dphi = kinem::delta_phi(phi1,phi2);
+  float dphi = inline_maths::delta_phi(phi1,phi2);
+  return (eta1-eta2)*(eta1-eta2)+dphi*dphi; }
+
+inline float DELTA_r(float eta1,float eta2,float phi1,float phi2) {
+  //float dphi = kinem::delta_phi(phi1,phi2);
+  float dphi = inline_maths::delta_phi(phi1,phi2);
+  return sqrt((eta1-eta2)*(eta1-eta2)+dphi*dphi);
+}
+
+inline float E2eta(float* p) { 
+   float small= 1.E-05;
+   float E[3];
+   if(p[3] < 0.0) {
+    E[0]= -p[0];
+    E[1]= -p[1];
+    E[2]= -p[2];
+   }
+   else {
+    E[0]= p[0];
+    E[1]= p[1];
+    E[2]= p[2];
+   }
+   float pperp= sqrt(E[0]*E[0]+E[1]*E[1])+small;
+   float ptotal= sqrt(E[0]*E[0]+E[1]*E[1]+E[2]*E[2])+small;
+   //float theta= atan2(pperp,E[2]);
+ 
+   float eta= 0.0;
+   if(E[2] > 0.0) eta= log((ptotal+E[2])/pperp);
+   else eta= log(pperp/(ptotal-E[2]));
+   return eta;
+}
+
+inline float E2phi(float* p) { 
+   float small= 1.E-05;
+   float E[3];
+   if(p[3] < 0.0) {
+    E[0]= -p[0];
+    E[1]= -p[1];
+    E[2]= -p[2];
+   }
+   else {
+    E[0]= p[0];
+    E[1]= p[1];
+    E[2]= p[2];
+   }
+   float phi= atan2(E[1],E[0]+small);
+   //if(phi < 0.0) phi+=kinem::TWOPI;
+   if (phi < 0.0) phi += inline_maths::TWOPI;
+   return phi;
+}
+
+//template < class CalItem,class CalItemAddress,class CalIClusterChunk >
+template < class CalItem >
+class ConeClusterAlgo {
+  //
+  // Purpose: make calorimeter clusters using a cone algorithm from 
+  // preclusters created previously by the class ConePreClusterAlgo.
+  // Items must have addresses and 4-momenta.
+  // The algorithm is implemented with a template function makeClusters.
+  //  
+  public :
+
+
+//default constructor
+ConeClusterAlgo() {} 
+
+//constructor for cone jet algorithm
+ConeClusterAlgo( float CONErad,float JETmne,float SPLifr):
+  _CONErad(fabs(CONErad)), 
+  _JETmne(JETmne), 
+  _SPLifr(SPLifr),
+  _TWOrad(0.),
+  _D0_Angle(false),
+  _Increase_Delta_R(true),
+  _Kill_Far_Clusters(true),
+  _Jet_Et_Min_On_Iter(true),
+  _Far_Ratio(0.5),
+  _Eitem_Negdrop(-1.0),
+  _Et_Min_Ratio(0.5),
+  _Thresh_Diff_Et(0.01)
+  {}
+
+//changing default thresholds & parameters
+// (declared by PARAMETER in RUNI code)
+ConeClusterAlgo( float CONErad,float JETmne,float SPLifr,float TWOrad, 
+                 float Tresh_Diff_Et,bool D0_Angle,bool Increase_Delta_R,
+                 bool Kill_Far_Clusters,bool Jet_Et_Min_On_Iter,
+                 float Far_Ratio,float Eitem_Negdrop,float Et_Min_Ratio ):
+  _CONErad(fabs(CONErad)), 
+  _JETmne(JETmne),
+  _SPLifr(SPLifr),
+  _TWOrad(TWOrad),
+  _D0_Angle(D0_Angle),
+  _Increase_Delta_R(Increase_Delta_R),
+  _Kill_Far_Clusters(Kill_Far_Clusters),
+  _Jet_Et_Min_On_Iter(Jet_Et_Min_On_Iter),
+  _Far_Ratio(Far_Ratio),
+  _Eitem_Negdrop(Eitem_Negdrop),
+  _Et_Min_Ratio(Et_Min_Ratio),
+  _Thresh_Diff_Et(Tresh_Diff_Et)
+  {}
+
+//destructor
+~ConeClusterAlgo() {}
+  
+//to make jet clusters using cone algorithm
+void makeClusters(//const EnergyClusterReco* r,
+		  std::list<CalItem> &jets,
+		  list<const CalItem*> &itemlist, float Zvertex 
+		  //, const EnergyClusterCollection<CalItemAddress> &preclu,
+		  //CalIClusterChunk* chunkptr
+		  //) const;
+		  );
+
+//print parameters of the algorithm
+void print(ostream &os)const;
+
+  //vector< TemporaryJet > TempColl;  
+
+
+  private :
+  
+  float _CONErad;
+  float _JETmne;
+  float _SPLifr;
+
+  float _TWOrad;
+  bool _D0_Angle;
+  bool _Increase_Delta_R;
+  bool _Kill_Far_Clusters;
+  bool _Jet_Et_Min_On_Iter;
+  float _Far_Ratio;
+  float _Eitem_Negdrop;
+  float _Et_Min_Ratio;
+  float _Thresh_Diff_Et;
+
+  class TemporaryJet {
+
+  public:
+
+
+
+    TemporaryJet() {}
+
+    TemporaryJet(float eta,float phi) { 
+      _Eta=eta; 
+      _Phi=phi;
+    }
+
+    ~TemporaryJet() {}
+
+    void addItem(const CalItem* tw) {
+      _LItems.push_back(tw);
+    }
+
+    void setEtaPhiEt(float eta,float phi,float pT) {
+      _Eta= eta;
+      _Phi= phi;
+      _Et = pT;
+    }
+
+    void erase() {
+      _LItems.erase(_LItems.begin(),_LItems.end());
+      _Eta= 0.0;
+      _Phi= 0.0;
+      _Et = 0.0;  
+    }
+
+    bool share_jets(TemporaryJet &NewJet,float SharedFr,float SPLifr) {
+      //
+      // combined
+      //
+      if(SharedFr >= SPLifr) {
+	typename list<const CalItem*>::iterator it;
+	typename list<const CalItem*>::iterator end_of_old=_LItems.end();
+	for(it=NewJet._LItems.begin(); it!=NewJet._LItems.end(); it++) {
+	  typename list<const CalItem*>::iterator 
+	    where = find(_LItems.begin(),end_of_old,*it);
+	  // if the item is not shared, add to this jet
+	  if(where == end_of_old) {
+            _LItems.push_back(*it);
+          }
+	}
+	NewJet.erase();
+	return false;
+      } else {
+	//
+	// split
+	//
+	typename list<const CalItem*>::iterator it;
+	for(it=NewJet._LItems.begin(); it!=NewJet._LItems.end(); ) {
+	  typename list<const CalItem*>::iterator 
+	    where = find(_LItems.begin(),_LItems.end(),*it);
+	  if(where != _LItems.end()) {
+	    //float EtaItem=(*it)->eta();
+	    //float PhiItem=(*it)->phi();
+	    // stay closer to the RUNI conventions for negative E cells
+	    float pz[4];
+	    (*it)->p4vec(pz);
+	    float EtaItem= E2eta(pz);
+	    float PhiItem= E2phi(pz);
+
+	    float RadOld=R2_bis(_Eta,_Phi,EtaItem,PhiItem);
+	    float RadNew=R2_bis(NewJet.Eta(),NewJet.Phi(),EtaItem,PhiItem);
+	    if (RadNew > RadOld) { 
+	      it = NewJet._LItems.erase(it);
+	    }
+	    else {
+	      _LItems.erase(where);
+	      ++it;
+	    }
+	  }
+	  else ++it;
+	}
+	return true;
+      }
+    }
+  
+
+    float dist_R2(TemporaryJet &jet) const {
+      float deta= _Eta-jet.Eta();
+      //float dphi= kinem::delta_phi(_Phi,jet.Phi());
+      float dphi= inline_maths::delta_phi(_Phi,jet.Phi());
+      return (deta*deta+dphi*dphi); 
+    }
+ 
+    bool ItemInJet(const CalItem* tw) const {
+      typename list<const CalItem*>::const_iterator
+	where= find(_LItems.begin(),_LItems.end(),tw);
+      if(where != _LItems.end()) return true;
+      else return false;
+    }
+  
+    bool updateEtaPhiEt() { 
+      float ETsum = 0.0;
+      float ETAsum= 0.0;
+      float PHIsum= 0.0;
+      float Esum= 0.0;
+      typename list<const CalItem*>::iterator it;
+      for(it=_LItems.begin(); it!=_LItems.end(); it++) {
+        float ETk = (*it)->pT();
+        // now done in CalCell/CalTower if((*it)->E() < 0.0) ETk= -ETk;
+
+        //float ETAk= (*it)->eta();
+        //float PHIk= (*it)->phi();
+        float pz[4];
+        (*it)->p4vec(pz);
+        float ETAk= E2eta(pz);
+	// take care of the phi=0=2pi problem 
+        float PHIk= E2phi(pz);
+	//if(fabs(PHIk-_Phi) > kinem::TWOPI-fabs(PHIk-_Phi))
+	if(fabs(PHIk-_Phi) > inline_maths::TWOPI-fabs(PHIk-_Phi))
+	  {
+	  if(_Phi < PHIk) 
+	    {
+	      //PHIk -= kinem::TWOPI;
+	      PHIk -= inline_maths::TWOPI;
+	    }
+	  else
+	    {
+	      //PHIk += kinem::TWOPI;
+	      PHIk += inline_maths::TWOPI;
+	    }
+	  }
+	ETAsum+= ETAk*ETk;
+	PHIsum+= PHIk*ETk;
+	ETsum += ETk;
+        // Esum+=(*it)->E(); use 4-momentum components 
+	Esum+= pz[3];
+      }
+      if(ETsum <= 0.0) {
+	_Eta= 0.0;
+	_Phi= 0.0;
+	_Et = 0.0;
+        _E=0.;
+	return false;
+      }
+      else {
+         _Eta= ETAsum/ETsum;
+         _Phi= PHIsum/ETsum; 
+	 //if ( _Phi<0 ) _Phi+=kinem::TWOPI;
+	 if ( _Phi<0 ) _Phi+=inline_maths::TWOPI;
+         _Et = ETsum;
+         _E  = Esum;
+         return true;  
+      }
+    }
+
+    void D0_Angle_updateEtaPhi() {
+      float EXsum = 0.0;
+      float EYsum = 0.0;
+      float EZsum = 0.0;
+      typename list<const CalItem*>::iterator it;
+      for(it=_LItems.begin(); it!=_LItems.end(); it++) {
+	float p[4];
+	(*it)->p4vec(p);
+	EXsum += p[0];
+	EYsum += p[1];
+	EZsum += p[2];
+      }
+      //_Phi=kinem::phi(EYsum,EXsum);
+      _Phi=inline_maths::phi(EYsum,EXsum);
+      //_Eta=kinem::eta(EXsum,EYsum,EZsum);
+      _Eta=inline_maths::eta(EXsum,EYsum,EZsum);
+    } 
+
+    void getItems(list<const CalItem*> &ecv) const {
+      ecv.clear(); //ls 27/Feb/2010
+      typename list<const CalItem*>::const_iterator it;
+      for(it=_LItems.begin(); it!=_LItems.end(); it++) {
+	ecv.push_back(*it);
+      }
+    }
+
+    float Eta() {return _Eta;}
+    float Phi() {return _Phi;}
+    float Et()  {return _Et;}
+    float E()  {return _E;}
+    list<const CalItem*> &LItems() {return _LItems;}
+    
+  private:
+    list<const CalItem*> _LItems;
+    float _Eta;
+    float _Phi;
+    float _Et;
+    float _E;
+  }; //class TemporaryJet
+
+  void getItemsInCone(list<const CalItem*> &tlist, float etaJet, float phiJet,
+  		      float cone_radius, float zvertex_in) const; 
+  void getItemsInCone_bis(list<const CalItem*> &tlist, float etaJet, 
+               float phiJet,float cone_radius, float zvertex_in) const; 
+  
+public:
+  
+  vector< TemporaryJet > TempColl;  
+
+};
+  /////////////////////////////////////////////////////////
+
+//template < class CalItem,class CalItemAddress,class CalIClusterChunk >
+template < class CalItem >
+//void ConeClusterAlgo <CalItem,CalItemAddress,CalIClusterChunk >:: 
+void ConeClusterAlgo <CalItem >:: 
+getItemsInCone(list<const CalItem*> &tlist, float etaJet, float phiJet, 
+	       float cone_radius, float zvertex_in) const {
+//
+// provide the list of Items (towers, Cells...) containing the energy from a 
+// jet of a given cone size
+//
+  float ZVERTEX_MAX=200.;
+  float DMIN=80.;
+  float DMAX=360.;
+  float THETA_margin=0.022;
+   
+  float zvertex=zvertex_in;
+  float d1,d2;
+  float phi_d1, phi_d2;
+  float theta_E1, r1, r2, z1, z2;
+  float theta_d1, theta_d2, eta_d1, eta_d2;
+
+  // Ignore very large vertex positions
+  if (fabs(zvertex) > ZVERTEX_MAX ) zvertex=0.0;
+ 
+  if (zvertex >=0. ) {
+    d1=fabs(DMIN-zvertex);
+    d2=fabs(DMAX+zvertex);
+  } else {
+    d1=fabs(DMAX-zvertex);
+    d2=fabs(DMIN+zvertex);
+  }
+  
+  // calculate theta of physics cone and find which eta's this intercepts
+  // a the maximum points
+  phi_d1 = phiJet+cone_radius;
+  //theta_E1 = kinem::theta(etaJet+cone_radius);
+  theta_E1 = inline_maths::theta(etaJet+cone_radius);
+  z1 = zvertex+d1*cos(theta_E1);
+  r1 = d1*sin(theta_E1);
+
+  phi_d2 = phiJet-cone_radius;
+  //theta_E1 = kinem::theta(etaJet-cone_radius);
+  theta_E1 = inline_maths::theta(etaJet-cone_radius);
+  z2 = zvertex+d2*cos(theta_E1);
+  r2 = d2*sin(theta_E1);
+
+  // maximum spread in detector theta
+  theta_d1 = atan2(r1, z1);
+  theta_d2 = atan2(r2, z2);
+
+  // make sure they stay in the calorimeter 
+  theta_d1=max(theta_d1, THETA_margin);
+  theta_d2=max(theta_d2, THETA_margin);
+  //theta_d1=min(kinem::PI-(double)THETA_margin, (double)theta_d1);
+  theta_d1=min(inline_maths::PI-(double)THETA_margin, (double)theta_d1);
+  //theta_d2=min(kinem::PI-(double)THETA_margin, (double)theta_d2);
+  theta_d2=min(inline_maths::PI-(double)THETA_margin, (double)theta_d2);
+
+  //eta_d1 = kinem::eta(theta_d1);
+  eta_d1 = inline_maths::eta(theta_d1);
+  //eta_d2 = kinem::eta(theta_d2);
+  eta_d2 = inline_maths::eta(theta_d2);
+
+
+  typename list<const CalItem*>::iterator it;
+  for (it=tlist.begin() ; it != tlist.end() ; ) {
+    //float eta_cur= (*it)->eta();
+    //float phi_cur= (*it)->phi();
+    float pz[4];
+    (*it)->p4vec(pz);
+    float eta_cur= E2eta(pz);
+    float phi_cur= E2phi(pz);
+
+    bool accepted = eta_cur < eta_d1 && eta_cur > eta_d2;
+    //if ( phi_d2>0 && phi_d1<kinem::TWOPI ) {
+    if ( phi_d2>0 && phi_d1<inline_maths::TWOPI ) {
+      accepted = accepted && phi_cur<phi_d1 && phi_cur>phi_d2;
+    }
+    else{ // case the cone overlap the phi=0=2pi line
+      if ( phi_d2>0 ){
+	accepted = accepted && 
+	  //((phi_cur>phi_d2 && phi_cur<kinem::TWOPI) || phi_cur<phi_d1-kinem::TWOPI);
+	  ((phi_cur>phi_d2 && phi_cur<inline_maths::TWOPI) || phi_cur<phi_d1-inline_maths::TWOPI);
+      }
+      else{
+	accepted = accepted && 
+	  //((phi_cur<phi_d1 && phi_cur>0) || phi_cur>phi_d2+kinem::TWOPI);
+	  ((phi_cur<phi_d1 && phi_cur>0) || phi_cur>phi_d2+inline_maths::TWOPI);
+      }
+    }
+    if ( ! accepted ) it = tlist.erase(it);
+    else ++it;
+
+  }
+}
+  /////////////////////////////////////////////////////////
+//template < class CalItem,class CalItemAddress,class CalIClusterChunk >
+template < class CalItem >
+//void ConeClusterAlgo <CalItem,CalItemAddress,CalIClusterChunk >:: 
+void ConeClusterAlgo <CalItem>:: 
+getItemsInCone_bis(list<const CalItem*> &tlist, float etaJet, float phiJet, 
+	       float cone_radius, float zvertex_in) const {
+//
+// provide the list of Items (towers, Cells...) containing the energy from a 
+// jet of a given cone size
+//
+// WARNING: this is only to be used to compare to RUN I cone jets
+// 
+  float ZVERTEX_MAX=200.;
+  float DMIN=80.;
+  float DMAX=360.;
+  float THETA_margin=0.022;
+   
+  float zvertex=zvertex_in;
+  float d1,d2;
+  float phi_d1, phi_d2;
+  float theta_E1, r1, r2, z1, z2;
+  float theta_d1, theta_d2, eta_d1, eta_d2;
+
+  // Ignore very large vertex positions
+  if (fabs(zvertex) > ZVERTEX_MAX ) zvertex=0.0;
+ 
+  if (zvertex >=0. ) {
+    d1=fabs(DMIN-zvertex);
+    d2=fabs(DMAX+zvertex);
+  } else {
+    d1=fabs(DMAX-zvertex);
+    d2=fabs(DMIN+zvertex);
+  }
+  
+  // calculate theta of physics cone and find which eta's this intercepts
+  // a the maximum points
+  
+  phi_d1 = phiJet+cone_radius;
+  //theta_E1 = kinem::theta(etaJet+cone_radius);
+  theta_E1 = inline_maths::theta(etaJet+cone_radius);
+  z1 = zvertex+d1*cos(theta_E1);
+  r1 = d1*sin(theta_E1);
+
+  phi_d2 = phiJet-cone_radius;
+  //theta_E1 = kinem::theta(etaJet-cone_radius);
+  theta_E1 = inline_maths::theta(etaJet-cone_radius);
+  z2 = zvertex+d2*cos(theta_E1);
+  r2 = d2*sin(theta_E1);
+
+  // maximum spread in detector theta
+
+  theta_d1 = atan2(r1, z1);
+  theta_d2 = atan2(r2, z2);
+
+  // make sure they stay in the calorimeter 
+
+  theta_d1=max(theta_d1, THETA_margin);
+  theta_d2=max(theta_d2, THETA_margin);
+  //theta_d1=min(kinem::PI-(double)THETA_margin, (double)theta_d1);
+  theta_d1=min(inline_maths::PI-(double)THETA_margin, (double)theta_d1);
+  //theta_d2=min(kinem::PI-(double)THETA_margin, (double)theta_d2);
+  theta_d2=min(inline_maths::PI-(double)THETA_margin, (double)theta_d2);
+
+
+  //eta_d1 = kinem::eta(theta_d1);
+  eta_d1 = inline_maths::eta(theta_d1);
+  //eta_d2 = kinem::eta(theta_d2);
+  eta_d2 = inline_maths::eta(theta_d2);
+
+  float signe;
+ 
+  if( eta_d1>=0.0 ) signe= 1.0;
+  else signe= -1.0;
+  int ietaMAX= eta_d1/0.1+signe;
+  if(fabs(eta_d1)>=4.45) ietaMAX= 37*signe; 
+  else if(fabs(eta_d1)>=4.1) ietaMAX= 36*signe; 
+  else if(fabs(eta_d1)>=3.7) ietaMAX= 35*signe; 
+  else if(fabs(eta_d1)>=3.42) ietaMAX= 34*signe; 
+  else if(fabs(eta_d1)>=3.2) ietaMAX= 33*signe; 
+  
+  if( eta_d2>=0.0 ) signe= 1.0;
+  else signe= -1.0;
+  int ietaMIN= eta_d2/0.1+signe;
+  if(fabs(eta_d2)>=4.45) ietaMIN= 37*signe; 
+  else if(fabs(eta_d2)>=4.1) ietaMIN= 36*signe; 
+  else if(fabs(eta_d2)>=3.7) ietaMIN= 35*signe; 
+  else if(fabs(eta_d2)>=3.42) ietaMIN= 34*signe; 
+  else if(fabs(eta_d2)>=3.2) ietaMIN= 33*signe; 
+
+  //int iphiMAX= 64*phi_d1/(2.*kinem::PI)+1;
+  int iphiMAX= 64*phi_d1/(2.*inline_maths::PI)+1;
+  //int iphiMIN= 64*phi_d2/(2.*kinem::PI)+1;
+  int iphiMIN= 64*phi_d2/(2.*inline_maths::PI)+1;
+ 
+  typename list<const CalItem*>::iterator it;
+  for (it=tlist.begin() ; it != tlist.end() ; ) {
+    //float eta_cur= (*it)->eta();
+    //float phi_cur= (*it)->phi();
+    int ieta= (*it)->address().ieta();
+    int iphi= (*it)->address().iphi();
+    
+    bool accepted = ieta<ietaMAX && ieta>ietaMIN;
+    if ( iphiMIN>0 && iphiMAX<=64 ) {
+      accepted = accepted && iphi<iphiMAX && iphi>iphiMIN;
+    }
+    else{ // case the cone overlap the phi=0=2pi line
+      if ( iphiMIN>0 ){
+	accepted = accepted && 
+	  ((iphi>iphiMIN && iphi<=64) || iphi<iphiMAX-64);
+      }
+      else{
+	accepted = accepted && 
+	  ((iphi<iphiMAX && iphi>0) || iphi>iphiMIN+64);
+      }
+    }
+    if ( ! accepted ) it = tlist.erase(it);
+    else ++it;
+    
+  }
+}
+  /////////////////////////////////////////////////////////
+//template < class CalItem,class CalItemAddress,class CalIClusterChunk >
+template < class CalItem >
+//inline void ConeClusterAlgo <CalItem,CalItemAddress,CalIClusterChunk >:: 
+inline void ConeClusterAlgo <CalItem >:: 
+print(ostream &os) const {
+    os<<endl<<" CONE ALGORITHM, cone radius= "<<_CONErad<<endl<<
+    " min E_T fraction= "<<_JETmne<<endl<<
+    " minimum Delta_R separation between cones= "<<_TWOrad<<endl<<
+    " shared E_T fraction threshold for combining jets= "<<_SPLifr<<endl;
+}
+  /////////////////////////////////////////////////////////
+
+//template < class CalItem,class CalItemAddress,class CalIClusterChunk >
+template < class CalItem >
+//void ConeClusterAlgo <CalItem,CalItemAddress,CalIClusterChunk >:: 
+void ConeClusterAlgo <CalItem >:: 
+makeClusters(//const EnergyClusterReco* r,
+	     std::list<CalItem> &jets,
+	     list<const CalItem*> &itemlist, float Zvertex 
+	     //, const EnergyClusterCollection<CalItemAddress> &preclu,
+	     //CalIClusterChunk* chunkptr
+	     //) const {
+	     ) {
+
+  // create an energy cluster collection for jets 
+  //EnergyClusterCollection<CalItemAddress>* ptrcol;
+  //r->createClusterCollection(chunkptr, ptrcol);
+  std::vector<const CalItem*> ecv;
+  for ( typename std::list<const CalItem*>::iterator it = itemlist.begin(); 
+        it != itemlist.end(); it++) {
+    ecv.push_back(*it);
+  }
+
+
+  // Initialize
+  float Rcut= 1.E-06;
+  if(_Increase_Delta_R) Rcut= 1.E-04;
+  bool nojets;
+
+  //vector< TemporaryJet > TempColl;  
+  list< pair<float,float> > LTrack;
+
+  // get a vector with pointers to EnergyCluster in the collection
+  //vector<const EnergyCluster<CalItemAddress>*> ecv;
+  //preclu.getClusters(ecv);
+
+  // loop over all preclusters
+  //typename vector<const EnergyCluster<CalItemAddress>*>::iterator jclu;
+  typename std::vector<const CalItem*>::iterator jclu;
+  for( jclu=ecv.begin(); jclu!=ecv.end(); jclu++ ) {
+    ////const EnergyCluster<CalItemAddress>* ptr= *jclu;
+    const CalItem* ptr= *jclu;
+    //float PHIst= ptr->phi();
+    //float ETAst= ptr->eta();
+    float pz[4];
+    ptr->p4vec(pz);
+    float ETAst= E2eta(pz);
+    float PHIst= E2phi(pz);
+
+    //cout << "seed 4-vec ";
+    //for ( int i = 0; i < 4; i++) cout << pz[i] << " ";
+    //cout << endl;
+
+    nojets= false;
+    // check to see if precluster is too close to a found jet
+    if(_Kill_Far_Clusters) {
+      list< pair<float,float> >::iterator kj;
+      for(kj=LTrack.begin(); kj!=LTrack.end(); kj++) {
+	if(DELTA_r((*kj).first,ETAst,(*kj).second,PHIst)<_Far_Ratio*_CONErad) {
+	  nojets= true;
+	  //cout << "seed too close ! skip " << endl;
+	  break;
+	}
+      }
+    }
+    if( nojets==false ) {
+      TemporaryJet TJet(ETAst,PHIst);
+      list< pair<int,float> > JETshare;
+
+      // start of cone building loop
+      int trial= 0;
+      do{  
+        trial++;
+	//cout << " trial " << trial << endl;
+
+	ETAst= TJet.Eta();
+        PHIst= TJet.Phi();
+        TJet.erase();
+
+	//if(PHIst > kinem::TWOPI) PHIst= PHIst-kinem::TWOPI;
+	if(PHIst > inline_maths::TWOPI) PHIst= PHIst-inline_maths::TWOPI;
+	//if(PHIst < 0.0  ) PHIst= PHIst+kinem::TWOPI;
+	if(PHIst < 0.0  ) PHIst= PHIst+inline_maths::TWOPI;
+	//if( PHIst>kinem::TWOPI || PHIst<0.0 ) {
+	if( PHIst>inline_maths::TWOPI || PHIst<0.0 ) {
+          TJet.setEtaPhiEt(0.0,0.0,0.0);
+	  break; // end loop do (illegal jet PHI) 
+        }
+	TJet.setEtaPhiEt(ETAst,PHIst,0.0);
+
+	// calculate eta & phi limits for cone
+        list<const CalItem*> Twlist(itemlist);
+
+	getItemsInCone(Twlist,ETAst,PHIst,_CONErad,Zvertex); 
+	//  only to compare with RUN I cone jets !   getItemsInCone_bis(Twlist,ETAst,PHIst,_CONErad,Zvertex); 
+
+	// loop over the possible items for this cone
+        typename list<const CalItem*>::iterator tk;
+        for( tk= Twlist.begin(); tk!=Twlist.end(); tk++ ) {
+	  float ETk =(*tk)->pT();
+          // now done in CalCell/CalTower if((*tk)->E() < 0.0) ETk= -ETk;
+
+          if( ETk > _Eitem_Negdrop ) { 
+	    //float ETAk=(*tk)->eta();
+	    //float PHIk=(*tk)->phi();
+            float pz[4];
+            (*tk)->p4vec(pz);
+            float ETAk= E2eta(pz);
+            float PHIk= E2phi(pz);
+
+	    float dphi= fabs(PHIk-PHIst);
+	    //if(dphi > kinem::TWOPI-dphi) {
+	    if(dphi > inline_maths::TWOPI-dphi) {
+              //if(PHIst < PHIk) PHIk= PHIk-kinem::TWOPI;
+              if(PHIst < PHIk) PHIk= PHIk-inline_maths::TWOPI;
+              //else PHIk= PHIk+kinem::TWOPI; 
+              else PHIk= PHIk+inline_maths::TWOPI; 
+            }
+
+	    if( R2_bis(ETAk,PHIk,ETAst,PHIst) <= _CONErad*_CONErad ) { 
+	      TJet.addItem(*tk);
+	    }
+	  }
+	}// end loop tk
+ 
+	if(TJet.updateEtaPhiEt()==false) {
+	  //cout << " negative E jet ! drop " << endl;
+	  break;
+	}
+
+	// require some minimum ET on every iteration
+	if(_Jet_Et_Min_On_Iter) {
+	  if( TJet.Et() < _JETmne*_Et_Min_Ratio ) {
+	    //cout << " too low ET jet ! drop " << endl;
+	    break; // end loop trial
+          }
+        }
+  
+	//cout << " R2 = " << R2_bis(TJet.Eta(),TJet.Phi(),ETAst,PHIst) << 
+	//  " Rcut = " << Rcut << endl;
+      }while(R2_bis(TJet.Eta(),TJet.Phi(),ETAst,PHIst)>=Rcut && trial<=50);
+ 
+      if( TJet.Et() >= _JETmne ) {
+	//cout << " jet accepted will check for overlaps " << endl; 
+	if(_D0_Angle) TJet.D0_Angle_updateEtaPhi();
+	//cout << "  after TJet.D0_Angle_updateEtaPhi() " << endl;
+	
+        // item also in another jet
+        list<const CalItem*> Lst;
+        TJet.getItems(Lst);
+        typename list<const CalItem*>::iterator tk;
+        for(tk=Lst.begin(); tk!=Lst.end(); tk++) {
+	  float ETk=(*tk)->pT();
+          // now done in CalCell/CalTower if((*tk)->E() < 0.0) ETk= -ETk;
+          for(unsigned int kj=0; kj<TempColl.size(); kj++) {
+	    if(TempColl[kj].ItemInJet(*tk)==true) {
+	      list< pair<int,float> >::iterator pit;
+              bool jetok= false;
+              for(pit=JETshare.begin(); pit!=JETshare.end();pit++) {
+                if((*pit).first == (int) kj) {
+                  jetok= true;
+                  (*pit).second+= ETk;
+                  break;
+                }
+              }
+              if(jetok==false) JETshare.push_back(make_pair(kj,ETk));
+            }
+          }
+        }
+	
+	if(JETshare.size() >0) {
+	  list< pair<int,float> >::iterator pit;
+	  float Ssum= 0.0;
+	  list< pair<int,float> >::iterator pitMAX=JETshare.begin();
+	  for(pit=JETshare.begin(); pit!=JETshare.end(); pit++) {
+	    Ssum+= (*pit).second;
+	    if((*pit).second > (*pitMAX).second) pitMAX= pit;
+	  }
+
+          //int IJET= (*pitMAX).first;
+	  bool splshr;
+	  float Eleft= fabs(TJet.Et()-Ssum);
+	  float Djets= TempColl[(*pitMAX).first].dist_R2(TJet);
+	  if(Djets <= _TWOrad || Eleft <= _Thresh_Diff_Et) { 
+	    TJet.erase();
+	    splshr= false;
+	  }
+	  else {
+	    float SharedFr=Ssum/min(TempColl[(*pitMAX).first].Et(),TJet.Et());
+	    if(JETshare.size() >1) {
+	      typename list<const CalItem*>::iterator tk;
+	      for(tk=TJet.LItems().begin(); tk!=TJet.LItems().end(); ) {
+                bool found = false;
+		list< pair<int,float> >::iterator pit;
+		for(pit=JETshare.begin(); pit!=JETshare.end();pit++) {
+		  if((*pit).first!=(*pitMAX).first) { 
+		    if(TempColl[(*pit).first].ItemInJet(*tk)==true) {
+		      tk = TJet.LItems().erase(tk);
+		      found = true;
+		      break;
+		    }
+		  }
+		}
+		if ( !found ) ++tk;
+	      }
+	    }
+
+	    splshr= TempColl[(*pitMAX).first].share_jets(TJet,SharedFr,_SPLifr);
+
+	    if( splshr==true ) {
+	      //cout << " jet splitted due to overlaps " << endl;
+	      TempColl[(*pitMAX).first].updateEtaPhiEt();
+	      TJet.updateEtaPhiEt();
+	      if(_D0_Angle) TJet.D0_Angle_updateEtaPhi();
+	      if(_D0_Angle) TempColl[(*pitMAX).first].D0_Angle_updateEtaPhi();
+	      TempColl.push_back(TJet);  
+	      LTrack.push_back(make_pair(TJet.Eta(),TJet.Phi()));
+	    }
+	    else {
+	      //cout << " jet merged due to overlaps " << endl;
+	      TempColl[(*pitMAX).first].updateEtaPhiEt();
+	      if(_D0_Angle) TempColl[(*pitMAX).first].D0_Angle_updateEtaPhi();
+	    }  
+	  }
+	}
+	else {
+	  TJet.updateEtaPhiEt();
+	  if(_D0_Angle) TJet.D0_Angle_updateEtaPhi();
+          TempColl.push_back(TJet);  
+          LTrack.push_back(make_pair(TJet.Eta(),TJet.Phi()));
+	}
+      } //JETmne
+    } //nojets
+  }// end loop jclu 
+
+  for(unsigned int i=0; i<TempColl.size(); i++) {
+    //EnergyCluster<CalItemAddress>* ptrclu;
+    CalItem ptrclu;
+    //r->createCluster(ptrcol,ptrclu);
+    list<const CalItem*> Vi;
+    TempColl[i].getItems(Vi);
+    typename list<const CalItem*>::iterator it;
+    for(it=Vi.begin(); it!=Vi.end(); it++) {
+      const CalItem* ptr= *it;
+      //CalItemAddress addr= ptr->address();
+      float p[4];
+      ptr->p4vec(p);
+      //float emE= ptr->emE();
+      //r->addClusterItem(ptrclu,addr,p,emE);
+      ptrclu.Add(*ptr);
+    }
+    jets.push_back(ptrclu);
+  }
+
+}// end 
+
+} //namespace d0runi
+
+FASTJET_END_NAMESPACE
+
+#endif  //  CONECLUSTERALGO_H
+
+
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/D0RunIBaseConePlugin.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/D0RunIBaseConePlugin.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/D0RunIBaseConePlugin.cc	(revision 5)
@@ -0,0 +1,242 @@
+//STARTHEADER
+// $Id: D0RunIBaseConePlugin.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2009-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+// D0 stuff
+// apparently this has to go first to avoid a problem with gcc-4.0.1 builds on Macs
+#include <list>
+#include "ConeClusterAlgo.hpp"
+#include "HepEntityIpre96.h"
+#include "HepEntityI.h"
+
+#include "fastjet/D0RunIBaseConePlugin.hh"
+#include "fastjet/D0RunIpre96ConePlugin.hh"
+#include "fastjet/D0RunIConePlugin.hh"
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/Error.hh"
+#include <sstream>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std; 
+using namespace d0runi;
+
+/////////////////////////////////////////////
+//                                         //
+// D0RunIBaseConePlugin implementation     //
+//                                         //
+/////////////////////////////////////////////
+
+const double D0RunIBaseConePlugin::_DEFAULT_SPLifr             = 0.5; //shared Et fraction threshold
+const double D0RunIBaseConePlugin::_DEFAULT_TWOrad             = 0.; 
+const bool   D0RunIBaseConePlugin::_DEFAULT_D0_Angle           = false;
+const bool   D0RunIBaseConePlugin::_DEFAULT_Increase_Delta_R   = true;
+const bool   D0RunIBaseConePlugin::_DEFAULT_Kill_Far_Clusters  = true;
+const bool   D0RunIBaseConePlugin::_DEFAULT_Jet_Et_Min_On_Iter = true;
+const double D0RunIBaseConePlugin::_DEFAULT_Far_Ratio          = 0.5;
+const double D0RunIBaseConePlugin::_DEFAULT_Eitem_Negdrop      = -1.0;
+const double D0RunIBaseConePlugin::_DEFAULT_Et_Min_Ratio       = 0.5;
+const double D0RunIBaseConePlugin::_DEFAULT_Thresh_Diff_Et     = 0.01;
+
+
+// for the real work, we write a template class that decides which
+// HepEntity type to use
+template<typename HepEntityType>
+void D0RunIBaseConePlugin::run_clustering_worker(ClusterSequence & clust_seq) const{
+  // create the entities needed by the D0 code
+  vector<HepEntityType> entities(clust_seq.jets().size());
+  list<const HepEntityType * > ensemble;
+  for (unsigned i = 0; i < clust_seq.jets().size(); i++) {
+    entities[i].Fill(clust_seq.jets()[i].E(),
+		     clust_seq.jets()[i].px(),
+		     clust_seq.jets()[i].py(),
+		     clust_seq.jets()[i].pz(),
+		     i);
+    // use only the particles that do not have infinite rapidity
+    if (abs(entities[i].pz() ) < entities[i].E() ) {
+      ensemble.push_back(& (entities[i]));
+    }
+  }
+
+  // prepare the D0 algorithm
+  ConeClusterAlgo<HepEntityType> 
+    RunIconeAlgo(CONErad(), 
+		 JETmne(),
+		 TWOrad(),
+		 SPLifr(),
+		 D0_Angle(),
+		 Increase_Delta_R(),
+		 Kill_Far_Clusters(),
+		 Jet_Et_Min_On_Iter(),
+		 Far_Ratio(),
+		 Eitem_Negdrop(),
+		 Et_Min_Ratio(),
+		 Thresh_Diff_Et());
+
+
+  // run the algorithm
+  float Zvertex = 0.;
+  list<HepEntityType> jets;
+  RunIconeAlgo.makeClusters(jets, ensemble, Zvertex);
+
+  // now transfer the information about the jets into the
+  // FastJet structure
+  for(int i = RunIconeAlgo.TempColl.size()-1; i >= 0; i--) {
+    
+    std::list<const HepEntityType*> tlist = RunIconeAlgo.TempColl[i].LItems();
+    typename std::list<const HepEntityType*>::iterator tk;
+        
+    // get first particle in list
+    tk = tlist.begin();
+    int jet_k = (*tk)->index;
+
+    // GS addition: in order to use the proper recombination scheme
+    // used by D0 we need to keep track of the sum as a
+    // "HepEntityType"
+    HepEntityType jet_current_momentum = *(*tk);
+
+    // now merge with remaining particles in list
+    tk++;
+    for (; tk != tlist.end(); tk++) {
+      int jet_i = jet_k;
+      int jet_j = (*tk)->index;
+      // do a fake recombination step with dij=0
+      double dij = 0.0;
+
+      // GS addition: find the new momentum and convert that into a
+      // pseudo-jet
+      jet_current_momentum.Add(**tk);
+      PseudoJet new_mom(jet_current_momentum.px(), jet_current_momentum.py(), 
+			jet_current_momentum.pz(), jet_current_momentum.E());
+
+      clust_seq.plugin_record_ij_recombination(jet_i, jet_j, dij, new_mom, jet_k);
+    }
+    
+    // NB: put a sensible looking d_iB just to be nice...
+    double d_iB = clust_seq.jets()[jet_k].perp2();
+    clust_seq.plugin_record_iB_recombination(jet_k, d_iB);    
+  }
+}
+
+
+/////////////////////////////////////////////
+//                                         //
+// D0RunIpre96ConePlugin implementation    //
+//                                         //
+/////////////////////////////////////////////
+
+bool D0RunIpre96ConePlugin::_first_time=true;
+
+string D0RunIpre96ConePlugin::description () const {
+  ostringstream desc;
+  
+  desc << "D0 Run I (pre 96) cone jet algorithm, with ";
+  desc << "cone_radius = "        << CONErad        () << ", "
+       << "min_jet_Et = "         << JETmne         () << ", " 
+       << "split_fraction = "     << SPLifr         ();
+
+  return desc.str();
+}
+
+void D0RunIpre96ConePlugin::run_clustering(ClusterSequence & clust_seq) const {
+  // print a banner if we run this for the first time
+  _print_banner(clust_seq.fastjet_banner_stream());
+
+  run_clustering_worker<HepEntityIpre96>(clust_seq);
+}
+
+// print a banner for reference to the 3rd-party code
+void D0RunIpre96ConePlugin::_print_banner(ostream *ostr) const{
+  if (! _first_time) return;
+  _first_time=false;
+
+  // make sure the user has not set the banner stream to NULL
+  if (!ostr) return;  
+
+  (*ostr) << "#--------------------------------------------------------------------------" << endl;
+  (*ostr) << "# You are running the D0 Run I (pre96) Cone plugin for FastJet             " << endl;
+  (*ostr) << "# Original code by the D0 collaboration, provided by Lars Sonnenschein;    " << endl;
+  (*ostr) << "# interface by FastJet authors                                             " << endl;
+  (*ostr) << "# If you use this plugin, please cite                                      " << endl;
+  (*ostr) << "#   B. Abbott et al. [D0 Collaboration], FERMILAB-PUB-97-242-E.            " << endl;
+  (*ostr) << "# in addition to the usual FastJet reference.                              " << endl;
+  (*ostr) << "#--------------------------------------------------------------------------" << endl;
+
+  // make sure we really have the output done.
+  ostr->flush();
+}
+
+
+/////////////////////////////////////////////
+//                                         //
+// D0RunIConePlugin implementation         //
+//                                         //
+/////////////////////////////////////////////
+
+bool D0RunIConePlugin::_first_time=true;
+
+string D0RunIConePlugin::description () const {
+  ostringstream desc;
+  
+  desc << "D0 Run I cone jet algorithm, with ";
+  desc << "cone_radius = "        << CONErad        () << ", "
+       << "min_jet_Et = "         << JETmne         () << ", " 
+       << "split_fraction = "     << SPLifr         ();
+
+  return desc.str();
+}
+
+void D0RunIConePlugin::run_clustering(ClusterSequence & clust_seq) const {
+  // print a banner if we run this for the first time
+  _print_banner(clust_seq.fastjet_banner_stream());
+
+  run_clustering_worker<HepEntityI>(clust_seq);
+}
+
+// print a banner for reference to the 3rd-party code
+void D0RunIConePlugin::_print_banner(ostream *ostr) const{
+  if (! _first_time) return;
+  _first_time=false;
+
+  // make sure the user has not set the banner stream to NULL
+  if (!ostr) return;  
+
+  (*ostr) << "#--------------------------------------------------------------------------" << endl;
+  (*ostr) << "# You are running the D0 Run I Cone plugin for FastJet                     " << endl;
+  (*ostr) << "# Original code provided by Lars Sonnenschein; interface by FastJet authors" << endl;
+  (*ostr) << "# If you use this plugin, please cite                                      " << endl;
+  (*ostr) << "#   B. Abbott et al. [D0 Collaboration], FERMILAB-PUB-97-242-E.            " << endl;
+  (*ostr) << "# in addition to the usual FastJet reference.                              " << endl;
+  (*ostr) << "#--------------------------------------------------------------------------" << endl;
+
+  // make sure we really have the output done.
+  ostr->flush();
+}
+
+
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/HepEntityI.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/HepEntityI.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/HepEntityI.h	(revision 5)
@@ -0,0 +1,145 @@
+#ifndef  D0RunIconeJets_HepEntity_class
+#define  D0RunIconeJets_HepEntity_class
+
+#include "inline_maths.h"
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace d0runi{
+
+//Author: Lars Sonnenschein 15/Sep/2009
+//This is an example class fulfilling the minimal requirements needed by the
+//D0 RunI cone jet algorithm implementation, which is an inlined template class
+
+// This file is distributed with FastJet under the terms of the GNU
+// General Public License (v2). Permission to do so has been granted
+// by Lars Sonnenschein and the D0 collaboration (see COPYING for
+// details)
+//
+// History of changes in FastJet compared tothe original version of
+// HepEntity.h
+//
+// 2011-12-13  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * added license information
+//
+// 2011-11-14  Gregory Soyez  <soyez@fastjet.fr>
+//
+//         * removed some harmless warnings coming with the -Wshadow gcc option
+// 
+// 2011-10-06  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * put the code in the fastjet::d0runi namespace
+
+class HepEntityI {
+
+ public:
+
+  HepEntityI() {
+    Et=0.;
+    eta=0.;
+    phi=0.;
+    index = -1;
+    return;
+  }
+
+
+  HepEntityI(double E_in, double px_in, double py_in, double pz_in,
+	     int index_in = -1) : index(index_in) {
+    //Snowmass Et scheme    
+    double pt = sqrt(px_in*px_in+py_in*py_in);
+    double p = sqrt(pt*pt+pz_in*pz_in);
+    phi = inline_maths::phi(px_in,py_in);
+    double theta = asin(pt/p);
+    eta = inline_maths::eta(theta);
+
+    Et = E_in*sin(theta);
+    
+    return;
+  }
+
+
+
+   HepEntityI(const HepEntityI& in) : Et(in.Et), eta(in.eta), phi(in.phi), index(in.index) {
+    return;
+  }
+
+
+
+  
+  inline double pT() const {
+    return Et;
+  }
+
+  inline double px() const {
+    return Et*cos(phi);
+  }
+
+  inline double py() const {
+    return Et*sin(phi);
+  }
+
+  inline double pz() const {
+    return Et*sinh(eta);
+  }
+  
+  inline double E() const {
+    return Et*cosh(eta);
+  }
+
+  
+  inline void p4vec(float* p) const {
+    p[0] = Et*cos(phi);
+    p[1] = Et*sin(phi);
+    p[2] = Et*sinh(eta);
+    p[3] = Et*cosh(eta); //E
+    return;
+  }
+  
+
+  inline void Add(const HepEntityI el) {
+    //assumes Et, eta and phi stored accurately
+    double w2 = el.Et;
+    Et += el.Et;
+    w2 /= Et;
+    
+    eta += w2*(el.eta - eta);
+    phi += w2*inline_maths::delta_phi(el.phi, phi); 
+
+    return; 
+  }
+
+
+  inline void Fill(double E_in, double px_in, double py_in, double pz_in, int index_in) {
+    double pt = sqrt(px_in*px_in+py_in*py_in);
+    double p = sqrt(pt*pt+pz_in*pz_in);
+    phi = inline_maths::phi(px_in,py_in);
+    double theta = asin(pt/p);
+    eta = inline_maths::eta(theta);
+    
+    Et = E_in*sin(theta);
+
+    index = index_in;
+    
+    return;
+  }
+
+
+  double Et;
+  double eta;
+  double phi;
+  int index;
+
+ private:
+
+
+
+};
+//end of class HepEntityI;
+
+} // end of namespace d0runi
+
+FASTJET_END_NAMESPACE
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/HepEntityIpre96.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/HepEntityIpre96.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/HepEntityIpre96.h	(revision 5)
@@ -0,0 +1,157 @@
+#ifndef  D0RunIconeJets_HepEntityPre96_class
+#define  D0RunIconeJets_HepEntityPre96_class
+
+#include "inline_maths.h"
+#include "HepEntityI.h"
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace d0runi{
+
+//Author: Lars Sonnenschein 25/Feb/2010
+//This is an example class fulfilling the minimal requirements needed by the
+//D0 RunI cone jet algorithm implementation prior to 1996, which is an inlined template class
+//See FERMILAB-Pub-97-242-E for details
+
+// This file is distributed with FastJet under the terms of the GNU
+// General Public License (v2). Permission to do so has been granted
+// by Lars Sonnenschein and the D0 collaboration (see COPYING for
+// details)
+//
+// History of changes in FastJet compared tothe original version of
+// HepEntity.h
+//
+// 2011-12-13  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * added license information
+//
+// 2011-11-14  Gregory Soyez  <soyez@fastjet.fr>
+//
+//         * removed some harmless warnings coming with the -Wshadow gcc option
+// 
+// 2011-10-06  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * put the code in the fastjet::d0runi namespace
+
+class HepEntityIpre96 : public HepEntityI {
+
+ public:
+
+  HepEntityIpre96() {
+    Et=0.;
+    eta=0.;
+    phi=0.;
+    Ex=0.;
+    Ey=0.;
+    Ez=0.;
+    index = -1;
+    phi_pre96=0.;
+    eta_pre96=0.;
+
+    return;
+  }
+
+
+ HepEntityIpre96(double E_in, double px_in, double py_in, double pz_in,
+		 int index_in = -1) : index(index_in) {
+   //Snowmass Et scheme    
+    double pt = sqrt(px_in*px_in+py_in*py_in);
+    double p = sqrt(pt*pt+pz_in*pz_in);
+    phi = inline_maths::phi(px_in,py_in);
+    double theta = asin(pt/p);
+    eta = inline_maths::eta(theta);
+
+    Et = E_in*sin(theta);
+
+    phi_pre96 = phi;
+    eta_pre96 = eta;
+
+    Ex = Et*cos(phi_pre96);
+    Ey = Et*sin(phi_pre96);
+    Ez = Et*sinh(eta_pre96);
+  
+    return;
+  }
+
+
+  inline double px() const {
+    return Et*cos(phi_pre96);
+  }
+
+  inline double py() const {
+    return Et*sin(phi_pre96);
+  }
+
+  inline double pz() const {
+    return Et*sinh(eta_pre96);
+  }
+  
+  inline double E() const {
+    return Et*cosh(eta_pre96);
+  }
+  
+ 
+  inline void Add(const HepEntityIpre96 el) {
+    //assumes Et, eta and phi stored accurately
+    double w2 = el.Et;
+    Et += el.Et;
+    w2 /= Et;
+    
+    eta += w2*(el.eta - eta);
+    phi += w2*inline_maths::delta_phi(el.phi, phi); 
+
+
+    Ex += el.Ex;
+    Ey += el.Ey;
+    Ez += el.Ez;
+    phi_pre96 = atan2(Ey, Ex);
+    double theta_pre96 = atan2(sqrt(Ex*Ex+Ey*Ey),Ez);
+    eta_pre96 = -log(tan(theta_pre96/2.));
+
+    return; 
+  }
+
+
+  inline void Fill(double E_in, double px_in, double py_in, double pz_in, int index_in) {
+    double pt = sqrt(px_in*px_in+py_in*py_in);
+    double p = sqrt(pt*pt+pz_in*pz_in);
+    phi = inline_maths::phi(px_in,py_in);
+    double theta = asin(pt/p);
+    eta = inline_maths::eta(theta);
+
+    Et = E_in*sin(theta);
+
+    
+    phi_pre96 = phi;
+    eta_pre96 = eta;
+
+    Ex = Et*cos(phi_pre96);
+    Ey = Et*sin(phi_pre96);
+    Ez = Et*sinh(eta_pre96);
+
+    index = index_in;
+
+    return;
+  }
+
+
+  double Ex;
+  double Ey;
+  double Ez;
+  int index;
+  double phi_pre96;
+  double eta_pre96;
+
+ private:
+
+
+
+};
+//end of class HepEntityIpre96;
+
+} // end of namespace d0runi
+
+FASTJET_END_NAMESPACE
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/fastjet/D0RunIBaseConePlugin.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/fastjet/D0RunIBaseConePlugin.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/fastjet/D0RunIBaseConePlugin.hh	(revision 5)
@@ -0,0 +1,157 @@
+#ifndef __D0RUNIBASECONEPLUGIN_HH__
+#define __D0RUNIBASECONEPLUGIN_HH__
+
+//STARTHEADER
+// $Id: D0RunIBaseConePlugin.hh 1778 2010-10-25 10:02:58Z soyez $
+//
+// Copyright (c) 2009-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/JetDefinition.hh"
+
+// questionable whether this should be in fastjet namespace or not...
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+//
+/// @ingroup internal
+/// \class D0RunIBaseConePlugin
+///
+/// D0RunIBaseConePlugin is base class for a plugin for FastJet (v3.0 or later) 
+/// that provides an interface to the D0 version of Run-I cone algorithm
+///
+/// Note that this base class is purely virtual and thus needs to be
+/// overloaded. In practice this means that you should use one of
+/// D0RunIConePlugin or D0RunIpre96ConePlugin.
+///
+/// The D0 code has been obtained from Lars Sonnenschein's web-space
+/// http://www-d0.fnal.gov/~sonne/D0RunIcone.tgz
+///
+/// The version of the D0 Run I code distributed here has been
+/// modified by the FastJet authors, so as to provide access to the
+/// contents of the jets (as is necessary for the plugin). This does
+/// not modify the results of the clustering.
+//
+//----------------------------------------------------------------------
+class D0RunIBaseConePlugin : public JetDefinition::Plugin {
+public:
+  /// A D0RunIConePlugin constructor which sets the "free" parameters of the
+  /// algorithm:
+  ///
+  ///  \param CONErad is the cone radius
+  ///
+  ///  \param JETmne is a minimum ET requirement on every iteration
+  ///    (jet dropped if Et < JETmne * Et_min_ratio ).
+  ///    The value that has been used by D0 for JETmne: 8 GeV 
+  ///    (and Et_min_ratio is 0.5)
+  ///
+  ///  \param SPlifr is the shared Et fraction splitting threshold, and
+  ///    a value of 0.5 was usually used by D0
+  ///
+  /// The remaining parameters of the algorithm are not to be modified if the algorithm
+  /// is to correspond to the one actually used by D0.
+  D0RunIBaseConePlugin (double CONErad_in, 
+			double JETmne_in, 
+			double SPLifr_in = _DEFAULT_SPLifr) :
+    _CONErad           (CONErad_in                 ),
+    _JETmne            (JETmne_in                  ),
+    _SPLifr            (SPLifr_in                  ),
+    _TWOrad            (_DEFAULT_TWOrad            ),
+    _D0_Angle          (_DEFAULT_D0_Angle          ),
+    _Increase_Delta_R  (_DEFAULT_Increase_Delta_R  ),
+    _Kill_Far_Clusters (_DEFAULT_Kill_Far_Clusters ),
+    _Jet_Et_Min_On_Iter(_DEFAULT_Jet_Et_Min_On_Iter),
+    _Far_Ratio         (_DEFAULT_Far_Ratio         ),
+    _Eitem_Negdrop     (_DEFAULT_Eitem_Negdrop     ),
+    _Et_Min_Ratio      (_DEFAULT_Et_Min_Ratio      ),
+    _Thresh_Diff_Et    (_DEFAULT_Thresh_Diff_Et    ){}
+
+  // some functions to return info about parameters
+  inline double CONErad           () const { return _CONErad           ;} //= 0.7;
+  inline double JETmne            () const { return _JETmne            ;} //= 8.0;
+  inline double SPLifr            () const { return _SPLifr            ;} // =0.5;
+  inline double TWOrad            () const { return _TWOrad            ;} //= 0.;
+  inline bool   D0_Angle          () const { return _D0_Angle          ;} // =false;
+  inline bool   Increase_Delta_R  () const { return _Increase_Delta_R  ;} // =true; 
+  inline bool   Kill_Far_Clusters () const { return _Kill_Far_Clusters ;} // =true; 
+  inline bool   Jet_Et_Min_On_Iter() const { return _Jet_Et_Min_On_Iter;} // =true; 
+  inline double Far_Ratio         () const { return _Far_Ratio         ;} // =0.5; 
+  inline double Eitem_Negdrop     () const { return _Eitem_Negdrop     ;} // =-1.0;
+  inline double Et_Min_Ratio      () const { return _Et_Min_Ratio      ;} // =0.5; 
+  inline double Thresh_Diff_Et    () const { return _Thresh_Diff_Et    ;} // =0.01;
+
+
+  /// access the split_ratio() also by the name overlap_threshold()
+  inline double overlap_threshold() const {return SPLifr();}
+
+  // the things that are required by base class
+  virtual std::string description () const = 0;
+
+  // the part that really does the clustering
+  virtual void run_clustering(ClusterSequence &) const = 0;
+
+  /// the plugin mechanism's standard way of accessing the jet radius
+  virtual double R() const {return CONErad();}
+
+protected:
+  template<typename HepEntityType>
+  void run_clustering_worker(ClusterSequence &) const;
+
+  //private:
+
+  double _CONErad  ;//= 0.7 
+  double _JETmne  ;//= 8.
+  //the parameters below have been found to be set to the values given below 
+  //in the original implementation, shouldn't be altered 
+  double _SPLifr            ;  //=0.5
+  double _TWOrad            ;  //=0.
+  bool   _D0_Angle          ;  //=false
+  bool   _Increase_Delta_R  ;  //=true
+  bool   _Kill_Far_Clusters ;  //=true
+  bool   _Jet_Et_Min_On_Iter;  //=true
+  double _Far_Ratio         ;  //=0.5         
+  double _Eitem_Negdrop     ;  //=-1.0
+  double _Et_Min_Ratio      ;  //=0.5
+  double _Thresh_Diff_Et    ;  //=0.01
+
+  // here are the variables for the default parameters of the D0 Run I Cone algorithm.
+  // They are set in the .cc file 
+  const static double _DEFAULT_SPLifr                  ;  // = 0.5; //shared Et fraction threshold
+  const static double _DEFAULT_TWOrad                  ;  // = 0.; //minimum Delta_R separation between cones
+  const static bool   _DEFAULT_D0_Angle                ;  // = false;
+  const static bool   _DEFAULT_Increase_Delta_R        ;  // = true;
+  const static bool   _DEFAULT_Kill_Far_Clusters       ;  // = true;
+  const static bool   _DEFAULT_Jet_Et_Min_On_Iter      ;  // = true;
+  const static double _DEFAULT_Far_Ratio               ;  // = 0.5;
+  const static double _DEFAULT_Eitem_Negdrop           ;  // = -1.0;
+  const static double _DEFAULT_Et_Min_Ratio            ;  // = 0.5;
+  const static double _DEFAULT_Thresh_Diff_Et          ;  // = 0.01;
+};
+
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
+
+#endif // __D0RUNIBASECONEPLUGIN_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/fastjet/D0RunIConePlugin.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/fastjet/D0RunIConePlugin.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/fastjet/D0RunIConePlugin.hh	(revision 5)
@@ -0,0 +1,97 @@
+#ifndef __D0RUNICONEPLUGIN_HH__
+#define __D0RUNICONEPLUGIN_HH__
+
+//STARTHEADER
+// $Id: D0RunIConePlugin.hh 1778 2010-10-25 10:02:58Z soyez $
+//
+// Copyright (c) 2009-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "D0RunIBaseConePlugin.hh"
+
+// questionable whether this should be in fastjet namespace or not...
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+//
+/// @ingroup plugins
+/// \class D0RunIConePlugin
+///
+/// A plugin for FastJet (v3.0 or later) that provides an interface to
+/// the D0 version of Run-I cone algorithm
+///
+/// The D0 code has been obtained from Lars Sonnenschein's web-space
+/// http://www-d0.fnal.gov/~sonne/D0RunIcone.tgz
+///
+/// The version of the D0 Run I code distributed
+/// here has been modified by the FastJet authors, so as to provide
+/// access to the contents of the jets (as is necessary for the
+/// plugin). This does not modify the results of the clustering.
+///
+/// The difference between this algorithm and the post-1996 version
+/// relates to the way the final jet momenta are calculated. Details
+/// are to be found in FERMILAB-PUB-97-242-E.
+//
+//----------------------------------------------------------------------
+class D0RunIConePlugin : public D0RunIBaseConePlugin {
+public:
+  /// The D0RunIConePlugin constructor, which sets the "free" parameters of the
+  /// algorithm:
+  ///
+  ///  \param CONErad is the cone radius
+  ///
+  ///  \param JETmne is a minimum ET requirement on every iteration
+  ///    (jet dropped if Et < JETmne * Et_min_ratio ).
+  ///    The value that has been used by D0 for JETmne: 8 GeV 
+  ///    (and Et_min_ratio is 0.5)
+  ///
+  ///  \param SPlifr is the shared Et fraction splitting threshold, and
+  ///    a value of 0.5 was usually used by D0
+  ///
+  /// The remaining parameters of the algorithm are not to be modified if the algorithm
+  /// is to correspond to the one actually used by D0.
+  ///
+  D0RunIConePlugin (double CONErad_in, double JETmne_in , double SPLifr_in = _DEFAULT_SPLifr)
+    : D0RunIBaseConePlugin(CONErad_in, JETmne_in , SPLifr_in){}
+
+  // the things that are required by base class
+  virtual std::string description () const;
+
+  // the part that really does the clustering
+  virtual void run_clustering(ClusterSequence &) const;
+
+private:
+  static bool _first_time;
+
+  /// print a banner for reference to the 3rd-party code
+  void _print_banner(std::ostream *ostr) const;
+};
+
+
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
+
+#endif // __D0RUNICONEPLUGIN_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/fastjet/D0RunIpre96ConePlugin.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/fastjet/D0RunIpre96ConePlugin.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/fastjet/D0RunIpre96ConePlugin.hh	(revision 5)
@@ -0,0 +1,97 @@
+#ifndef __D0RUNIPRE96CONEPLUGIN_HH__
+#define __D0RUNIPRE96CONEPLUGIN_HH__
+
+//STARTHEADER
+// $Id: D0RunIpre96ConePlugin.hh 1778 2010-10-25 10:02:58Z soyez $
+//
+// Copyright (c) 2009-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "D0RunIBaseConePlugin.hh"
+
+// questionable whether this should be in fastjet namespace or not...
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+//
+/// @ingroup plugins
+/// \class D0RunIpre96ConePlugin
+///
+/// A plugin for FastJet (v3.0 or later) that provides an interface to
+/// the pre 1996 D0 version of Run-I cone algorithm
+///
+/// The D0 code has been obtained from Lars Sonnenschein's web-space
+/// http://www-d0.fnal.gov/~sonne/D0RunIcone.tgz
+///
+/// The version of the D0 Run I code distributed
+/// here has been modified by the FastJet authors, so as to provide
+/// access to the contents of the jets (as is necessary for the
+/// plugin). This does not modify the results of the clustering.
+///
+/// The difference between this algorithm and the post-1996 version
+/// relates to the way the final jet momenta are calculated. Details
+/// are to be found in FERMILAB-PUB-97-242-E.
+//
+//----------------------------------------------------------------------
+class D0RunIpre96ConePlugin : public D0RunIBaseConePlugin {
+public:
+  /// The D0RunIpre96ConePlugin constructor, which sets the "free" parameters of the
+  /// algorithm:
+  ///
+  ///  \param CONErad is the cone radius
+  ///
+  ///  \param JETmne is a minimum ET requirement on every iteration
+  ///   (jet dropped if Et < JETmne * Et_min_ratio ).
+  ///   The value that has been used by D0 for JETmne: 8 GeV 
+  ///   (and Et_min_ratio is 0.5)
+  ///
+  ///  \param SPlifr is the shared Et fraction splitting threshold, and
+  ///   a value of 0.5 was usually used by D0
+  ///
+  /// The remaining parameters of the algorithm are not to be modified if the algorithm
+  /// is to correspond to the one actually used by D0.
+  ///
+  ///
+  D0RunIpre96ConePlugin (double CONErad_in, double JETmne_in , double SPLifr_in = _DEFAULT_SPLifr)
+    : D0RunIBaseConePlugin(CONErad_in, JETmne_in , SPLifr_in){}
+
+  // the things that are required by base class
+  virtual std::string description () const;
+
+  // the part that really does the clustering
+  virtual void run_clustering(ClusterSequence &) const;
+
+private:
+  static bool _first_time;
+
+  /// print a banner for reference to the 3rd-party code
+  void _print_banner(std::ostream *ostr) const;
+};
+
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
+
+#endif // __D0RUNIPRE96CONEPLUGIN_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/inline_maths.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/inline_maths.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunICone/inline_maths.h	(revision 5)
@@ -0,0 +1,149 @@
+#ifndef INLINE_MATHS
+#define INLINE_MATHS
+
+// This file is distributed with FastJet under the terms of the GNU
+// General Public License (v2). Permission to do so has been granted
+// by Lars Sonnenschein and the D0 collaboration (see COPYING for
+// details)
+//
+// History of changes in FastJet compared tothe original version of
+// inline_math.h
+//
+// 2011-12-13  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * added license information
+//
+// 2011-10-06  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * put the code in the fastjet::d0runi namespace
+
+#include <cmath>
+#include <cerrno>
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+//using namespace std;
+
+namespace d0runi{
+namespace inline_maths {
+
+const double PI = fabs(acos(-1.));
+
+const double TWOPI = 2*PI;
+
+
+inline double sqr(double a) {
+  return a*a;
+}
+
+
+
+inline double min(double a, double b) {
+  return (a < b) ? a : b;
+}
+
+
+
+inline double delta_phi(double phi1, double phi2) {
+  double dphi = min( double(fabs(phi1-phi2)), double(2.*PI-fabs(phi1-phi2)) );
+  return (phi1 < phi2) ? -dphi : dphi;
+}
+
+
+
+inline double phi(double px, double py) {
+  return atan2(py, px);
+}
+
+
+
+inline double y(double E, double pz) {
+  errno=0;
+  double y;
+  //cout << "inline_maths: ";
+  if (fabs(E-pz) == 0.) {
+    //    cout << "Error in header mathe.h: division by 0 in function y!" <<  " p=" << p << " pz=" << pz << endl;
+    //  exit(721);
+    errno=721;
+    y = 99999.;
+  }
+  else {
+    y = 0.5*log((E+pz)/(E-pz));
+  }
+  //cout << "y: E=" << E << " pz=" << pz << " y=" << y << endl;
+  return y;
+}
+
+
+
+
+inline double eta(double p, double pz) {
+  errno=0;
+  double eta;
+  //cout << "inline_maths: ";
+  if (fabs(p-pz) == 0.) {
+    //    cout << "Error in header mathe.h: division by 0 in function eta!" <<  " p=" << p << " pz=" << pz << endl;
+    //  exit(721);
+    errno=721;
+    eta = 99999.;
+  }
+  else {
+    eta = 0.5*log((p+pz)/(p-pz));
+  }
+  //cout << "eta: p=" << p << " pz=" << pz << " eta=" << eta << endl;
+  return eta;
+}
+
+
+
+
+ inline double eta(double px, double py, double pz) {
+   errno=0;
+   double eta;
+  //cout << "inline_maths: ";
+   double p = sqrt(px*px+py*py+pz*pz);
+   if (fabs(p-pz) == 0.) {
+    //    cout << "Error in header mathe.h: division by 0 in function eta!" <<  " p=" << p << " pz=" << pz << endl;
+    //  exit(721);
+    errno=721;
+    eta = 99999.;
+  }
+  else {
+    eta = 0.5*log((p+pz)/(p-pz));
+  }
+  //cout << "eta: p=" << p << " pz=" << pz << " eta=" << eta << endl;
+  return eta;
+}
+
+
+
+ inline double eta(double theta) {
+   double eta = -log(tan(theta/2.));
+   
+   return eta;
+ }
+ 
+
+ inline double theta(double eta) {
+   double theta = 2.*atan(exp(-eta));
+   
+   return theta;
+ }
+ 
+ inline double theta(double px, double py, double pz) {
+   double Eta = eta(px, py, pz);
+   double theta = 2.*atan(exp(-Eta));
+   
+   return theta;
+ }
+ 
+
+
+} //end usename inline_maths
+} //end usename d0runi
+
+FASTJET_END_NAMESPACE
+
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/ConeJetInfo.hpp
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/ConeJetInfo.hpp	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/ConeJetInfo.hpp	(revision 5)
@@ -0,0 +1,89 @@
+#ifndef D0RunIIconeJets_CONEJETINFO_HPP
+#define D0RunIIconeJets_CONEJETINFO_HPP
+
+// --------------------------------------------------------------------------
+// ConeJetInfo.hpp
+// Purpose: Hold informations about the cone jets that do not fit into
+//   a CalTClusterChunk/IntEclusterChunk.
+//
+// Created: Laurent Duflot 31-JUL-2000
+//
+// Modified:
+//  09-Aug-2000 Laurent Duflot
+//   + add initial jet ET (i.e. before split/merge) 
+//    1-May-2007 Lars Sonnenschein
+//    extracted from D0 software framework and modified to remove subsequent dependencies
+//
+//
+// This file is distributed with FastJet under the terms of the GNU
+// General Public License (v2). Permission to do so has been granted
+// by Lars Sonnenschein and the D0 collaboration (see COPYING for
+// details)
+//
+// History of Changes in FastJet compared tothe original version of
+// ConeJetInfo.hpp
+//
+// 2011-12-13  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * added license information
+//
+// 2011-11-14  Gregory Soyez  <soyez@fastjet.fr>
+//
+//         * changed the name of a few parameters to avoid a gcc
+//           -Wshadow warning
+//
+// 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * put the code in the fastjet::d0 namespace
+//
+// --------------------------------------------------------------------------
+
+
+//#define CONEJET_SPLITMERGE_MOD 100
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace d0{
+
+namespace D0RunIIconeJets_CONEJETINFO {
+
+const int CONEJET_SPLITMERGE_MOD = 100;
+
+class ConeJetInfo
+{
+public:
+  ConeJetInfo(): _seedET(0.), _initial_jet_ET(0.), _nb_split_merge(0) {};
+  ConeJetInfo( float seedET_in): _seedET(seedET_in),  _nb_split_merge(0) {}; 
+  ConeJetInfo( float seedET_in, float initialET_in, int nb_split, int nb_merge): 
+    _seedET(seedET_in), _initial_jet_ET(initialET_in), 
+    _nb_split_merge(nb_merge + CONEJET_SPLITMERGE_MOD*nb_split) {};
+  ~ConeJetInfo() {};
+
+  float seedET() const {return _seedET;};
+  float initialET() const { return _initial_jet_ET; };
+  int nbSplit() const {return _nb_split_merge/CONEJET_SPLITMERGE_MOD;};
+  int nbMerge() const {return _nb_split_merge%CONEJET_SPLITMERGE_MOD;};
+  int SplitMergeWord() const {return _nb_split_merge;};
+
+  void initialET(float ET) { _initial_jet_ET = ET;};
+  void splitted() { _nb_split_merge += CONEJET_SPLITMERGE_MOD;};
+  void merged() { _nb_split_merge += 1;};
+
+
+private:
+  float _seedET;
+  float _initial_jet_ET;  // stable cone ET before split/merge
+  int _nb_split_merge;
+  
+};
+
+}
+
+}  // namespace d0
+
+FASTJET_END_NAMESPACE
+
+#endif
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/ConeSplitMerge.hpp
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/ConeSplitMerge.hpp	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/ConeSplitMerge.hpp	(revision 5)
@@ -0,0 +1,336 @@
+#ifndef  D0RunIIconeJets_CONESPLITMERGE
+#define  D0RunIIconeJets_CONESPLITMERGE
+// ---------------------------------------------------------------------------
+// ConeSplitMerge.hpp
+//
+// Created: 28-JUL-2000 Francois Touze
+//
+// Purpose: Implements the pT ordered jet split/merge algorithm for the 
+//   Improved Legacy Cone Algorithm split/merge algo.
+//
+// Modified:
+//   31-JUL-2000  Laurent Duflot
+//     + introduce support for additional informations (ConeJetInfo)
+//    1-AUG-2000  Laurent Duflot
+//     + jet merge criteria was wrong, now calculate shared_ET and compare to 
+//       neighbour jet pT.
+//     + split was incomplete: shared items not really removed from jets.
+//    4-Aug-2000  Laurent Duflot
+//     + use item methods y() and phi() rather than p4vec() and then P2y and 
+//       P2phi
+//    7-Aug-2000  Laurent Duflot 
+//     + force the list to be organized by decreasing ET and, for identical ET,
+//       by decreasing seedET. Identical protojets can be found by eg nearby
+//       seeds. The seedET ordering is such that for identical jets, the one
+//       with the highest seedET is kept, which is what we want for efficiency
+//       calculations.
+//     + avoid unecessary copies of lists by using reference when possible
+//    9-Aug-2000  Laurent Duflot
+//     + save initial jet ET before split/merge
+//    1-May-2007 Lars Sonnenschein
+//    extracted from D0 software framework and modified to remove subsequent dependencies
+//
+//
+// This file is distributed with FastJet under the terms of the GNU
+// General Public License (v2). Permission to do so has been granted
+// by Lars Sonnenschein and the D0 collaboration (see COPYING for
+// details)
+//
+// History of changes in FastJet compared tothe original version of
+// ConeSplitMerge.hpp
+//
+// 2011-12-13  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * added license information
+//
+// 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * put the code in the fastjet::d0 namespace
+//
+// 2007-12-14  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * replaced make_pair by std::make_pair
+//
+// ---------------------------------------------------------------------------
+
+
+#include <iostream>
+#include <map>
+#include <utility>
+#include <vector>
+#include "ProtoJet.hpp"
+
+//using namespace D0RunIIconeJets_CONEJETINFO;
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace d0{
+
+//
+// this class is used to order ProtoJets by decreasing ET and seed ET
+template <class Item>
+class ProtoJet_ET_seedET_order
+{
+public:
+  bool operator()(const ProtoJet<Item> & first, const ProtoJet<Item> & second)
+  {
+    if ( first.pT() > second.pT() ) return true;
+    else
+      if ( first.pT() < second.pT() ) return false;
+      else return ( first.info().seedET() > second.info().seedET() );
+  }
+};
+
+
+template <class Item>
+class ConeSplitMerge {
+
+public :
+
+  typedef std::multimap<ProtoJet<Item>,float,ProtoJet_ET_seedET_order<Item> > PJMMAP;
+  
+  ConeSplitMerge();
+  ConeSplitMerge(const std::vector<ProtoJet<Item> >& jvector);
+  ConeSplitMerge(const std::list<ProtoJet<Item> >& jlist);
+  ~ConeSplitMerge() {;}
+  void split_merge(std::vector<ProtoJet<Item> >& ecv,float s, float pT_min_leading_protojet, float pT_min_second_protojet, int MergeMax, float pT_min_noMergeMax);
+
+private :
+  PJMMAP _members;
+};
+///////////////////////////////////////////////////////////////////////////////
+template<class Item>
+ConeSplitMerge<Item>::ConeSplitMerge():_members() {;}
+
+template<class Item>
+ConeSplitMerge<Item>::ConeSplitMerge(const std::vector<ProtoJet<Item> >& jvector) 
+{
+  // sort proto_jets in Et descending order
+  typename std::vector<ProtoJet<Item> >::const_iterator jt;
+  for(jt = jvector.begin(); jt != jvector.end(); ++jt) 
+  {
+    // this is supposed to be a stable cone, declare so
+    ProtoJet<Item> jet(*jt);
+    jet.NowStable();
+    _members.insert(std::make_pair(jet,jet.pT()));
+  }
+}
+
+template<class Item>
+ConeSplitMerge<Item>::ConeSplitMerge(const std::list<ProtoJet<Item> >& jlist) 
+{
+  //_max_nb_items =-1;
+  // sort proto_jets in Et descending order
+  typename std::list<ProtoJet<Item> >::const_iterator jt;
+  for(jt = jlist.begin(); jt != jlist.end(); ++jt) 
+  {
+    // this is supposed to be a stable cone, declare so
+    ProtoJet<Item> jet(*jt);
+    jet.NowStable();
+    _members.insert(std::make_pair(jet,jet.pT()));
+  }
+}
+
+template<class Item>
+void ConeSplitMerge<Item>::split_merge(std::vector<ProtoJet<Item> >& jcv,
+				       float shared_ET_fraction,
+				       float pT_min_leading_protojet, float pT_min_second_protojet,
+				       int MergeMax, float pT_min_noMergeMax) 
+{
+  while(!_members.empty()) 
+  {
+    /*
+    {
+      std::cout << std::endl;
+      std::cout << " ---------------  list of protojets ------------------ " <<std::endl;
+      for ( PJMMAP::iterator it = _members.begin();
+	    it != _members.end(); ++it)
+      {
+	std::cout << " pT y phi " << (*it).pT() << " " << (*it).y() << " " << (*it).phi() << " " << (*it).info().seedET() <<  " " << (*it).info().nbMerge() << " " << (*it).info().nbSplit() << std::endl;
+      }
+      std::cout << " ----------------------------------------------------- " <<std::endl;
+    }
+    */
+
+
+    // select highest Et jet
+    typename PJMMAP::iterator itmax= _members.begin();
+    ProtoJet<Item> imax((*itmax).first);
+    const std::list<const Item*>& ilist(imax.LItems());
+
+    _members.erase(itmax);
+ 
+    // does jet share items?
+    bool share= false;
+    float shared_ET = 0.;
+    typename PJMMAP::iterator jtmax;
+    typename PJMMAP::iterator jt;
+    for(jt = _members.begin(); jt != _members.end(); ++jt) 
+    {
+      const std::list<const Item*>& jlist((*jt).first.LItems());
+      typename std::list<const Item*>::const_iterator tk;
+      int count;
+      for(tk = ilist.begin(), count = 0; tk != ilist.end(); 
+	  ++tk, ++count) 
+      {
+	typename std::list<const Item*>::const_iterator where= 
+	  find(jlist.begin(),jlist.end(),*tk);   
+	if(where != jlist.end()) 
+	{
+	  share= true;
+	  shared_ET += (*tk)->pT();
+	}
+      }
+      if(share) 
+      {
+	jtmax = jt;
+	break;
+      }
+    }
+    
+    if(!share) {
+      // add jet to the final jet list
+      jcv.push_back(imax);
+      //std::cout << " final jet " << imax.pT() << " "<< imax.info().nbMerge() << " " << imax.info().nbSplit() << std::endl; 
+    }
+    else 
+    {
+      // find highest Et neighbor
+      ProtoJet<Item> jmax((*jtmax).first);
+
+      // drop neighbor
+      _members.erase(jtmax);
+
+
+      //std::cout << " split or merge ? " << imax.pT() << " " << shared_ET << " " << jmax.pT() << " " << s << " " << (jmax.pT())*s << std::endl;
+
+      // merge
+      if( shared_ET > (jmax.pT())*shared_ET_fraction 
+	  && (imax.pT() > pT_min_leading_protojet || jmax.pT() > pT_min_second_protojet)
+	  && (imax.info().nbMerge() < MergeMax || imax.pT() > pT_min_noMergeMax))
+	{
+	  // add neighbor's items to imax
+	  const std::list<const Item*>& jlist(jmax.LItems());
+	  typename std::list<const Item*>::const_iterator tk;
+	  typename std::list<const Item*>::const_iterator iend= ilist.end();
+	  bool same = true; // is jmax just the same as imax ? 
+	  for(tk = jlist.begin(); tk != jlist.end(); ++tk) 
+	    {
+	      typename std::list<const Item*>::const_iterator where= 
+		find(ilist.begin(),iend,*tk);   
+	      if(where == iend) 
+		{
+		  imax.addItem(*tk);
+		  same = false;
+		}
+	    }
+	  if ( ! same ) 
+	    {
+	      // recalculate
+	      //float old_pT = imax.pT();
+	      
+	      imax.updateJet();
+	      imax.merged();
+	      //std::cout << " jet merge :: " << old_pT << " " << jmax.pT() << " " << imax.pT() << " "<< imax.info().nbMerge() << " " << imax.info().nbSplit() << std::endl; 
+	    }
+	}
+      
+      //split and assign removed shared cells from lowest pT protojet
+      else if(shared_ET > (jmax.pT())*shared_ET_fraction)
+      {
+	// here we need to pull the lists, because there are items to remove                                                                           
+	std::list<const Item*> ilist(imax.LItems());
+	std::list<const Item*> jlist(jmax.LItems());
+
+        typename std::list<const Item*>::iterator tk;
+        for(tk = jlist.begin(); tk != jlist.end(); )
+	  {
+	    typename std::list<const Item*>::iterator where=
+	      find(ilist.begin(),ilist.end(),*tk);
+	    if(where != ilist.end()) {
+	      tk = jlist.erase(tk);
+	    }
+	    else ++tk;
+	  }
+	
+        jmax.erase();
+
+        for ( typename std::list<const Item*>::const_iterator it = jlist.begin();
+              it != jlist.end(); ++it) jmax.addItem(*it);
+
+        // recalculated jet quantities 
+        jmax.updateJet();
+        jmax.splitted();
+        //std::cout << " jet split 1 :: " << jmax.pT() << " "<< jmax.info().nbMerge() << " " << jmax.info().nbSplit() << std::endl;                         
+        _members.insert(std::make_pair(jmax,jmax.pT()));
+      }
+
+      // split and assign shared cells to nearest protojet
+      else 
+      {
+	// here we need to pull the lists, because there are items to remove
+	std::list<const Item*> ilist(imax.LItems());
+	std::list<const Item*> jlist(jmax.LItems());
+	
+	typename std::list<const Item*>::iterator tk;
+	for(tk = jlist.begin(); tk != jlist.end(); ) 
+	{
+	  typename std::list<const Item*>::iterator where= 
+	    find(ilist.begin(),ilist.end(),*tk);
+	  if(where != ilist.end()) {
+	    float yk   = (*tk)->y();
+	    float phik = (*tk)->phi();
+	    float di= RD2(imax.y(),imax.phi(),yk,phik);
+	    float dj= RD2(jmax.y(),jmax.phi(),yk,phik);
+	    if(dj > di) 
+	    {
+	      tk = jlist.erase(tk);
+	      //std::cout << " shared item " << (*tk)->pT() << " removed from neighbour jet " << std::endl;
+	    }
+	    else
+	    {
+	      ilist.erase(where);
+	      ++tk;
+	      //std::cout << " shared item " << (*tk)->pT() << " removed from leading jet " << std::endl;
+	    }
+	  }
+	  else ++tk;
+	}
+	// recalculate jets imax and jmax
+	
+	// first erase all items
+	imax.erase();
+	// put items that are left
+	for ( typename std::list<const Item*>::const_iterator it = ilist.begin();
+	      it != ilist.end(); ++it) imax.addItem(*it);
+	// recalculated jet quantities
+	imax.updateJet();
+	imax.splitted();
+	//std::cout << " jet split 2 :: " << imax.pT() << " "<< imax.info().nbMerge() << " " << imax.info().nbSplit() << std::endl; 
+
+
+	// first erase all items
+	jmax.erase();
+	// put items that are left
+	for ( typename std::list<const Item*>::const_iterator it = jlist.begin();
+	      it != jlist.end(); ++it) jmax.addItem(*it);
+	// recalculated jet quantities
+	jmax.updateJet();
+	jmax.splitted();
+	//std::cout << " jet split " << jmax.pT() << " "<< jmax.info().nbMerge() << " " << jmax.info().nbSplit() << std::endl; 
+
+	_members.insert(std::make_pair(jmax,jmax.pT()));
+      }
+      _members.insert(std::make_pair(imax,imax.pT()));
+    }
+  } // while
+}
+///////////////////////////////////////////////////////////////////////////////
+
+}  // namespace d0
+
+FASTJET_END_NAMESPACE
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/D0RunIIConePlugin.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/D0RunIIConePlugin.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/D0RunIIConePlugin.cc	(revision 5)
@@ -0,0 +1,166 @@
+//STARTHEADER
+// $Id: D0RunIIConePlugin.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/D0RunIIConePlugin.hh"
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/Error.hh"
+#include <sstream>
+
+// D0 stuff
+#include <list>
+#include "ILConeAlgorithm.hpp"
+#include "HepEntity.h"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+using namespace d0;
+
+const double D0RunIIConePlugin::_DEFAULT_split_ratio              = 0.5  ; // overlap threshold
+const double D0RunIIConePlugin::_DEFAULT_far_ratio                = 0.5  ;
+const double D0RunIIConePlugin::_DEFAULT_Et_min_ratio             = 0.5  ;
+const bool   D0RunIIConePlugin::_DEFAULT_kill_duplicate           = true ;
+const double D0RunIIConePlugin::_DEFAULT_duplicate_dR             = 0.005; 
+const double D0RunIIConePlugin::_DEFAULT_duplicate_dPT            = 0.01 ; 
+const double D0RunIIConePlugin::_DEFAULT_search_factor            = 1.0  ; 
+const double D0RunIIConePlugin::_DEFAULT_pT_min_leading_protojet  = 0.   ; 
+const double D0RunIIConePlugin::_DEFAULT_pT_min_second_protojet   = 0.   ;
+const int    D0RunIIConePlugin::_DEFAULT_merge_max                = 10000; 
+const double D0RunIIConePlugin::_DEFAULT_pT_min_nomerge           = 0.   ;
+
+bool D0RunIIConePlugin::_first_time = true;
+
+string D0RunIIConePlugin::description () const {
+  ostringstream desc;
+  
+  desc << "D0 Run II Improved Legacy (midpoint) cone jet algorithm, with ";
+  desc << "cone_radius = "        << cone_radius        () << ", "
+       << "min_jet_Et = "         << min_jet_Et         () << ", " 
+       << "split_ratio = "        << split_ratio        ();
+
+  return desc.str();
+}
+
+
+void D0RunIIConePlugin::run_clustering(ClusterSequence & clust_seq) const {
+  // print a banner if we run this for the first time
+  _print_banner(clust_seq.fastjet_banner_stream());
+ 
+  // create the entities needed by the D0 code
+  vector<HepEntity> entities(clust_seq.jets().size());
+  list<const HepEntity * > ensemble;
+  for (unsigned i = 0; i < clust_seq.jets().size(); i++) {
+    entities[i].Fill(clust_seq.jets()[i].E(),
+                     clust_seq.jets()[i].px(),
+                     clust_seq.jets()[i].py(),
+                     clust_seq.jets()[i].pz(),
+                     i);
+    // use only the particles that do not have infinite rapidity
+    if (abs(entities[i].pz) < entities[i].E) {
+      ensemble.push_back(& (entities[i]));
+    }
+  }
+
+  // prepare the D0 algorithm
+  ILConeAlgorithm<HepEntity> 
+    ilegac(cone_radius(), 
+           min_jet_Et(), 
+           split_ratio(),
+	   far_ratio(), 
+           Et_min_ratio(), 
+           kill_duplicate(), 
+           duplicate_dR(), 
+	   duplicate_dPT(), 
+           search_factor(), 
+           pT_min_leading_protojet(), 
+	   pT_min_second_protojet(), 
+           merge_max(), 
+           pT_min_nomerge());
+
+  // run the algorithm
+  float Item_ET_Threshold = 0.;
+  list<HepEntity> jets;
+  ilegac.makeClusters(jets, ensemble, Item_ET_Threshold);
+
+  // now transfer the information about the jets into the
+  // FastJet structure
+  for(int i = ilegac.ilcv.size()-1; i >= 0; i--) {
+    
+    std::list<const HepEntity*> tlist = ilegac.ilcv[i].LItems();
+    std::list<const HepEntity*>::iterator tk;
+    
+    // get first particle in list
+    tk = tlist.begin();
+
+    // if there is no particle, just discard it
+    // Note: this unexpected behaviour has been observed when the
+    //       min_jet_Et parameter was set to 0
+    if (tk==tlist.end())
+      continue;
+
+    int jet_k = (*tk)->index;
+    // now merge with remaining particles in list
+    tk++;
+    for (; tk != tlist.end(); tk++) {
+      int jet_i = jet_k;
+      int jet_j = (*tk)->index;
+      // do a fake recombination step with dij=0
+      double dij = 0.0;
+      clust_seq.plugin_record_ij_recombination(jet_i, jet_j, dij, jet_k);
+    }
+
+    // NB: put a sensible looking d_iB just to be nice...
+    double d_iB = clust_seq.jets()[jet_k].perp2();
+    clust_seq.plugin_record_iB_recombination(jet_k, d_iB);
+
+  }
+}
+
+// print a banner for reference to the 3rd-party code
+void D0RunIIConePlugin::_print_banner(ostream *ostr) const{
+  if (! _first_time) return;
+  _first_time=false;
+
+  // make sure the user has not set the banner stream to NULL
+  if (!ostr) return;  
+
+  (*ostr) << "#--------------------------------------------------------------------------" << endl;
+  (*ostr) << "# You are running the D0 Run II Cone plugin for FastJet                    " << endl;
+  (*ostr) << "# Original code by the D0 collaboration, provided by Lars Sonnenschein;    " << endl;
+  (*ostr) << "# interface by FastJet authors                                             " << endl;
+  (*ostr) << "# If you use this plugin, please cite                                      " << endl;
+  (*ostr) << "#   G. C. Blazey et al., hep-ex/0005012                                    " << endl;
+  (*ostr) << "#   V. M. Abazov et al. [D0 Collaboration], arXiv:1110.3771 [hep-ex]       " << endl; 
+  (*ostr) << "# in addition to the usual FastJet reference.                              " << endl;
+  (*ostr) << "#--------------------------------------------------------------------------" << endl;
+
+  // make sure we really have the output done.
+  ostr->flush();
+}
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/HepEntity.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/HepEntity.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/HepEntity.h	(revision 5)
@@ -0,0 +1,121 @@
+#ifndef  D0RunIIconeJets_HepEntity_class
+#define  D0RunIIconeJets_HepEntity_class
+
+#include "inline_maths.h"
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace d0{
+
+//Author: Lars Sonnenschein 28/Mar/2007
+//This is an example class fulfilling the minimal requirements needed by the
+//D0 RunII cone jet algorithm implementation, which is an inlined template class
+//
+//
+// This file is distributed with FastJet under the terms of the GNU
+// General Public License (v2). Permission to do so has been granted
+// by Lars Sonnenschein and the D0 collaboration (see COPYING for
+// details)
+//
+// History of changes in FastJet compared tothe original version of
+// HepEntity.h
+//
+// 2011-12-13  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * added license information
+//
+// 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * put the code in the fastjet::d0 namespace
+//
+// 2007-12-14  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * added an index member
+
+class HepEntity {
+
+ public:
+
+  HepEntity() {
+    E=0.;
+    px=0.;
+    py=0.;
+    pz=0.;
+    index = -1;
+    return;
+  }
+
+
+  HepEntity(double E_in, double px_in, double py_in, double pz_in, int index_in = -1) : 
+    E(E_in), px(px_in), py(py_in), pz(pz_in), index(index_in) {
+    return;
+  }
+
+
+    HepEntity(const HepEntity& in) : E(in.E), px(in.px), py(in.py), pz(in.pz), index(in.index) {
+    return;
+  }
+
+  
+  inline double y() const {
+    return inline_maths::y(E,pz);
+  }
+
+
+  inline double phi() const {
+     return inline_maths::phi(px,py);
+  }
+
+
+  inline double pT() const {
+     return sqrt(inline_maths::sqr(px)+inline_maths::sqr(py));
+  }
+
+
+  inline void p4vec(float* p) const {
+    p[0] = px;
+    p[1] = py;
+    p[2] = pz;
+    p[3] = E;
+    return;
+  }
+
+  inline void Add(const HepEntity el) {
+    E += el.E;
+    px += el.px;
+    py += el.py;
+    pz += el.pz;
+    return;
+  }
+
+  inline void Fill(double E_in, double px_in, double py_in, double pz_in, int index_in = -1) {
+    E = E_in;
+    px = px_in;
+    py = py_in;
+    pz = pz_in;
+    index = index_in;
+    return;
+  }
+
+
+  double E;
+  double px;
+  double py;
+  double pz;
+  int    index;
+
+ private:
+
+
+
+};
+//end of class HepEntity;
+
+
+}  // namespace d0
+
+FASTJET_END_NAMESPACE
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/ILConeAlgorithm.hpp
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/ILConeAlgorithm.hpp	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/ILConeAlgorithm.hpp	(revision 5)
@@ -0,0 +1,604 @@
+#ifndef  D0RunIIconeJets_ILCONEALGORITHM
+#define  D0RunIIconeJets_ILCONEALGORITHM
+// ---------------------------------------------------------------------------
+// ILConeAlgorithm.hpp
+//
+// Created: 28-JUL-2000 Francois Touze (+ Laurent Duflot)
+//
+// Purpose: Implements the Improved Legacy Cone Algorithm
+//
+// Modified:
+//   31-JUL-2000  Laurent Duflot
+//     + introduce support for additional informations (ConeJetInfo)
+//    1-AUG-2000  Laurent Duflot
+//     + seedET for midpoint jet is -999999., consistent with seedET ordering
+//       in ConeSplitMerge: final jets with seedET=-999999. will be midpoint 
+//       jets which were actually different from stable cones.
+//    4-Aug-2000  Laurent Duflot
+//     + remove unecessary copy in TemporaryJet::is_stable()
+//   11-Aug-2000  Laurent Duflot
+//     + remove using namespace std
+//     + add threshold on item. The input list to makeClusters() IS modified
+//   20-June-2002 John Krane
+//     + remove bug in midpoint calculation based on pT weight
+//     + started to add new midpoint calculation based on 4-vectors,
+//       but not enough info held by this class
+//   24-June-2002 John Krane
+//     + modify is_stable() to not iterate if desired 
+//       (to expand search cone w/out moving it)
+//     + added search cone logic for initial jets but not midpoint jets as per
+//       agreement with CDF
+//   19-July-2002 John Krane
+//     + _SEARCH_CONE size factor now provided by calreco/CalClusterReco.cpp 
+//     + (default = 1.0 = like original ILCone behavior)
+//   10-Oct-2002 John Krane
+//     + Check min Pt of cone with full size first, then iterate with search cone
+//   07-Dec-2002 John Krane
+//     + speed up the midpoint phi-wrap solution
+//   01-May-2007 Lars Sonnenschein
+//   extracted from D0 software framework and modified to remove subsequent dependencies
+//
+//
+// This file is distributed with FastJet under the terms of the GNU
+// General Public License (v2). Permission to do so has been granted
+// by Lars Sonnenschein and the D0 collaboration (see COPYING for
+// details)
+//
+// History of changes in FastJet compared tothe original version of
+// ProtoJet.hpp
+//
+// 2012-06-12  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * Replaced addItem(...) by this->addItem(...) to allow
+//          compilation with gcc 4.7 which no longer performs
+//          unqualified template lookups. See
+//          e.g. http://gcc.gnu.org/gcc-4.7/porting_to.html
+//
+// 2011-12-13  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * added license information
+//
+// 2011-11-14  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * changed the name of a few parameters to avoid a gcc
+//          -Wshadow warning
+//
+// 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * put the code in the fastjet::d0 namespace
+//
+// 2007-12-14  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * moved the 'std::vector<ProtoJet<Item> > ilcv' structure
+//          containing the info about the final jets from a local
+//          variable to a class variable (for integration in the
+//          FastJet plugin core)
+//
+// ---------------------------------------------------------------------------
+
+#include <vector>
+#include <list>
+#include <utility>  // defines pair<,>
+#include <map>
+#include <algorithm>
+#include <iostream>
+
+
+//#include "energycluster/EnergyClusterReco.hpp"
+//#include "energycluster/ProtoJet.hpp"
+#include "ProtoJet.hpp"
+//#include "energycluster/ConeSplitMerge.hpp"
+#include "ConeSplitMerge.hpp"
+//#include "energycluster/ConeJetInfoChunk.hpp"
+
+#include "inline_maths.h"
+
+///////////////////////////////////////////////////////////////////////////////
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace d0{
+
+using namespace inline_maths;
+
+/*
+ NB: Some attempt at optimizing the code has been made by ordering the object
+     along rapidity but this did not improve the speed. There are traces of 
+     these atemps in the code, that will be cleaned up in the future.
+ */
+
+// at most one of those !
+// order the input list and use lower_bound() and upper_bound() to restrict the
+// on item to those that could possibly be in the cone.
+//#define ILCA_USE_ORDERED_LIST
+
+// idem but use an intermediate multimap in hope that lower_bound() and 
+// upper_bound() are faster in this case.
+//#define ILCA_USE_MMAP
+
+
+#ifdef ILCA_USE_ORDERED_LIST
+// this class is used to order the item list along rapidity
+template <class Item>
+class rapidity_order
+{
+public:
+  bool operator()(const Item* first, const Item* second)
+  {
+    return (first->y() < second->y());
+  }
+  bool operator()(float const & first, const Item* second)
+  {
+    return (first  < second->y());
+  }
+  bool operator()(const Item* first, float const& second)
+  {
+    return (first->y() < second);
+  }
+};
+#endif
+
+
+//template <class Item,class ItemAddress,class IChunk>
+template <class Item>
+class ILConeAlgorithm 
+{
+
+public:
+
+  // default constructor (default parameters are crazy: you should not use that
+  // constructor !)
+  ILConeAlgorithm():
+    _CONE_RADIUS(0.),
+    _MIN_JET_ET(99999.),
+    _ET_MIN_RATIO(0.5),
+    _FAR_RATIO(0.5),
+    _SPLIT_RATIO(0.5),
+    _DUPLICATE_DR(0.005),
+    _DUPLICATE_DPT(0.01),
+    _SEARCH_CONE(0.5),
+    _PT_MIN_LEADING_PROTOJET(0), 
+    _PT_MIN_SECOND_PROTOJET(0), 
+    _MERGE_MAX(10000), 
+    _PT_MIN_noMERGE_MAX(0)
+  {;}
+
+  // full constructor
+  ILConeAlgorithm(float cone_radius, float min_jet_Et, float split_ratio,
+		  float far_ratio=0.5, float Et_min_ratio=0.5,
+		  bool kill_duplicate=true, float duplicate_dR=0.005, 
+		  float duplicate_dPT=0.01, float search_factor=1.0, 
+		  float pT_min_leading_protojet=0., float pT_min_second_protojet=0.,
+		  int merge_max=10000, float pT_min_nomerge=0.) :
+    // cone radius
+    _CONE_RADIUS(cone_radius), 
+    // minimum jet ET
+    _MIN_JET_ET(min_jet_Et), 
+    // stable cones must have ET > _ET_MIN_RATIO*_MIN_JET_ET at any iteration
+    _ET_MIN_RATIO(Et_min_ratio),
+    // precluster at least _FAR_RATIO*_CONE_RADIUS away from stable cones
+    _FAR_RATIO(far_ratio), 
+    // split or merge criterium           
+    _SPLIT_RATIO(split_ratio),
+    _DUPLICATE_DR(duplicate_dR),
+    _DUPLICATE_DPT(duplicate_dPT),
+    _SEARCH_CONE(cone_radius/search_factor),
+    // kill stable cone if within _DUPLICATE_DR and delta(pT)<_DUPLICATE_DPT
+    // of another stable cone.
+    _KILL_DUPLICATE(kill_duplicate),
+    _PT_MIN_LEADING_PROTOJET(pT_min_leading_protojet),
+    _PT_MIN_SECOND_PROTOJET(pT_min_second_protojet),
+    _MERGE_MAX(merge_max),
+    _PT_MIN_noMERGE_MAX(pT_min_nomerge)
+    {;}
+
+  //destructor
+  ~ILConeAlgorithm() {;}
+
+  // make jet clusters using improved legacy cone algorithm
+  //void makeClusters(const EnergyClusterReco* r,
+  void makeClusters(
+		    // the input list modified (ordered)
+		    std::list<Item> &jets,
+		    std::list<const Item*>& itemlist, 
+		    //float zvertex,   
+		    ////std::list<const Item*>& itemlist);   
+		    //const EnergyClusterCollection<ItemAddress>& preclu,
+		    //IChunk* chunkptr, ConeJetInfoChunk* infochunkptr,
+		    const float Item_ET_Threshold);
+
+  // this will hold the final jets + contents
+  std::vector<ProtoJet<Item> > ilcv;
+
+private:
+
+  float _CONE_RADIUS;
+  float _MIN_JET_ET;
+  float _ET_MIN_RATIO;
+  float _FAR_RATIO;
+  float _SPLIT_RATIO;
+  float _DUPLICATE_DR;
+  float _DUPLICATE_DPT;
+  float _SEARCH_CONE;
+
+  bool _KILL_DUPLICATE;
+
+  float _PT_MIN_LEADING_PROTOJET;
+  float _PT_MIN_SECOND_PROTOJET;
+  int  _MERGE_MAX; 
+  float _PT_MIN_noMERGE_MAX;
+
+  // private class 
+  // This is a ProtoJet with additional methods dist(), midpoint() and 
+  // is_stable()
+  class TemporaryJet : public ProtoJet<Item> 
+  {
+    
+  public :
+    
+    TemporaryJet(float seedET) : ProtoJet<Item>(seedET) {;}
+
+    TemporaryJet(float seedET,float y_in,float phi_in) : 
+      ProtoJet<Item>(seedET,y_in,phi_in) {;}
+    
+    ~TemporaryJet() {;}
+    
+    float dist(TemporaryJet& jet) const 
+    {
+      return RDelta(this->_y,this->_phi,jet.y(),jet.phi()); 
+    }
+    
+    void midpoint(const TemporaryJet& jet,float & y_out, float & phi_out) const 
+    {
+      // Midpoint should probably be computed w/4-vectors but don't 
+      // have that info.  Preserving Pt-weighted calculation - JPK
+      float pTsum = this->_pT + jet.pT();
+      y_out = (this->_y*this->_pT + jet.y()*jet.pT())/pTsum;
+
+      phi_out = (this->_phi*this->_pT + jet.phi()*jet.pT())/pTsum;
+      // careful with phi-wrap area: convert from [0,2pi] to [-pi,pi]
+      //ls: original D0 code, as of 23/Mar/2007
+      //if ( abs(phi-this->_phi)>2.0 ) { // assumes cones R=1.14 or smaller, merge within 2R only  
+      //ls: abs bug fixed 26/Mar/2007 
+      if ( fabs(phi_out-this->_phi)>2.0 ) { // assumes cones R=1.14 or smaller, merge within 2R only  
+        phi_out = fmod( this->_phi+PI, TWOPI);
+	if (phi_out < 0.0) phi_out += TWOPI;
+	phi_out -= PI;
+
+	float temp=fmod( jet.phi()+PI, TWOPI);
+	if (temp < 0.0) temp += TWOPI;
+	temp -= PI;
+
+	phi_out = (phi_out*this->_pT + temp*jet.pT()) /pTsum;
+      }
+
+      if ( phi_out < 0. ) phi_out += TWOPI;
+    }
+    
+
+////////////////////////////////////////
+#ifdef ILCA_USE_MMAP
+    bool is_stable(const std::multimap<float,const Item*>& items, 
+		   float radius, float min_ET, int max_iterations=50) 
+#else
+    bool is_stable(const std::list<const Item*>& itemlist, float radius, 
+		 float min_ET, int max_iterations=50) 
+#endif
+    // Note: max_iterations = 0 will just recompute the jet using the specified cone
+    {
+      float radius2 = radius*radius;
+      float Rcut= 1.E-06;
+      
+      
+      // ?? if(_Increase_Delta_R) Rcut= 1.E-04;
+      bool stable= true;
+      int trial= 0;
+      float Yst;
+      float PHIst;
+      do {  
+	trial++;
+	//std::cout << "   trial " << trial << " " << _y << " " << _phi << std::endl; 
+	Yst  = this->_y;
+	PHIst= this->_phi;    
+	//cout << "is_stable beginning do loop: this->_pT=" << this->_pT << " this->_y=" << this->_y << " this->_phi=" << this->_phi << endl;
+	this->erase();
+	
+	this->setJet(Yst,PHIst,0.0);
+	
+	
+#ifdef ILCA_USE_ORDERED_LIST      
+	std::list<const Item*>::const_iterator lower = 
+	  lower_bound(itemlist.begin(),itemlist.end(),Yst-radius,
+		      rapidity_order<Item>());
+	std::list<const Item*>::const_iterator upper = 
+	  upper_bound(itemlist.begin(),itemlist.end(),Yst+radius,
+		      rapidity_order<Item>());
+	for(std::list<const Item*>::const_iterator tk = lower; tk != upper; ++tk)      {
+	  //std::cout << " is_stable: item y=" << (*tk)->y() << " phi=" << (*tk)->phi() << " RD2=" << RD2((*tk)->y(),(*tk)->phi(),Yst,PHIst) << " " << Yst-radius << " " << Yst+radius << endl;
+	  if(RD2((*tk)->y(),(*tk)->phi(),Yst,PHIst) <= radius2) 
+	    {
+	      this->addItem(*tk);
+	    }
+	}       
+#else
+#ifdef ILCA_USE_MMAP      
+	// need to loop only on the subset with   Yst-R < y < Yst+R
+	for ( std::multimap<float,const Item*>::const_iterator 
+		tk = items.lower_bound(Yst-radius);
+	      tk != items.upper_bound(Yst+radius); ++tk )
+	  {
+	    //std::cout << "     item " << (*tk)->y() << " " << (*tk)->phi() << " " << RD2((*tk)->y(),(*tk)->phi(),Yst,PHIst) << " " << Yst-radius << " " << Yst+radius << endl;
+	    if(RD2(((*tk).second)->y(),((*tk).second)->phi(),Yst,PHIst) <= radius2) 
+	      {
+		this->addItem((*tk).second);
+	      }
+	  }
+	
+#else   
+
+	//cout << " is_stable: itemlist.size()=" << itemlist.size() << endl;
+	for(typename std::list<const Item*>::const_iterator tk = itemlist.begin(); tk != itemlist.end(); ++tk) 
+	  {
+	    //std::cout << "    is_stable: item (*tk)->y()=" << (*tk)->y() << " (*tk)->phi=" << (*tk)->phi() << " RD2=" << RD2((*tk)->y(),(*tk)->phi(),Yst,PHIst) << " Yst-rad=" << Yst-radius << " Yst+rad=" << Yst+radius << endl;
+	    if(RD2((*tk)->y(),(*tk)->phi(),Yst,PHIst) <= radius2) 
+	       {
+		 //cout << "add item to *tk" << endl;
+		this->addItem(*tk);
+	      }
+	  }
+#endif
+#endif      
+      
+	//std::cout << "is_stable, before update: jet this->_y=" << this->_y << " _phi=" << this->_phi << " _pT=" << this->_pT << " min_ET=" << min_ET << std::endl; 
+	this->updateJet();
+	//std::cout << "is_stable, after update: jet this->_y=" << this->_y << " _phi=" << this->_phi << " _pT=" << this->_pT << " min_ET=" << min_ET << std::endl; 
+	
+	if(this->_pT < min_ET ) 
+	  {
+	    stable= false;
+	    break;
+	  } 
+	//cout << "is_stable end while loop: this->_pT=" << this->_pT << " this->_y=" << this->_y << " this->_phi=" << this->_phi << endl;
+      } while(RD2(this->_y,this->_phi,Yst,PHIst) >= Rcut && trial <= max_iterations);
+      //std::cout << "   trial stable " << trial << " " << stable << std::endl; 
+      return stable;
+    }
+    
+  private :
+    
+  };
+};
+///////////////////////////////////////////////////////////////////////////////
+//template <class Item,class ItemAddress,class IChunk>
+//void ILConeAlgorithm <Item,ItemAddress,IChunk>::
+template <class Item>
+void ILConeAlgorithm <Item>::
+//makeClusters(const EnergyClusterReco* r,
+makeClusters(
+             std::list<Item> &jets,
+	     std::list<const Item*>& ilist, 
+	     //float Zvertex, 
+	     ////std::list<const Item*>& ilist) 
+	     //const EnergyClusterCollection<ItemAddress>& preclu,
+	     //IChunk* chunkptr, ConeJetInfoChunk* infochunkptr,
+	     const float Item_ET_Threshold) 
+{
+  // remove items below threshold
+  for ( typename std::list<const Item*>::iterator it = ilist.begin(); 
+
+        it != ilist.end(); )
+  {
+    if ( (*it)->pT() < Item_ET_Threshold ) 
+    {
+      it = ilist.erase(it);
+    }
+      else ++it;
+  }
+
+  // create an energy cluster collection for jets 
+  //EnergyClusterCollection<ItemAddress>* ptrcol;
+  //Item* ptrcol;
+  //r->createClusterCollection(chunkptr,ptrcol);
+  ////std::vector<const EnergyCluster<ItemAddress>*> ecv;
+  std::vector<const Item*> ecv;
+  for ( typename std::list<const Item*>::iterator it = ilist.begin(); 
+        it != ilist.end(); it++) {
+    ecv.push_back(*it);
+  }
+
+
+  //preclu.getClusters(ecv);
+  //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% need to fill here vector ecv
+
+  //std::cout << " number of seed clusters: " << ecv.size() << std::endl;
+
+  // skip precluster close to jets
+  float far_def = _FAR_RATIO*_CONE_RADIUS * _FAR_RATIO*_CONE_RADIUS;
+
+  // skip if jet Et is below some value
+  float ratio= _MIN_JET_ET*_ET_MIN_RATIO;
+
+
+#ifdef ILCA_USE_ORDERED_LIST
+  // sort the list in rapidity order
+  ilist.sort(rapidity_order<Item>());
+#else
+#ifdef ILCA_USE_MMAP  
+  // create a y ordered list of items 
+  std::multimap<float,const Item*> items;
+  std::list<const Item*>::const_iterator it;
+  for(it = ilist.begin(); it != ilist.end(); ++it) 
+  {
+    pair<float,const Item*> p((*it)->y(),*it);
+    items.insert(p);
+  }
+#endif
+#endif
+
+  std::vector<ProtoJet<Item> > mcoll;
+  std::vector<TemporaryJet> scoll; 
+
+
+  // find stable jets around seeds 
+  //typename std::vector<const EnergyCluster<ItemAddress>* >::iterator jclu;
+  typename std::vector<const Item*>::iterator jclu;
+  for(jclu = ecv.begin(); jclu != ecv.end(); ++jclu) 
+  {
+    //const EnergyCluster<ItemAddress>* ptr= *jclu;
+    const Item* ptr= *jclu;
+    float p[4];
+    ptr->p4vec(p);
+    float Yst  = P2y(p);
+    float PHIst= P2phi(p);
+
+    // don't keep preclusters close to jet
+    bool is_far= true;
+    // ?? if(_Kill_Far_Clusters) {
+    for(unsigned int i = 0; i < scoll.size(); ++i) 
+    {
+      float y  = scoll[i].y();
+      float phi= scoll[i].phi();
+      if(RD2(Yst,PHIst,y,phi) < far_def) 
+      {
+	is_far= false;
+	break;
+      }
+    }
+    // ?? }
+
+    if(is_far) 
+    {
+      TemporaryJet jet(ptr->pT(),Yst,PHIst);
+      //cout << "temporary jet: pt=" << ptr->pT() << " y=" << Yst << " phi=" << PHIst << endl;
+
+      // Search cones are smaller, so contain less jet Et 
+      // Don't throw out too many little jets during search phase!
+      // Strategy: check Et first with full cone, then search with low-GeV min_et thresh
+#ifdef ILCA_USE_MMAP
+      if(jet.is_stable(items,_CONE_RADIUS,ratio,0) && jet.is_stable(items,_SEARCH_CONE,3.0)) 
+#else
+      if(jet.is_stable(ilist,_CONE_RADIUS,ratio,0) && jet.is_stable(ilist,_SEARCH_CONE,3.0)) 
+#endif
+      {
+
+	//cout << "temporary jet is stable" << endl;
+
+// jpk  Resize the found jets 
+#ifdef ILCA_USE_MMAP
+        jet.is_stable(items,_CONE_RADIUS,ratio,0) ;
+#else
+        jet.is_stable(ilist,_CONE_RADIUS,ratio,0) ;
+#endif
+	//cout << "found jet has been resized if any" << endl;
+
+	if ( _KILL_DUPLICATE ) 
+	{
+	  // check if we are not finding the same jet again
+	  float distmax = 999.; int imax = -1;
+	  for(unsigned int i = 0; i < scoll.size(); ++i) 
+	  {
+	    float dist = jet.dist(scoll[i]);
+	    if ( dist < distmax )
+	    {
+	      distmax = dist;
+	      imax = i;
+	    }
+	  }
+	  if ( distmax > _DUPLICATE_DR ||
+	       fabs((jet.pT()-scoll[imax].pT())/scoll[imax].pT())>_DUPLICATE_DPT )
+	  {
+	    scoll.push_back(jet);
+	    mcoll.push_back(jet);
+	    //std::cout << " stable cone " << jet.y() << " " << jet.phi() << " " << jet.pT() << std::endl;
+	  }
+	  /*
+	    else
+	    {
+	    std::cout << " jet too close to a found jet " << distmax << " " << 
+	    fabs((jet.pT()-scoll[imax].pT())/scoll[imax].pT()) << std::endl;
+	    }
+	  */
+	}
+	else
+	{
+	  scoll.push_back(jet);
+	  mcoll.push_back(jet);
+	  //std::cout << " stable cone " << jet.y() << " " << jet.phi() << " " << jet.pT() << std::endl;
+	}
+
+      }
+    }
+  }
+
+  // find stable jets around midpoints
+  for(unsigned int i = 0; i < scoll.size(); ++i) 
+  {
+    for(unsigned int k = i+1; k < scoll.size(); ++k) 
+    {
+      float djet= scoll[i].dist(scoll[k]);
+      if(djet > _CONE_RADIUS && djet < 2.*_CONE_RADIUS) 
+      {
+	float y_mid,phi_mid;
+	scoll[i].midpoint(scoll[k],y_mid,phi_mid);
+	TemporaryJet jet(-999999.,y_mid,phi_mid);
+	//std::cout << " midpoint: " << scoll[i].pT() << " " << scoll[i].info().seedET() << " " << scoll[k].pT() << " " << scoll[k].info().seedET() << " " << y_mid << " " << phi_mid << std::endl; 
+
+// midpoint jets are full size
+#ifdef ILCA_USE_MMAP
+      if(jet.is_stable(items,_CONE_RADIUS,ratio)) 
+#else
+      if(jet.is_stable(ilist,_CONE_RADIUS,ratio)) 
+#endif
+	{
+	  mcoll.push_back(jet);
+	  //std::cout << " stable midpoint cone " << jet.y() << " " << jet.phi() << " " << jet.pT() << std::endl;
+	}
+      }
+    }
+  }
+
+
+  // do a pT ordered splitting/merging
+  ConeSplitMerge<Item> pjets(mcoll);
+  ilcv.clear();
+  pjets.split_merge(ilcv,_SPLIT_RATIO, _PT_MIN_LEADING_PROTOJET, _PT_MIN_SECOND_PROTOJET, _MERGE_MAX, _PT_MIN_noMERGE_MAX);
+
+
+  for(unsigned int i = 0; i < ilcv.size(); ++i) 
+  {
+    if ( ilcv[i].pT() > _MIN_JET_ET )
+    {
+      //EnergyCluster<ItemAddress>* ptrclu;
+      Item ptrclu;
+      //r->createCluster(ptrcol,ptrclu);
+      
+      std::list<const Item*> tlist=ilcv[i].LItems();
+      typename std::list<const Item*>::iterator tk;
+      for(tk = tlist.begin(); tk != tlist.end(); ++tk) 
+      {
+	//ItemAddress addr= (*tk)->address();
+	float pk[4];
+	(*tk)->p4vec(pk);
+        //std::cout << (*tk)->index <<" " <<  (*tk) << std::endl;
+	//float emE= (*tk)->emE();
+	//r->addClusterItem(ptrclu,addr,pk,emE);
+	//ptrclu->Add(*tk);
+	ptrclu.Add(**tk);
+      }
+      // print out
+      //ptrclu->print(cout);
+      
+      //infochunkptr->addInfo(ilcv[i].info());
+      jets.push_back(ptrclu);
+    }
+  }
+}
+
+}  // namespace d0
+
+FASTJET_END_NAMESPACE
+
+#endif
+
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/ProtoJet.hpp
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/ProtoJet.hpp	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/ProtoJet.hpp	(revision 5)
@@ -0,0 +1,235 @@
+#ifndef  D0RunIIconeJets_PROTOJET
+#define  D0RunIIconeJets_PROTOJET
+// ---------------------------------------------------------------------------
+// ProtoJet.hpp
+//
+// Created: 28-JUL-2000 Francois Touze (+ Laurent Duflot)
+//
+// Purpose: Implements a proto-jet object that is used as input by the 
+//   Improved Legacy Cone Algorithm split/merge algo.
+//
+// Modified:
+//    9-Aug-2000  Laurent Duflot
+//     + save the initial stable cone ET before split/merge
+//    1-May-2007 Lars Sonnenschein
+//    extracted from D0 software framework and modified to remove subsequent dependencies 
+//
+//
+// This file is distributed with FastJet under the terms of the GNU
+// General Public License (v2). Permission to do so has been granted
+// by Lars Sonnenschein and the D0 collaboration (see COPYING for
+// details)
+//
+// History of changes in FastJet compared tothe original version of
+// ProtoJet.hpp
+//
+// 2011-12-13  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * added license information
+//
+// 2011-11-14  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * changed the name of a few parameters to avoid a gcc
+//          -Wshadow warning
+//
+// 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * put the code in the fastjet::d0 namespace
+//
+// 2007-12-14  Gavin Salam  <salam@lpthe.jussieu.fr>
+// 
+//        * replaced make_pair by std::make_pair
+//
+// ---------------------------------------------------------------------------
+ 
+//#include "kinem_util/AnglesUtil.hpp"
+//#include "energycluster/ConeJetInfo.hpp"
+#include "ConeJetInfo.hpp"
+#include <list>
+#include <cmath>
+
+#include "inline_maths.h" //ls
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace d0{
+
+using namespace inline_maths;
+using namespace D0RunIIconeJets_CONEJETINFO;
+
+
+inline float RD2(float y1,float phi1,float y2,float phi2) 
+{
+  float dphi= delta_phi(phi1,phi2);
+  return (y1-y2)*(y1-y2)+dphi*dphi; 
+}
+
+inline float RDelta(float y1,float phi1,float y2,float phi2) 
+{
+  float dphi= delta_phi(phi1,phi2);
+  return sqrt((y1-y2)*(y1-y2)+dphi*dphi); 
+}
+
+inline float P2y(float* p4vec) {
+  return y(p4vec[3],p4vec[2]);
+}
+
+inline float P2phi(float* p4vec) {
+  return phi(p4vec[0],p4vec[1]);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+template <class Item>
+class ProtoJet {
+
+public :
+
+  ProtoJet(float seedET);
+  ProtoJet(float seedET,float y,float phi);
+  ProtoJet(const ProtoJet<Item>& pj);
+  ~ProtoJet() {;}
+
+  void addItem(const Item* tw); 
+  void setJet(float y,float phi,float pT); 
+  void updateJet();
+  void erase();
+
+  float y() const; 
+  float phi() const;
+  float pT() const;
+  const ConeJetInfo & info() const;
+  const std::list<const Item*>& LItems() const;
+
+  void print(std::ostream &os) const;
+
+  // actions to be taken when the jet is a stable cone
+  void NowStable();
+  // declare the jet to have been splitted
+  void splitted(){_info.splitted();};
+  // declare the jet to have been merged
+  void merged(){_info.merged();};
+protected :
+
+  std::list<const Item*> _LItems;
+  float _y;
+  float _phi;
+  float _pT;
+  ConeJetInfo _info;
+
+};
+///////////////////////////////////////////////////////////////////////////////
+template<class Item>
+ProtoJet<Item>::ProtoJet(float seedET) : _LItems(), _info(seedET) {
+    _y  = 0.0;
+    _phi= 0.0;
+    _pT = 0.0;
+}
+
+template<class Item>
+ProtoJet<Item>::ProtoJet(float seedET,float y_in,float phi_in) :  _LItems(), _info(seedET) { 
+  _y  = y_in; 
+  _phi= phi_in;
+  _pT = 0.0;
+}
+
+template<class Item>
+ProtoJet<Item>::ProtoJet(const ProtoJet<Item>& pj): _y(pj._y), 
+						    _phi(pj._phi), _pT(pj._pT),
+                                                    _info(pj._info)
+{ 
+  typename std::list<const Item*>::const_iterator it;
+  for(it = pj._LItems.begin(); it != pj._LItems.end(); ++it) { 
+    _LItems.push_back(*it);
+  }
+}
+
+template<class Item>
+void ProtoJet<Item>::addItem(const Item* tw) {
+  _LItems.push_back(tw);
+}
+
+template<class Item>
+void ProtoJet<Item>::setJet(float y_in,float phi_in,float pT_in) {
+  _y  = y_in;
+  _phi= phi_in;
+  _pT = pT_in;
+}
+
+template<class Item>
+void ProtoJet<Item>::updateJet() { 
+  //float ETsum = 0.0;
+  //float ysum  = 0.0;
+  //float PHIsum= 0.0;
+  float p[4] = {0.,0.,0.,0.};
+  typename std::list<const Item*>::iterator it;
+  for(it = _LItems.begin(); it != _LItems.end(); ++it) 
+  {
+    float pk[4];
+    (*it)->p4vec(pk);
+    //cout << "updateJet: px=" << pk[0] << " py=" << pk[1] << " pz=" << pk[2] << " E=" << pk[3] << endl; 
+    for ( int i = 0; i < 4 ; ++i) p[i] += pk[i];
+  }
+  _y = P2y(p);
+  _phi = P2phi(p);
+  _pT = sqrt(p[0]*p[0] + p[1]*p[1]);
+  if ( p[3] < 0. ) _pT = - _pT;
+
+}
+
+template<class Item>
+void ProtoJet<Item>::erase() {
+  _LItems.erase(_LItems.begin(),_LItems.end());
+  _y  = 0.0;
+  _phi= 0.0;
+  _pT = 0.0; 
+  // _info is not modified in order to keep split/merge history
+}
+
+// actions to be taken when the jet is a stable cone
+template<class Item>
+void ProtoJet<Item>::NowStable() {
+  _info.initialET(_pT);
+}
+
+template<class Item>
+void ProtoJet<Item>::print(std::ostream& os) const {
+  os<<"y phi Et = ("<<_y<<", "<<_phi<<", "<<this->_Et<<")"<<std::endl;
+  os<< " members= " << std::endl;
+  typename std::list<const Item*>::const_iterator i;
+  for(i = _LItems.begin(); i != _LItems.end(); ++i)
+    (*i)->print(os);
+  os << std::endl;
+}
+
+template<class Item>
+inline float ProtoJet<Item>::y() const{
+  return _y;
+}
+
+template<class Item>
+inline float ProtoJet<Item>::phi() const{
+  return _phi;
+}
+
+template<class Item>
+inline float ProtoJet<Item>::pT() const{
+  return _pT;
+}
+template<class Item>
+inline const ConeJetInfo & ProtoJet<Item>::info() const{
+  return _info;
+}
+
+template<class Item>   
+inline const std::list<const Item*>& ProtoJet<Item>::LItems() const{
+  return _LItems;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+}  // namespace d0
+
+FASTJET_END_NAMESPACE
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/fastjet/D0RunIIConePlugin.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/fastjet/D0RunIIConePlugin.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/fastjet/D0RunIIConePlugin.hh	(revision 5)
@@ -0,0 +1,165 @@
+#ifndef __D0RUNIICONEPLUGIN_HH__
+#define __D0RUNIICONEPLUGIN_HH__
+
+//STARTHEADER
+// $Id: D0RunIIConePlugin.hh 2761 2011-11-24 13:54:05Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/JetDefinition.hh"
+
+// questionable whether this should be in fastjet namespace or not...
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+//
+/// @ingroup plugins
+/// \class D0RunIIConePlugin
+/// Implementation of the D0 Run II Cone (plugin for fastjet v2.1 upwards)
+/// 
+/// D0RunIIConePlugin is a plugin for fastjet (v2.1 upwards) that
+/// provides an interface to the D0 version of Run-II iterative cone
+/// algorithm with midpoint seeds (also known as the Iterative Legacy
+/// Cone Algorithm, ILCA).
+///
+/// The D0 code has been taken from Lars Sonnenschein's web-space
+/// http://www-d0.fnal.gov/~sonne/D0RunIIcone.tgz
+///
+/// The version of the D0 Run II code distributed
+/// here has been modified by the FastJet authors, so as to provide
+/// access to the contents of the jets (as is necessary for the
+/// plugin). This does not modify the results of the clustering.
+//
+//----------------------------------------------------------------------
+class D0RunIIConePlugin : public JetDefinition::Plugin {
+public:
+
+  //
+  /// A D0RunIIConePlugin constructor which sets the "free" parameters of the
+  /// algorithm:
+  ///
+  ///  - the cone_radius has the usual meaning
+  ///
+  ///  - the min_jet_Et causes cones to be discarded at if at any
+  ///    iteration they have pt < Et_min_ratio * min_jet_Et. Two
+  ///    values have been used by D0 for min_jet_Et: 8 GeV in earlier
+  ///    Run II publicatinos, 6 GeV in later publications
+  ///
+  ///  - split_ratio is equivalent to the overlap threshold during the split/merge step. 
+  ///    Default: 0.5.
+  ///
+  /// The remaining parameters of the algorithm are not to be modified if the algorithm
+  /// is to correspond to the one actually used by D0.
+  //
+  D0RunIIConePlugin (double cone_radius_in, 
+                     double min_jet_Et_in , 
+                     double split_ratio_in = _DEFAULT_split_ratio) :
+    _cone_radius            (cone_radius_in                  ),
+    _min_jet_Et             (min_jet_Et_in                   ),
+    _split_ratio            (split_ratio_in                  ),
+    _far_ratio              (_DEFAULT_far_ratio              ),
+    _Et_min_ratio           (_DEFAULT_Et_min_ratio           ),
+    _kill_duplicate         (_DEFAULT_kill_duplicate         ),
+    _duplicate_dR           (_DEFAULT_duplicate_dR           ),
+    _duplicate_dPT          (_DEFAULT_duplicate_dPT          ),
+    _search_factor          (_DEFAULT_search_factor          ),
+    _pT_min_leading_protojet(_DEFAULT_pT_min_leading_protojet),
+    _pT_min_second_protojet (_DEFAULT_pT_min_second_protojet ),
+    _merge_max              (_DEFAULT_merge_max              ),
+    _pT_min_nomerge         (_DEFAULT_pT_min_nomerge         )
+  {
+    // nothing to be done here!
+  }
+
+  // some functions to return info about parameters
+  inline double cone_radius            () const { return _cone_radius            ;} //= 0.5;
+  inline double min_jet_Et             () const { return _min_jet_Et             ;} //= 8.0;
+  inline double split_ratio            () const { return _split_ratio            ;} //= 0.5;
+  inline double far_ratio              () const { return _far_ratio              ;} // =0.5;
+  inline double Et_min_ratio           () const { return _Et_min_ratio           ;} // =0.5;
+  inline bool   kill_duplicate         () const { return _kill_duplicate         ;} // =true;
+  inline double duplicate_dR           () const { return _duplicate_dR           ;} // =0.005; 
+  inline double duplicate_dPT          () const { return _duplicate_dPT          ;} // =0.01; 
+  inline double search_factor          () const { return _search_factor          ;} // =1.0; 
+  inline double pT_min_leading_protojet() const { return _pT_min_leading_protojet;} // =0.; 
+  inline double pT_min_second_protojet () const { return _pT_min_second_protojet ;} // =0.;
+  inline int    merge_max              () const { return _merge_max              ;} // =10000; 
+  inline double pT_min_nomerge         () const { return _pT_min_nomerge         ;} // =0.;
+
+
+  /// access the split_ratio() also by the name overlap_threshold()
+  inline double overlap_threshold() const {return split_ratio();}
+
+  // the things that are required by base class
+  virtual std::string description () const;
+  virtual void run_clustering(ClusterSequence &) const;
+  /// the plugin mechanism's standard way of accessing the jet radius
+  virtual double R() const {return cone_radius();}
+  
+
+private:
+
+  double _cone_radius ;//= 0.5;
+  double _min_jet_Et  ;//= 8.0;
+  double _split_ratio ;//= 0.5; // overlap threshold
+        
+  //the parameters below have been found to be set to the values given below 
+  //in the original implementation, shouldn't be altered
+  double _far_ratio              ; // =0.5;
+  double _Et_min_ratio           ; // =0.5;
+  bool   _kill_duplicate         ; // =true;
+  double _duplicate_dR           ; // =0.005; 
+  double _duplicate_dPT          ; // =0.01; 
+  double _search_factor          ; // =1.0; 
+  double _pT_min_leading_protojet; // =0.; 
+  double _pT_min_second_protojet ; // =0.;
+  int    _merge_max              ; // =10000; 
+  double _pT_min_nomerge         ; // =0.;
+
+  // here are the variables for the default parameters of the D0 Run II Cone algorithm.
+  // They are set in the .cc file 
+  const static double _DEFAULT_split_ratio             ;// = 0.5  ; // overlap threshold
+  const static double _DEFAULT_far_ratio               ;// = 0.5  ;
+  const static double _DEFAULT_Et_min_ratio            ;// = 0.5  ;
+  const static bool   _DEFAULT_kill_duplicate          ;// = true ;
+  const static double _DEFAULT_duplicate_dR            ;// = 0.005; 
+  const static double _DEFAULT_duplicate_dPT           ;// = 0.01 ; 
+  const static double _DEFAULT_search_factor           ;// = 1.0  ; 
+  const static double _DEFAULT_pT_min_leading_protojet ;// = 0.   ; 
+  const static double _DEFAULT_pT_min_second_protojet  ;// = 0.   ;
+  const static int    _DEFAULT_merge_max               ;// = 10000; 
+  const static double _DEFAULT_pT_min_nomerge          ;// = 0.   ;
+
+  static bool _first_time;
+
+  /// print a banner for reference to the 3rd-party code
+  void _print_banner(std::ostream *ostr) const;
+};
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
+
+#endif // __D0RUNIICONEPLUGIN_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/inline_maths.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/inline_maths.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/D0RunIICone/inline_maths.h	(revision 5)
@@ -0,0 +1,84 @@
+#ifndef INLINE_MATHS
+#define INLINE_MATHS
+
+// This file is distributed with FastJet under the terms of the GNU
+// General Public License (v2). Permission to do so has been granted
+// by Lars Sonnenschein and the D0 collaboration (see COPYING for
+// details)
+//
+// History of changes in FastJet compared tothe original version of
+// inline_math.h
+//
+// 2011-12-13  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * added license information
+//
+// 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
+//
+//        * put the code in the fastjet::d0 namespace
+
+#include <cerrno>
+
+#include <fastjet/internal/base.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+namespace d0{
+
+namespace inline_maths {
+
+const double PI = fabs(acos(-1.));
+
+const double TWOPI = 2*PI;
+
+
+inline double sqr(double a) {
+  return a*a;
+}
+
+
+
+inline double min(double a, double b) {
+  return (a < b) ? a : b;
+}
+
+
+
+inline double delta_phi(double phi1, double phi2) {
+  return min( double(fabs(phi1-phi2)), double(2.*PI-fabs(phi1-phi2)) );
+}
+
+
+
+inline double phi(double px, double py) {
+  return atan2(py, px);
+}
+
+
+
+inline double y(double E, double pz) {
+  errno=0;
+  double y;
+  //cout << "inline_maths: ";
+  if (fabs(E-pz) == 0.) {
+    //    cout << "Error in header mathe.h: division by 0 in function eta!" <<  " p=" << p << " pz=" << pz << endl;
+    //  exit(721);
+    errno=721;
+    y = 99999.;
+  }
+  else {
+    y = 0.5*log((E+pz)/(E-pz));
+  }
+  //cout << "y: E=" << E << " pz=" << pz << " y=" << y << endl;
+  return y;
+}
+
+
+} //end usename inline_maths
+
+
+}  // namespace d0
+
+FASTJET_END_NAMESPACE
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/EECambridge/EECambridgePlugin.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/EECambridge/EECambridgePlugin.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/EECambridge/EECambridgePlugin.cc	(revision 5)
@@ -0,0 +1,117 @@
+//STARTHEADER
+// $Id: EECambridgePlugin.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2007-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+// fastjet stuff
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/EECambridgePlugin.hh"
+#include "fastjet/NNH.hh"
+
+// other stuff
+#include <sstream>
+#include <limits>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+
+//----------------------------------------------------------------------
+/// class to help run an e+e- Cambridge algorithm
+class EECamBriefJet {
+public:
+  void init(const PseudoJet & jet) {
+    double norm = 1.0/sqrt(jet.modp2());
+    nx = jet.px() * norm;
+    ny = jet.py() * norm;
+    nz = jet.pz() * norm;
+  }
+
+  double distance(const EECamBriefJet * jet) const {
+    double dij = 1 - nx*jet->nx
+                   - ny*jet->ny
+                   - nz*jet->nz;
+    return dij;
+  }
+
+  double beam_distance() const {
+    return numeric_limits<double>::max();
+  }
+
+private:
+  double nx, ny, nz;
+};
+
+
+string EECambridgePlugin::description () const {
+  ostringstream desc;
+  desc << "EECambridge plugin with ycut = " << ycut() ;
+  return desc.str();
+}
+
+void EECambridgePlugin::run_clustering(ClusterSequence & cs) const {
+  int njets = cs.jets().size();
+  NNH<EECamBriefJet> nnh(cs.jets());
+
+  double Q2 = cs.Q2(); 
+
+  while (njets > 0) {
+    int i, j, k;
+    // here we get a minimum based on the purely angular variable from the NNH class
+    // (called dij there, but vij in the Cambridge article (which uses dij for 
+    // a kt distance...)
+    double vij = nnh.dij_min(i, j); // i,j are return values...
+
+    // next we work out the dij (ee kt distance), and based on its
+    // value decide whether we have soft-freezing (represented here by
+    // a "Beam" clustering) or not
+    double dij;
+    if (j >= 0) {
+      double scale = min(cs.jets()[i].E(), cs.jets()[j].E());
+      dij = 2 * vij * scale * scale;
+      if (dij > Q2 * ycut()) {
+	// we'll call the softer partner a "beam" jet
+	if (cs.jets()[i].E() > cs.jets()[j].E()) std::swap(i,j);
+	j = -1;
+      }
+    } else {
+      // for the last particle left, just use yij = 1
+      dij = Q2;
+    }
+    
+    if (j >= 0) {
+      cs.plugin_record_ij_recombination(i, j, dij, k);
+      nnh.merge_jets(i, j, cs.jets()[k], k);
+    } else {
+      cs.plugin_record_iB_recombination(i, dij);
+      nnh.remove_jet(i);
+    }
+    njets--;
+  }
+    
+}
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/EECambridge/fastjet/EECambridgePlugin.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/EECambridge/fastjet/EECambridgePlugin.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/EECambridge/fastjet/EECambridgePlugin.hh	(revision 5)
@@ -0,0 +1,91 @@
+#ifndef __EECAMBRIDGEPLUGIN_HH__
+#define __EECAMBRIDGEPLUGIN_HH__
+
+//STARTHEADER
+// $Id: EECambridgePlugin.hh 2692 2011-11-14 16:27:44Z soyez $
+//
+// Copyright (c) 2009, Matteo Cacciari, Gavin Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#include "fastjet/JetDefinition.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+// forward declaration to reduce includes
+class ClusterSequence;
+
+//----------------------------------------------------------------------
+//
+/// @ingroup plugins
+/// \class EECambridgePlugin
+/// Implementation of the e+e- Cambridge algorithm (plugin for fastjet v2.4 upwards)
+///
+/// EECambridgePlugin is a plugin for fastjet (v2.4 upwards)
+/// It implements the Cambridge algorithm, as defined in 
+/// 
+/// Better jet clustering algorithms
+/// Yuri Dokshitzer, Garth Leder, Stefano Moretti,  Bryan Webber 
+/// JHEP 9708 (1997) 001
+/// http://www-spires.slac.stanford.edu/spires/find/hep/www?rawcmd=FIND+j+JHEPA%2C9708%2C001
+///
+/// On construction one must supply a ycut value.
+///
+/// To get the jets at the end call ClusterSequence::inclusive_jets();
+class EECambridgePlugin : public JetDefinition::Plugin {
+public:
+  /// Main constructor for the EECambridge Plugin class.  
+  /// It takes the dimensionless parameter ycut (the Q value for normalisation
+  /// of the kt-distances is taken from the sum of all particle energies).
+  EECambridgePlugin (double ycut_in) : _ycut(ycut_in) {}
+
+  /// copy constructor
+  EECambridgePlugin (const EECambridgePlugin & plugin) {
+    *this = plugin;
+  }
+
+  // the things that are required by base class
+  virtual std::string description () const;
+  virtual void run_clustering(ClusterSequence &) const;
+
+  double ycut() const {return _ycut;}
+
+  /// the plugin mechanism's standard way of accessing the jet radius.
+  /// This must be set to return something sensible, even if R
+  /// does not make sense for this algorithm!
+  virtual double R() const {return 1.0;}
+
+  /// avoid the warning whenever the user requests "exclusive" jets
+  /// from the cluster sequence
+  virtual bool exclusive_sequence_meaningful() const {return true;}
+
+private:
+  double _ycut;
+};
+
+FASTJET_END_NAMESPACE        // defined in fastjet/internal/base.hh
+
+#endif // __EECAMBRIDGEPLUGIN_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/GridJet/GridJetPlugin.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/GridJet/GridJetPlugin.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/GridJet/GridJetPlugin.cc	(revision 5)
@@ -0,0 +1,184 @@
+//STARTHEADER
+// $Id: GridJetPlugin.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2011, Matteo Cacciari, Gavin Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+// fastjet stuff
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/GridJetPlugin.hh"
+
+// other stuff
+#include <vector>
+#include <sstream>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+
+//----------------------------------------------------------------------
+GridJetPlugin::GridJetPlugin (double ymax,
+                              double requested_grid_spacing, 
+                              const JetDefinition & post_jet_def) :
+  _ymin(-ymax), _ymax(ymax), 
+  _requested_grid_spacing(requested_grid_spacing) ,
+  _post_jet_def(post_jet_def)
+{
+  setup_grid();
+}
+
+void GridJetPlugin::setup_grid() {
+  // since we've exchanged the arguments of the constructor,
+  // there's a danger of calls with exchanged ymax,spacing arguments -- 
+  // the following check should catch most such situations.
+  assert(_ymax>0 && _ymax - _ymin >= _requested_grid_spacing);
+
+  double ny_double = (_ymax-_ymin) / _requested_grid_spacing;
+  _ny = int(ny_double+0.49999);
+  _dy = (_ymax-_ymin) / _ny;
+  
+  _nphi = int (twopi / _requested_grid_spacing + 0.5);
+  _dphi = twopi / _nphi;
+
+  // some sanity checking (could throw a fastjet::Error)
+  assert(_ny >= 1 && _nphi >= 1);
+
+  _ntotal = _nphi * _ny;
+}
+
+
+//----------------------------------------------------------------------
+string GridJetPlugin::description () const {
+  ostringstream desc;
+  desc << "GridJetPlugin plugin with ymax = " << _ymax << ", dy = " << _dy << ", dphi = " << _dphi << " (requested grid spacing was " << _requested_grid_spacing << ")";
+  if (_post_jet_def.jet_algorithm() != undefined_jet_algorithm) {
+    desc << ", followed by " << _post_jet_def.description();
+  }
+  return desc.str();
+}
+
+
+//----------------------------------------------------------------------
+double GridJetPlugin::R() const {return sqrt(_dy*_dphi/pi);}
+
+
+//----------------------------------------------------------------------
+int GridJetPlugin::igrid(const PseudoJet & p) const {
+  // directly taking int does not work for values between -1 and 0
+  // so use floor instead
+  // double iy_double = (p.rap() - _ymin) / _dy;
+  // if (iy_double < 0.0) return -1;
+  // int iy = int(iy_double);
+  // if (iy >= _ny) return -1;
+
+  // writing it as below gives a huge speed gain (factor two!). Even
+  // though answers are identical and the routine here is not the
+  // speed-critical step. It's not at all clear why.
+  int iy = int(floor( (p.rap() - _ymin) / _dy ));
+  if (iy < 0 || iy >= _ny) return -1;
+
+  int iphi = int( p.phi()/_dphi );
+  assert(iphi >= 0 && iphi <= _nphi);
+  if (iphi == _nphi) iphi = 0; // just in case of rounding errors
+
+  int igrid_res = iy*_nphi + iphi;
+  assert (igrid_res >= 0 && igrid_res < _ny*_nphi);
+  return igrid_res;
+}
+
+
+//----------------------------------------------------------------------
+void GridJetPlugin::run_clustering(ClusterSequence & cs) const {
+  
+  // we will create a grid; 
+  //  * -1 will indicate there is no jet here currently
+  //  * a number >= 0 will mean that particle indicated by the index
+  //    is currently the jet on the grid
+  vector<int> grid(_ntotal, -1);
+ 
+  int nparticles = cs.jets().size();
+  double dij_or_diB = 1.0;
+
+  int ngrid_active = 0;
+
+  // combine particles with whatever is in the grid
+  for (int i = 0; i < nparticles; i++) {
+    int igrd = igrid(cs.jets()[i]);
+    //cout << i << " " << cs.jets()[i].rap() << " " << cs.jets()[i].phi() 
+    // 	 << " " << igrd << " " << grid.size() << " " << _ntotal << endl;
+    if (igrd < 0) continue;
+    assert(igrd <= _ntotal);
+    if (grid[igrd] == -1) {
+      grid[igrd] = i; // jet index of initial particle i is i
+      ngrid_active++;
+    } else {
+      int k;
+      cs.plugin_record_ij_recombination(grid[igrd], i, dij_or_diB, k);
+      grid[igrd] = k; // grid takes jet index of new particle
+      //cout << "  res: " << cs.jets()[k].rap() << " " << cs.jets()[k].phi() << endl;
+    }
+  }
+
+  if (_post_jet_def.jet_algorithm() == undefined_jet_algorithm) {
+    // make the final jets via iB recombinations
+    for (unsigned igrd = 0; igrd < grid.size(); igrd++) {
+      if (grid[igrd] != -1) cs.plugin_record_iB_recombination(grid[igrd], 
+							      dij_or_diB);
+    }
+  } else {
+    // otherwise post-cluster the grid elements with a normal jet algorithm
+    vector<PseudoJet> inputs;
+    vector<int>       cs_indices;
+    inputs.reserve(ngrid_active);
+    cs_indices.reserve(2*ngrid_active);
+    for (unsigned igrd = 0; igrd < grid.size(); igrd++) {
+      if (grid[igrd] != -1) {
+	inputs.push_back(cs.jets()[grid[igrd]]);
+	cs_indices.push_back(grid[igrd]);
+      }
+    }
+    ClusterSequence post_cs(inputs, _post_jet_def);
+    const vector<ClusterSequence::history_element> & post_history = post_cs.history();
+    const vector<PseudoJet>                        & post_jets = post_cs.jets();
+    for (unsigned ihist = ngrid_active; ihist < post_history.size(); ihist++) {
+      const ClusterSequence::history_element & hist = post_history[ihist];
+      int post_ij1 = post_history[hist.parent1].jetp_index;
+      int ij1 = cs_indices[post_ij1];
+      if (hist.parent2 >= 0) {
+	int post_ij2 = post_history[hist.parent2].jetp_index;
+	int ij2 = cs_indices[post_ij2];
+	int k;
+	cs.plugin_record_ij_recombination(ij1, ij2, hist.dij, post_jets[hist.jetp_index], k); 
+	assert(int(cs_indices.size()) == hist.jetp_index);
+	cs_indices.push_back(k);
+      } else {
+	cs.plugin_record_iB_recombination(ij1, hist.dij);
+      }
+    }
+    
+  }
+}
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/GridJet/fastjet/GridJetPlugin.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/GridJet/fastjet/GridJetPlugin.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/GridJet/fastjet/GridJetPlugin.hh	(revision 5)
@@ -0,0 +1,93 @@
+#ifndef __GRIDJETPLUGIN_HH__
+#define __GRIDJETPLUGIN_HH__
+
+//STARTHEADER
+// $Id: GridJetPlugin.hh 2267 2011-06-20 15:10:23Z salam $
+//
+// Copyright (c) 2011, Matteo Cacciari, Gavin Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#include "fastjet/JetDefinition.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+// forward declaration to reduce includes
+class ClusterSequence;
+
+//----------------------------------------------------------------------
+//
+/// @ingroup plugins
+/// \class GridJetPlugin
+/// plugin for fastjet (v3.0 upwards) that clusters particles such
+/// that all particles in a given cell of a rectangular rapidity-phi
+/// grid end up in a common "jet".
+///
+/// This is not intended for use as a regular jet clustering algorithm, 
+/// but is rather provided for comparison purposes with the 
+/// GridMedianBackgroundEstimator (which is even faster).
+class GridJetPlugin : public JetDefinition::Plugin {
+public:
+  /// Main constructor for the GridJetPlugin Plugin class.
+  ///
+  /// \param ymax           The maximal rapidity extent of the grid
+  /// \param requested_grid_spacing The requested grid spacing
+  /// \param post_jet_def   if present, and not == JetDefinition()
+  ///                       (which has undefined_jet_algorithm), then
+  ///                       run the post_jet_def on the result of the grid
+  ///                       clustering.
+  GridJetPlugin (double ymax, double requested_grid_spacing,
+		 const JetDefinition & post_jet_def = JetDefinition());
+
+  /// copy constructor
+  GridJetPlugin (const GridJetPlugin & plugin) {
+    *this = plugin;
+  }
+
+  // the things that are required by base class
+  virtual std::string description () const;
+  virtual void run_clustering(ClusterSequence &) const;
+
+  /// This returns the sqrt(dphi*dy/pi) -- i.e. the radius that for a
+  /// circular jet would give the same area.
+  virtual double R() const;
+
+private:
+
+  void setup_grid();
+
+  int igrid(const PseudoJet & p) const;
+
+  double _ymin, _ymax, _dy, _dphi, _requested_grid_spacing;
+  int _ny, _nphi, _ntotal;
+
+  JetDefinition _post_jet_def;
+
+};
+
+FASTJET_END_NAMESPACE        // defined in fastjet/internal/base.hh
+
+#endif // __GRIDJETPLUGIN_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/Jade/JadePlugin.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/Jade/JadePlugin.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/Jade/JadePlugin.cc	(revision 5)
@@ -0,0 +1,110 @@
+//STARTHEADER
+// $Id: JadePlugin.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2007-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+// fastjet stuff
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/JadePlugin.hh"
+#include <iostream>
+//#include "fastjet/internal/ClusterSequence_N2.icc"
+#include "fastjet/NNH.hh"
+
+// other stuff
+#include <vector>
+#include <sstream>
+#include <limits>
+
+
+
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+
+//----------------------------------------------------------------------
+/// class to help run a JADE algorithm
+class JadeBriefJet {
+public:
+  void init(const PseudoJet & jet) {
+    double norm = 1.0/sqrt(jet.modp2());
+    nx = jet.px() * norm;
+    ny = jet.py() * norm;
+    nz = jet.pz() * norm;
+    rt2E = sqrt(2.0)*jet.E();
+  }
+
+  double distance(const JadeBriefJet * jet) const {
+    double dij = 1 - nx*jet->nx
+                   - ny*jet->ny
+                   - nz*jet->nz;
+    dij *= rt2E*jet->rt2E;
+    return dij;
+  }
+
+  double beam_distance() const {
+    return numeric_limits<double>::max();
+  }
+
+private:
+  double rt2E, nx, ny, nz;
+};
+
+
+//----------------------------------------------------------------------
+string JadePlugin::description () const {
+  ostringstream desc;
+  desc << "e+e- JADE algorithm plugin";
+  return desc.str();
+}
+
+//----------------------------------------------------------------------
+void JadePlugin::run_clustering(ClusterSequence & cs) const {
+  int njets = cs.jets().size();
+  NNH<JadeBriefJet> nnh(cs.jets());
+
+  // if testing against Hoeth's implementation, need to rescale the
+  // dij by Q^2.
+  //double Q2 = cs.Q2(); 
+
+  while (njets > 0) {
+    int i, j, k;
+    double dij = nnh.dij_min(i, j);
+
+    if (j >= 0) {
+      cs.plugin_record_ij_recombination(i, j, dij, k);
+      nnh.merge_jets(i, j, cs.jets()[k], k);
+    } else {
+      double diB = cs.jets()[i].E()*cs.jets()[i].E(); // get new diB
+      cs.plugin_record_iB_recombination(i, diB);
+      nnh.remove_jet(i);
+    }
+    njets--;
+  }
+}
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/Jade/fastjet/JadePlugin.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/Jade/fastjet/JadePlugin.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/Jade/fastjet/JadePlugin.hh	(revision 5)
@@ -0,0 +1,105 @@
+#ifndef __JADEPLUGIN_HH__
+#define __JADEPLUGIN_HH__
+
+//STARTHEADER
+// $Id: JadePlugin.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2009, Matteo Cacciari, Gavin Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/JetDefinition.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+// forward declaration to reduce includes
+class ClusterSequence;
+
+//----------------------------------------------------------------------
+//
+/// @ingroup plugins
+/// \class JadePlugin
+/// Implementation of the e+e- Jade algorithm (plugin for fastjet v2.4 upwards)
+///
+/// JadePlugin is a plugin for fastjet (v2.4 upwards)
+/// It implements the JADE algorithm, which is an e+e- sequential
+/// recombination algorithm with interparticle distance
+///
+///   dij = 2 E_i E_j (1 - cos theta_ij)
+///
+/// or equivalently
+///
+///   yij = dij/E_{vis}^2                
+///
+/// This corresponds to the distance measured used in 
+///
+///   "Experimental Investigation of the Energy Dependence of the Strong Coupling Strength."
+///   JADE Collaboration (S. Bethke et al.)
+///   Phys.Lett.B213:235,1988
+///
+/// The JADE article carries out particle recombinations in the
+/// E-scheme (4-vector recombination), which is the default procedure for this 
+/// plugin.
+///
+/// NOTE: other widely used schemes include E0, P, P0; however they also 
+///       involve modifications to the distance measure. Be sure of
+///       what you're doing before running a JADE type algorithm.
+///
+/// To access the jets with a given ycut value (clustering stops once
+/// all yij > ycut), use
+///
+///   vector<PseudoJet> jets = cluster_sequence.exclusive_jets_ycut(ycut);
+///
+/// and related routines.
+class JadePlugin : public JetDefinition::Plugin {
+public:
+  /// Main constructor for the Jade Plugin class.  
+  JadePlugin (){}
+
+  /// copy constructor
+  JadePlugin (const JadePlugin & plugin) {
+    *this = plugin;
+  }
+
+  // the things that are required by base class
+  virtual std::string description () const;
+  virtual void run_clustering(ClusterSequence &) const;
+
+  /// the plugin mechanism's standard way of accessing the jet radius.
+  /// This must be set to return something sensible, even if R
+  /// does not make sense for this algorithm!
+  virtual double R() const {return 1.0;}
+
+  /// avoid the warning whenever the user requests "exclusive" jets
+  /// from the cluster sequence
+  virtual bool exclusive_sequence_meaningful() const {return true;}
+
+private:
+
+};
+
+FASTJET_END_NAMESPACE        // defined in fastjet/internal/base.hh
+
+#endif // __JADEPLUGIN_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/NestedDefs/NestedDefsPlugin.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/NestedDefs/NestedDefsPlugin.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/NestedDefs/NestedDefsPlugin.cc	(revision 5)
@@ -0,0 +1,148 @@
+//STARTHEADER
+// $Id: NestedDefsPlugin.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2007-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+// TODO
+// ? Maybe one could provide additional recomb. dists as an "extra".;
+
+// fastjet stuff
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/NestedDefsPlugin.hh"
+
+// other stuff
+#include <vector>
+#include <sstream>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+
+string NestedDefsPlugin::description () const {
+  ostringstream desc;
+  
+  desc << "NestedDefs: successive application of " ;
+  unsigned int i=1;
+  for (list<JetDefinition>::const_iterator it=_defs.begin();it!=_defs.end();it++){
+    desc << "Definition " << i++ << " [" << it->description() << "] - ";
+  }
+
+  return desc.str();
+}
+
+void NestedDefsPlugin::run_clustering(ClusterSequence & clust_seq) const {
+  vector<PseudoJet> momenta;
+
+  // build the initial list of particles
+  momenta = clust_seq.jets();
+  unsigned int step_n = momenta.size();
+
+  // initialise the conversion table, which works as follows
+  // conversion_table[step_cs_jet_index] = main_cs_jet_index
+  vector<unsigned int> conversion_table(2*step_n);
+  vector<unsigned int> new_conversion_table;
+  for (unsigned int i=0;i<step_n;i++)
+    conversion_table[i]=i;
+
+  // Now the steps go as follows:
+  // for each definition in the list, 
+  //  - do the clustering,
+  //  - copy the history into the main one
+  //  - update the list of momenta and the index conversion table
+  list<JetDefinition>::const_iterator def_iterator = _defs.begin();
+  unsigned int def_index=0;
+  bool last_def=false;
+
+  while (def_iterator!=_defs.end()){
+    last_def = (def_index == (_defs.size()-1));
+
+    // do the clustering
+    ClusterSequence step_cs(momenta, *def_iterator);
+
+    // clear the momenta as we shall fill them again
+    momenta.clear();
+    new_conversion_table.clear();
+
+    // retrieve the history
+    const vector<ClusterSequence::history_element> & step_history = step_cs.history();
+
+    // copy the history
+    // note that we skip the initial steps which are just the 
+    // declaration of the particles.
+    vector<ClusterSequence::history_element>::const_iterator 
+      hist_iterator = step_history.begin();
+
+    for (unsigned int i=step_n;i!=0;i--)
+      hist_iterator++;
+
+    while (hist_iterator != step_history.end()){
+      // check if it is a recombination with the beam or a simple recombination
+      if (hist_iterator->parent2 == ClusterSequence::BeamJet){
+	// save this jet for future clustering
+	// unless we've reached the last def in which case, record the clustering
+	unsigned int step_jet_index = step_cs.history()[hist_iterator->parent1].jetp_index;
+	if (last_def){
+	  clust_seq.plugin_record_iB_recombination(conversion_table[step_jet_index], 
+						   hist_iterator->dij);
+	} else {
+	  momenta.push_back(step_cs.jets()[step_jet_index]);
+	  new_conversion_table.push_back(conversion_table[step_jet_index]);
+	}
+      } else {
+	// record combination
+	// note that we set the recombination distance to 0 except for the last alg
+	unsigned int step_jet1_index = step_cs.history()[hist_iterator->parent1].jetp_index;
+	unsigned int step_jet2_index = step_cs.history()[hist_iterator->parent2].jetp_index;
+	PseudoJet newjet = step_cs.jets()[hist_iterator->jetp_index];
+	int jet_k;
+	clust_seq.plugin_record_ij_recombination(conversion_table[step_jet1_index], 
+						 conversion_table[step_jet2_index],
+						 last_def ? hist_iterator->dij : 0.0,
+						 newjet, jet_k);
+
+	// save info in the conversion table for tracking purposes
+	conversion_table[hist_iterator->jetp_index]=jet_k;
+      }
+
+      // go to the next history element
+      hist_iterator++;
+    }
+
+    // finalise this step:
+    //  - update nr of particles
+    //  - update conversion table
+    step_n = momenta.size();
+    for (unsigned int i=0;i<step_n;i++)
+      conversion_table[i] = new_conversion_table[i];
+
+    // go to the next alg
+    def_index++;
+    def_iterator++;
+  }
+
+}
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/NestedDefs/fastjet/NestedDefsPlugin.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/NestedDefs/fastjet/NestedDefsPlugin.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/NestedDefs/fastjet/NestedDefsPlugin.hh	(revision 5)
@@ -0,0 +1,81 @@
+//STARTHEADER
+// $Id: NestedDefsPlugin.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2007-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __NESTEDALGSPLUGIN_HH__
+#define __NESTEDALGSPLUGIN_HH__
+
+#include "fastjet/JetDefinition.hh"
+#include <list>
+#include <memory>
+#include <cmath>
+
+// questionable whether this should be in fastjet namespace or not...
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+// another forward declaration to reduce includes
+class PseudoJet;
+
+//----------------------------------------------------------------------
+//
+/// @ingroup plugins
+/// \class NestedDefsPlugin
+/// Plugin to run multiple jet definitions successively (plugin for fastjet v2.4 upwards)
+///
+/// NestedAglsPlugin is a plugin for fastjet (v2.4 upwards) that, given
+/// a list of jet definitions, performs the clustering by feeding the 
+/// particles to the first algorithm and then, successively feeding the 
+/// output to the next algorithm in the list.
+//
+class NestedDefsPlugin : public JetDefinition::Plugin {
+public:
+  /// Main constructor for the NestedDefs Plugin class.  
+  ///
+  /// The argument is an initialised list of jet algorithms
+  NestedDefsPlugin (std::list<JetDefinition> &defs) :
+    _defs(defs){}
+
+  /// copy constructor
+  NestedDefsPlugin (const NestedDefsPlugin & plugin) {
+    *this = plugin;
+  }
+
+  // the things that are required by base class
+  virtual std::string description () const;
+  virtual void run_clustering(ClusterSequence &) const;
+  /// the plugin mechanism's standard way of accessing the jet radius
+  /// here we return the R of the last alg in the list
+  virtual double R() const {return _defs.rbegin()->R();}
+
+private:
+  std::list<JetDefinition> _defs;
+};
+
+FASTJET_END_NAMESPACE        // defined in fastjet/internal/base.hh
+
+#endif // __SISCONEPLUGIN_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/README
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/README	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/README	(revision 5)
@@ -0,0 +1,52 @@
+README for the plugins directory/
+---------------------------------
+
+This directory contains plugins that allow one to use certain cone
+jet-finders within the fastjet framework.
+
+For instructions on how to build and use plugins, see the main fastjet
+documentation. For documentation on specific plugins, see the plugin
+header files which contain extensive information.
+
+PxCone/
+        contains the pxcone code and the associated plugin; note that
+        since pxcone is in fortran, when linking with this plugin it
+        is necessary to link also with fortran libraries, and the
+        variable that provides the options for this F77LIB is defined
+        in ../Makefile. 
+        ****
+        The user should have defined beforehand the environment  
+        variable G77LIBDIR which points to the directory containing 
+        the libg2c.a library.
+        The command 
+              locate libg2c.a | head -1 | sed 's/\/[^\/]*$//'  or
+              dirname `locate libg2c.a | head -1`
+        might help in locating such a directory.
+        Alternatively, uncomment the G77LIBDIR line in ../Makefile
+        ****
+
+CDFCones/
+        contains CDF's code for their jetclu and midpoint jet finders
+        (actually in the CDFcode subdirectory), as well as the
+        associated plugins.
+
+
+usage_examples/
+        some programs to illustrate use of individual plugins as well
+        as several jet finders together. To run these programs, you
+        should first:
+
+        - build fastjet (see instructions in parent directory)
+        - build the plugins:
+            make
+          (if you just want a subset of plugins just go to the
+          relevant directory and build what you need).
+
+        - then build an example program and then run it
+            cd usage_examples
+            make
+            ./many_algs_example < data/single-event.dat
+        
+
+        
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/AUTHORS
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/AUTHORS	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/AUTHORS	(revision 5)
@@ -0,0 +1,16 @@
+This program was written by Gregory Soyez(1) and Gavin Salam(2)
+
+Address: (1) IPhT, CEA Saclay
+	     Orme des Merisiers, Bat 774
+	     F-91191 Gif-sur-Yvette Cedex
+	     France
+
+	 (2) PH-TH, CERN, CH-1211 Geneva 23, Switzerland;
+             Physics Department, Princeton University, Princeton NJ 08544, USA;
+             LPTHE, UPMC (Univ. Paris 6), 75252 Paris cedex 05, France.
+
+phone  : +33 69 08 40 11
+         +41 22 767 2462
+
+email  : soyez@fastjet.fr
+         salam@lpthe.jussieu.fr
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/COPYING
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/COPYING	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/COPYING	(revision 5)
@@ -0,0 +1,284 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/SISConePlugin.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/SISConePlugin.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/SISConePlugin.cc	(revision 5)
@@ -0,0 +1,217 @@
+
+// fastjet stuff
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/SISConePlugin.hh"
+
+// sisocne stuff
+#include "momentum.h"
+#include "siscone.h"
+
+// other stuff
+#include<sstream>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+using namespace siscone;
+
+/// shortcut for converting siscone Cmomentum into PseudoJet
+template<> PseudoJet::PseudoJet(const siscone::Cmomentum & four_vector) {
+  (*this) = PseudoJet(four_vector.px,four_vector.py,four_vector.pz,
+                      four_vector.E);
+}
+
+
+/////////////////////////////////////////////
+// static members declaration              //
+/////////////////////////////////////////////
+std::auto_ptr<SISConePlugin>           SISConePlugin::stored_plugin;
+std::auto_ptr<std::vector<PseudoJet> > SISConePlugin::stored_particles;
+std::auto_ptr<Csiscone>                SISConePlugin::stored_siscone;
+
+
+/////////////////////////////////////////////
+// now comes the implementation itself     //
+/////////////////////////////////////////////
+string SISConePlugin::description () const {
+  ostringstream desc;
+  
+  const string on = "on";
+  const string off = "off";
+
+  string sm_scale_string = "split-merge uses " + 
+    split_merge_scale_name(Esplit_merge_scale(split_merge_scale()));
+
+  desc << "SISCone jet algorithm with " ;
+  desc << "cone_radius = "       << cone_radius        () << ", ";
+  desc << "overlap_threshold = " << overlap_threshold  () << ", ";
+  desc << "n_pass_max = "        << n_pass_max         () << ", ";
+  desc << "protojet_ptmin = "    << protojet_ptmin()      << ", ";
+  desc <<  sm_scale_string                                << ", ";
+  desc << "caching turned "      << (caching() ? on : off);
+  desc << ", SM stop scale = "     << _split_merge_stopping_scale;
+
+  // add a note to the description if we use the pt-weighted splitting
+  if (_use_pt_weighted_splitting){
+    desc << ", using pt-weighted splitting";
+  }
+
+  if (_use_jet_def_recombiner){
+    desc << ", using jet-definition's own recombiner";
+  }
+
+  // create a fake siscone object so that we can find out more about it
+  Csiscone siscone;
+  if (siscone.merge_identical_protocones) {
+    desc << ", and (IR unsafe) merge_indentical_protocones=true" ;
+  }
+
+  desc << ", SISCone code v" << siscone_version();
+
+  return desc.str();
+}
+
+
+// overloading the base class implementation
+void SISConePlugin::run_clustering(ClusterSequence & clust_seq) const {
+
+  Csiscone::set_banner_stream(clust_seq.fastjet_banner_stream());
+
+  Csiscone   local_siscone;
+  Csiscone * siscone;
+  
+  unsigned n = clust_seq.jets().size();
+
+  bool new_siscone = true; // by default we'll be running it
+
+  if (caching()) {
+
+    // Establish if we have a cached run with the same R, npass and
+    // particles. If not then do any tidying up / reallocation that's
+    // necessary for the next round of caching, otherwise just set
+    // relevant pointers so that we can reuse and old run.
+    if (stored_siscone.get() != 0) {
+      new_siscone = !(stored_plugin->cone_radius()   == cone_radius()
+                      && stored_plugin->n_pass_max() == n_pass_max()  
+                      && stored_particles->size()    == n);
+      if (!new_siscone) {
+        for(unsigned i = 0; i < n; i++) {
+          // only check momentum because indices will be correctly dealt
+          // with anyway when extracting the clustering order.
+          new_siscone |= !have_same_momentum(clust_seq.jets()[i], 
+                                             (*stored_particles)[i]);
+        }
+      }
+    } 
+      
+    // allocate the new siscone, etc., if need be
+    if (new_siscone) {
+      stored_siscone  .reset( new Csiscone );
+      stored_particles.reset( new std::vector<PseudoJet>(clust_seq.jets()));
+      reset_stored_plugin();
+    }
+
+    siscone = stored_siscone.get();
+  } else {
+    siscone = &local_siscone;
+  }
+
+  // make sure stopping scale is set in siscone
+  siscone->SM_var2_hardest_cut_off = _split_merge_stopping_scale*_split_merge_stopping_scale;
+
+  // set the specific parameters
+  // when running with ghosts for passive areas, do not put the
+  // ghosts into the stable-cone search (not relevant)
+  siscone->stable_cone_soft_pt2_cutoff = ghost_separation_scale()
+                                         * ghost_separation_scale();
+  // set the type of splitting we want (default=std one, true->pt-weighted split)
+  siscone->set_pt_weighted_splitting(_use_pt_weighted_splitting);
+
+  if (new_siscone) {
+    // transfer fastjet initial particles into the siscone type
+    std::vector<Cmomentum> siscone_momenta(n);
+    for(unsigned i = 0; i < n; i++) {
+      const PseudoJet & p = clust_seq.jets()[i]; // shorthand
+      siscone_momenta[i] = Cmomentum(p.px(), p.py(), p.pz(), p.E());
+    }
+    
+    // run the jet finding
+    //cout << "plg sms: " << split_merge_scale() << endl;
+    siscone->compute_jets(siscone_momenta, cone_radius(), overlap_threshold(),
+			  n_pass_max(), protojet_or_ghost_ptmin(), 
+			  Esplit_merge_scale(split_merge_scale()));
+  } else {
+    // rerun the jet finding
+    // just run the overlap part of the jets.
+    //cout << "plg rcmp sms: " << split_merge_scale() << endl;
+    siscone->recompute_jets(overlap_threshold(), protojet_or_ghost_ptmin(), 
+			    Esplit_merge_scale(split_merge_scale()));
+  }
+
+  // extract the jets [in reverse order -- to get nice ordering in pt at end]
+  int njet = siscone->jets.size();
+
+  // allocate space for the extras object
+  SISConeExtras * extras = new SISConeExtras(n);
+
+  for (int ijet = njet-1; ijet >= 0; ijet--) {
+    const Cjet & jet = siscone->jets[ijet]; // shorthand
+    
+    // Successively merge the particles that make up the cone jet
+    // until we have all particles in it.  Start off with the zeroth
+    // particle.
+    int jet_k = jet.contents[0];
+    for (unsigned ipart = 1; ipart < jet.contents.size(); ipart++) {
+      // take the last result of the merge
+      int jet_i = jet_k;
+      // and the next element of the jet
+      int jet_j = jet.contents[ipart];
+      // and merge them (with a fake dij)
+      double dij = 0.0;
+
+      if (_use_jet_def_recombiner) {
+	clust_seq.plugin_record_ij_recombination(jet_i, jet_j, dij, jet_k);
+      } else {
+	// create the new jet by hand so that we can adjust its user index
+	PseudoJet newjet = clust_seq.jets()[jet_i] + clust_seq.jets()[jet_j];
+	// set the user index to be the pass in which the jet was discovered
+       // *** The following line was commented for 3.0.1 ***
+	//newjet.set_user_index(jet.pass);
+	clust_seq.plugin_record_ij_recombination(jet_i, jet_j, dij, newjet, jet_k);
+      }
+
+    }
+
+    // we have merged all the jet's particles into a single object, so now
+    // "declare" it to be a beam (inclusive) jet.
+    // [NB: put a sensible looking d_iB just to be nice...]
+    double d_iB = clust_seq.jets()[jet_k].perp2();
+    clust_seq.plugin_record_iB_recombination(jet_k, d_iB);
+
+    // now record the pass of the jet in the extras object
+    extras->_pass[clust_seq.jets()[jet_k].cluster_hist_index()] = jet.pass;
+  }
+
+  // now copy the list of protocones into an "extras" objects
+  for (unsigned ipass = 0; ipass < siscone->protocones_list.size(); ipass++) {
+    for (unsigned ipc = 0; ipc < siscone->protocones_list[ipass].size(); ipc++) {
+      PseudoJet protocone(siscone->protocones_list[ipass][ipc]);
+      protocone.set_user_index(ipass);
+      extras->_protocones.push_back(protocone);
+    }
+  }
+  extras->_most_ambiguous_split = siscone->most_ambiguous_split;
+
+  // tell it what the jet definition was
+  extras->_jet_def_plugin = this;
+
+  // give the extras object to the cluster sequence.
+  clust_seq.plugin_associate_extras(std::auto_ptr<ClusterSequence::Extras>(extras));
+}
+
+
+void SISConePlugin::reset_stored_plugin() const{
+  stored_plugin.reset( new SISConePlugin(*this));
+}
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/area.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/area.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/area.cc	(revision 5)
@@ -0,0 +1,348 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: area.h                                                              //
+// Description: header file for the computation of jet area                  //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "area.h"
+#include "momentum.h"
+#include <stdlib.h>
+#include <iostream>
+
+namespace siscone{
+using namespace std;
+
+/*******************************************************
+ * Cjet_area implementation                            *
+ * real Jet information, including its area(s)         *
+ *                                                     *
+ * This class contains information for one single jet. *
+ * That is, first, its momentum carrying information   *
+ * about its centre and pT, and second, its particle   *
+ * contents (from CJeT).                               *
+ * Compared to the Cjet class, it also includes the    *
+ * passive and active areas of the jet computed using  *
+ * the Carea class.                                    *
+ *******************************************************/
+
+// default ctor
+//--------------
+Cjet_area::Cjet_area(){
+  active_area = passive_area = 0.0;
+}
+
+// jet-initiated ctor
+//-------------------
+Cjet_area::Cjet_area(Cjet &j){
+  v = j.v;
+  n = j.n;
+  contents = j.contents;
+
+  pass = j.pass;
+
+  pt_tilde = j.pt_tilde;
+  sm_var2 = j.sm_var2;
+
+  active_area = passive_area = 0.0;
+}
+
+// default dtor
+//--------------
+Cjet_area::~Cjet_area(){
+
+}
+
+
+/******************************************************************
+ * Csiscone_area implementation                                   *
+ * class for the computation of jet areas.                        *
+ *                                                                *
+ * This is the class user should use whenever you want to compute *
+ * the jet area (passive and active).                             *
+ * It uses the SISCone algorithm to perform the jet analysis.     *
+ ******************************************************************/
+
+// default ctor
+//-------------
+Carea::Carea(){
+  grid_size = 60;     // 3600 particles added
+  grid_eta_max = 6.0; // maybe having twice more points in eta than in phi should be nice
+  grid_shift = 0.5;   // 50% "shacking"
+
+  pt_soft = 1e-100;
+  pt_shift = 0.05;
+  pt_soft_min = 1e-90;
+}
+
+// default dtor
+//-------------
+Carea::~Carea(){
+  
+}
+  
+/*
+ * compute the jet areas from a given particle set.
+ * The parameters of this method are the ones which control the jet clustering alghorithm.
+ * Note that the pt_min is not allowed here soince the jet-area determination involves soft 
+ * particles/jets and thus is used internally.
+ *  - _particles   list of particles
+ *  - _radius      cone radius
+ *  - _f           shared energy threshold for splitting&merging
+ *  - _n_pass_max  maximum number of passes (0=full search, the default)
+ *  - _split_merge_scale    the scale choice for the split-merge procedure
+ *        NOTE: SM_pt leads to IR unsafety for some events with momentum conservation. 
+ *              SM_Et is IR safe but not boost invariant and not implemented(!)
+ *              SM_mt is IR safe for hadronic events, but not for decays of two 
+ *                    back-to-back particles of identical mass
+ *              SM_pttilde  
+ *                    is always IR safe, and also boost invariant (default)
+ *  - _hard_only   when this is set on, only hard jets are computed
+ *                 and not the purely ghosted jets (default: false)
+ * return the jets together with their areas
+ * The return value is the number of jets (including pure-ghost ones if they are included)
+ ********************************************************************************************/
+int Carea::compute_areas(std::vector<Cmomentum> &_particles, double _radius, double _f, 
+			 int _n_pass_max, Esplit_merge_scale _split_merge_scale,
+			 bool _hard_only){
+
+  vector<Cmomentum> all_particles;
+
+  // put "hardest cut-off" if needed
+  // this avoids computation of ghosted jets when not required and 
+  // significantly shortens the SM.
+  if (_hard_only){
+    SM_var2_hardest_cut_off = pt_soft_min*pt_soft_min;
+  } 
+
+  // clear potential previous runs
+  jet_areas.clear();
+
+  // put initial set of particles in the list
+  int n_hard = _particles.size();
+  all_particles = _particles;
+
+  // build the set of ghost particles and add them to the particle list
+  int i,j;
+  double eta_g,phi_g,pt_g;
+
+  for (i=0;i<grid_size;i++){
+    for (j=0;j<grid_size;j++){
+      eta_g = grid_eta_max*(-1.0+2.0*(i+0.5+grid_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0))))/grid_size);
+      phi_g = M_PI        *(-1.0+2.0*(j+0.5+grid_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0))))/grid_size);
+      pt_g  = pt_soft*(1.0+pt_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0))));
+      all_particles.push_back(Cmomentum(pt_g*cos(phi_g),pt_g*sin(phi_g),pt_g*sinh(eta_g),pt_g*cosh(eta_g)));
+    }
+  }
+  
+  // run clustering with all particles.
+  // the split-merge here dynamically accounts for the purely soft jets.
+  // we therefore end up with the active area for the jets
+  int n_jets = compute_jets(all_particles, _radius, _f, _n_pass_max, 0.0, _split_merge_scale);
+
+  // save jets in the Cjet_area structure
+  // and determine their size
+  // jet contents is ordered by increasing index of the initial
+  // particles. Hence, we look for the first particle with index >= n_hard
+  // and deduce the number of ghosts in the jet, hence the area.
+  double area_factor = (2.0*grid_eta_max/grid_size)*(twopi/grid_size);
+  
+  for (i=0;i<(int) jets.size();i++){
+    jet_areas.push_back(jets[i]);
+    j=0;
+    while ((j<jets[i].n) && (jets[i].contents[j]<n_hard)) j++;
+    jet_areas[i].active_area = (jets[i].n-j)*area_factor;
+  }
+
+  // determine passive jet area
+  // for that onem we use the pt_min cut in order to remove purely
+  // soft jets from the SM procedure
+  recompute_jets(_f, pt_soft_min);
+
+  // for the area computation, we assume the jete order is the same!
+  for (i=0;i<(int) jets.size();i++){
+    j=0;
+    while ((j<jets[i].n) && (jets[i].contents[j]<n_hard)) j++;
+    jet_areas[i].passive_area = (jets[i].n-j)*area_factor;
+  }
+
+  // Note:
+  // there surely remain purely soft je at the end
+  // their active area is 0 by default (see ctor)
+
+  jets.clear();
+
+  return n_jets;
+}
+
+/*
+ * compute the passive jet areas from a given particle set.
+ * The parameters of this method are the ones which control the jet clustering alghorithm.
+ * Note that the pt_min is not allowed here soince the jet-area determination involves soft 
+ * particles/jets and thus is used internally.
+ *  - _particles   list of particles
+ *  - _radius      cone radius
+ *  - _f           shared energy threshold for splitting&merging
+ *  - _n_pass_max  maximum number of passes (0=full search, the default)
+ *  - _split_merge_scale    the scale choice for the split-merge procedure
+ *        NOTE: SM_pt leads to IR unsafety for some events with momentum conservation. 
+ *              SM_Et is IR safe but not boost invariant and not implemented(!)
+ *              SM_mt is IR safe for hadronic events, but not for decays of two 
+ *                    back-to-back particles of identical mass
+ *              SM_pttilde  
+ *                    is always IR safe, and also boost invariant (default)
+ * return the jets together with their passive areas
+ * The return value is the number of jets
+ ********************************************************************************************/
+int Carea::compute_passive_areas(std::vector<Cmomentum> &_particles, double _radius, double _f, 
+				 int _n_pass_max, Esplit_merge_scale _split_merge_scale){
+
+  vector<Cmomentum> all_particles;
+
+  // in the case of passive area, we do not need 
+  // to put the ghosts in the stable-cone search
+  // (they do no influence the list of stable cones)
+  // Here's how it goes...
+  stable_cone_soft_pt2_cutoff = pt_soft_min*pt_soft_min;
+
+  // clear potential previous runs
+  jet_areas.clear();
+
+  // put initial set of particles in the list
+  int n_hard = _particles.size();
+  all_particles = _particles;
+
+  // build the set of ghost particles and add them to the particle list
+  int i,j;
+  double eta_g,phi_g,pt_g;
+
+  for (i=0;i<grid_size;i++){
+    for (j=0;j<grid_size;j++){
+      eta_g = grid_eta_max*(-1.0+2.0*(i+0.5+grid_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0))))/grid_size);
+      phi_g = M_PI        *(-1.0+2.0*(j+0.5+grid_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0))))/grid_size);
+      pt_g  = pt_soft*(1.0+pt_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0))));
+      all_particles.push_back(Cmomentum(pt_g*cos(phi_g),pt_g*sin(phi_g),pt_g*sinh(eta_g),pt_g*cosh(eta_g)));
+    }
+  }
+  
+  // determine passive jet area
+  // for that onem we use the pt_min cut in order to remove purely
+  // soft jets from the SM procedure
+  int n_jets = compute_jets(all_particles, _radius, _f, _n_pass_max, pt_soft_min, _split_merge_scale);
+
+  // save jets in the Cjet_area structure
+  // and determine their size
+  // jet contents is ordered by increasing index of the initial
+  // particles. Hence, we look for the first particle with index >= n_hard
+  // and deduce the number of ghosts in the jet, hence the area.
+  double area_factor = (2.0*grid_eta_max/grid_size)*(twopi/grid_size);
+  for (i=0;i<(int) jets.size();i++){
+    j=0;
+    while ((j<jets[i].n) && (jets[i].contents[j]<n_hard)) j++;
+    jet_areas[i].passive_area = (jets[i].n-j)*area_factor;
+  }
+
+  jets.clear();
+
+  return n_jets;
+}
+
+/*
+ * compute the active jet areas from a given particle set.
+ * The parameters of this method are the ones which control the jet clustering alghorithm.
+ * Note that the pt_min is not allowed here soince the jet-area determination involves soft 
+ * particles/jets and thus is used internally.
+ *  - _particles   list of particles
+ *  - _radius      cone radius
+ *  - _f           shared energy threshold for splitting&merging
+ *  - _n_pass_max  maximum number of passes (0=full search, the default)
+ *  - _split_merge_scale    the scale choice for the split-merge procedure
+ *        NOTE: SM_pt leads to IR unsafety for some events with momentum conservation. 
+ *              SM_Et is IR safe but not boost invariant and not implemented(!)
+ *              SM_mt is IR safe for hadronic events, but not for decays of two 
+ *                    back-to-back particles of identical mass
+ *              SM_pttilde  
+ *                    is always IR safe, and also boost invariant (default)
+ *  - _hard_only   when this is set on, only hard jets are computed
+ *                 and not the purely ghosted jets (default: false)
+ * return the jets together with their active areas
+ * The return value is the number of jets (including pure-ghost ones if they are included)
+ ********************************************************************************************/
+int Carea::compute_active_areas(std::vector<Cmomentum> &_particles, double _radius, double _f, 
+				int _n_pass_max, Esplit_merge_scale _split_merge_scale,
+				bool _hard_only){
+
+  vector<Cmomentum> all_particles;
+
+  // put "hardest cut-off" if needed
+  // this avoids computation of ghosted jets when not required and 
+  // significantly shortens the SM.
+  if (_hard_only){
+    SM_var2_hardest_cut_off = pt_soft_min*pt_soft_min;
+  }
+
+  // clear potential previous runs
+  jet_areas.clear();
+
+  // put initial set of particles in the list
+  int n_hard = _particles.size();
+  all_particles = _particles;
+
+  // build the set of ghost particles and add them to the particle list
+  int i,j;
+  double eta_g,phi_g,pt_g;
+
+  for (i=0;i<grid_size;i++){
+    for (j=0;j<grid_size;j++){
+      eta_g = grid_eta_max*(-1.0+2.0*(i+0.5+grid_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0))))/grid_size);
+      phi_g = M_PI        *(-1.0+2.0*(j+0.5+grid_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0))))/grid_size);
+      pt_g  = pt_soft*(1.0+pt_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0))));
+      all_particles.push_back(Cmomentum(pt_g*cos(phi_g),pt_g*sin(phi_g),pt_g*sinh(eta_g),pt_g*cosh(eta_g)));
+    }
+  }
+  
+  // run clustering with all particles.
+  // the split-merge here dynamically accounts for the purely soft jets.
+  // we therefore end up with the active area for the jets
+  int n_jets = compute_jets(all_particles, _radius, _f, _n_pass_max, 0.0, _split_merge_scale);
+
+  // save jets in the Cjet_area structure
+  // and determine their size
+  // jet contents is ordered by increasing index of the initial
+  // particles. Hence, we look for the first particle with index >= n_hard
+  // and deduce the number of ghosts in the jet, hence the area.
+  double area_factor = (2.0*grid_eta_max/grid_size)*(twopi/grid_size);
+  
+  for (i=0;i<(int) jets.size();i++){
+    jet_areas.push_back(jets[i]);
+    j=0;
+    while ((j<jets[i].n) && (jets[i].contents[j]<n_hard)) j++;
+    jet_areas[i].active_area = (jets[i].n-j)*area_factor;
+  }
+
+  jets.clear();
+
+  return n_jets;
+}
+
+}
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/area.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/area.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/area.h	(revision 5)
@@ -0,0 +1,139 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: area.h                                                              //
+// Description: header file for the computation of jet area                  //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SISCONE_AREA_H__
+#define __SISCONE_AREA_H__
+
+#include "momentum.h"
+#include "siscone.h"
+
+namespace siscone{
+
+/**
+ * \class Cjet_area
+ * real Jet information, including its area(s)
+ *
+ * This class contains information for one single jet. 
+ * That is, first, its momentum carrying information
+ * about its centre and pT, and second, its particle
+ * contents.
+ * Compared to the Cjet class, it also includes the 
+ * passive and active areas of the jet computed using 
+ * the Carea class.
+ */
+class Cjet_area : public Cjet{
+ public:
+  /// default ctor
+  Cjet_area();
+
+  /// jet-initialised ctor
+  Cjet_area(Cjet &j);
+
+  /// default dtor
+  ~Cjet_area();
+
+  // area information
+  double passive_area;   ///< passive area
+  double active_area;    ///< active area
+};
+
+/**
+ * \class Carea
+ * class for the computation of jet areas.
+ * 
+ * This is the class user should use whenever you want to compute
+ * the jet area (passive and active). .
+ * It uses the SISCone algorithm to perform the jet analysis.
+ */
+class Carea : public Csiscone{
+ public:
+  /// default ctor
+  Carea();
+
+  /// default dtor
+  ~Carea();
+
+  /**
+   * compute the jet areas from a given particle set.
+   * The parameters of this method are the ones which control the jet clustering alghorithn.
+   * Note that the pt_min is not allowed here soince the jet-area determination involves soft 
+   * particles/jets and thus is used internally.
+   * \param _particles   list of particles
+   * \param _radius      cone radius
+   * \param _f           shared energy threshold for splitting&merging
+   * \param _n_pass_max  maximum number of passes (0=full search, the default)
+   * \param _split_merge_scale    the scale choice for the split-merge procedure
+   *        NOTE: SM_pt leads to IR unsafety for some events with momentum conservation. 
+   *              SM_Et is IR safe but not boost invariant and not implemented(!)
+   *              SM_mt is IR safe for hadronic events, but not for decays of two 
+   *                    back-to-back particles of identical mass
+   *              SM_pttilde  
+   *                    is always IR safe, and also boost invariant (default)
+   * \param _hard_only  when this is set on, only hard jets are computed
+   *                    and not the purely ghosted jets (default: false)
+   * \return the number of jets (including pure-ghost ones if they are included)
+   */
+  int compute_areas(std::vector<Cmomentum> &_particles, double _radius, double _f, 
+		    int _n_pass_max=0, Esplit_merge_scale _split_merge_scale=SM_pttilde,
+		    bool _hard_only=false);
+
+  /**
+   * compute the jet active areas from a given particle set.
+   * The parameters of this method are the ones which control the jet clustering alghorithn.
+   * Note that the pt_min is not allowed here soince the jet-area determination involves soft 
+   * particles/jets and thus is used internally.
+   * See compute_areas for paramters definition.
+   * \return the number of jets (including pure-ghost ones if they are included)
+   */
+  int compute_active_areas(std::vector<Cmomentum> &_particles, double _radius, double _f, 
+			   int _n_pass_max=0, Esplit_merge_scale _split_merge_scale=SM_pttilde,
+			   bool _hard_only=false);
+
+  /**
+   * compute the jet passive areas from a given particle set.
+   * The parameters of this method are the ones which control the jet clustering alghorithn.
+   * Note that the pt_min is not allowed here soince the jet-area determination involves soft 
+   * particles/jets and thus is used internally.
+   * See compute_areas for paramters definition.
+   */
+  int compute_passive_areas(std::vector<Cmomentum> &_particles, double _radius, double _f, 
+			    int _n_pass_max=0, Esplit_merge_scale _split_merge_scale=SM_pttilde);
+
+  int grid_size;        ///< size of the grid we add soft particles on (N_soft=(grid_size^2))
+  double grid_eta_max;  ///< maximal value of eta we add soft particles on
+  double grid_shift;    ///< fractional (random) displacement of the points om the grid
+
+  double pt_soft;       ///< pt of the soft particles added
+  double pt_shift;      ///< amplitude of the pt random shift
+  double pt_soft_min;   ///< pt_min used in SM to compute passive areas
+
+  /// jets with their areas
+  std::vector<Cjet_area> jet_areas;
+};
+
+}
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/circulator.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/circulator.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/circulator.h	(revision 5)
@@ -0,0 +1,90 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: circulator.h                                                        //
+// Description: header file for circulator (circulator class)                //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __CIRCULATOR_H__
+#define __CIRCULATOR_H__
+
+namespace siscone{
+
+/// \class circulator
+/// a circulator that is foreseen to take as template member either a
+/// pointer or an iterator;
+template<class T> class circulator { 
+
+public:
+  /// ctor with iniitalisation from iterators
+  ///  \param here   the current position
+  ///  \param begin  the first position
+  ///  \param end    the last position
+  inline circulator(T here, T begin, T end) : m_here(here), m_begin(begin), m_end(end) {}
+
+  /// copy ctor
+  ///  \param other  the circulator to copy
+  inline circulator(const circulator<T> & other) : m_here(other.m_here), m_begin(other.m_begin), m_end(other.m_end) {}
+
+  /// set just the position without resetting the begin and end elements
+  ///   \param other   the circulator to grab position from
+  void set_position(const circulator<T> & other) {m_here = other.m_here;}
+
+  /// set just the position without resetting the begin and end elements
+  ///   \param pointer   the iterator to use as the new position
+  void set_position(T pointer) {m_here = pointer;}
+
+  /// get the current object
+  T operator()() {return m_here;}
+
+  /// position incrementation
+  inline circulator<T> & operator++() { 
+    ++m_here; 
+    if (m_here == m_end) m_here = m_begin;
+    return *this;
+  }
+
+  /// position decrementation
+  inline circulator<T> & operator--() { 
+    if (m_here == m_begin) m_here = m_end;
+    --m_here; 
+    return *this;
+  }
+  
+  /// check if the current elements are the same
+  /// NB: for efficiency, this checks only the here element
+  ///  \param  other   the circulator to compare to the current one
+  bool operator==(const circulator & other) const {return m_here == other.m_here;}
+
+  /// check if the current elements are different
+  /// NB: for efficiency, this checks only the here element
+  ///  \param  other   the circulator to compare to the current one
+  bool operator!=(const circulator & other) const {return m_here != other.m_here;}
+
+private:
+  T  m_here, m_begin, m_end;   ///< the current, beginning and ending iterators/pointers
+};
+
+}
+
+#endif // __CIRCULATOR_H__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/config.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/config.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/config.h	(revision 5)
@@ -0,0 +1,66 @@
+/* siscone/config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `m' library (-lm). */
+#define HAVE_LIBM 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#define LT_OBJDIR ".libs/"
+
+/* Name of package */
+#define PACKAGE "siscone"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "SISCone"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "SISCone 2.0.5"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "siscone"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "2.0.5"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "2.0.5"
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/defines.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/defines.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/defines.h	(revision 5)
@@ -0,0 +1,128 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: defines.h                                                           //
+// Description: header file for generic parameters definitions               //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+//! \file defines.h
+#ifndef __DEFINES_H__
+#define __DEFINES_H__
+
+/// program name
+// we get "SISCone" by calling
+//  siscone::siscone_package_name
+// defined in siscone.h
+// Otherwise, config.h
+// It is also defined as "PACKAGE_NAME" in config.h but this method 
+// might lead to conflicts
+//#define PROGRAM   PACKAGE_NAME 
+
+// program version
+// we get it from
+//   siscone::siscone_version
+// defined in siscone.h
+// It is also defined as "VERSION" in config.h but this method 
+// might lead to conflicts
+
+/// perform final stability check using the quadtree
+/// With the following define enabled, the final check for stability
+/// is performed using the quadtree rather than the explicit list of 
+/// particles (see Cstable_cone::proceed_with_stability())
+//#define USE_QUADTREE_FOR_STABILITY_TEST
+
+
+/// threshold for recomoutation of the cone (see Cstable_cones::update_cone())
+/// When traversing cone candidates along the angular ordering,
+/// the momentum of the protojet candidate is computed incrementally
+/// from the particles that enter and leave the cone.
+/// When the cumulative change in "|px|+|py|" exceeds the cone "|px|+|py|"
+/// we explicitely recompute the cone contents
+#define PT_TSHOLD 1000.0
+
+
+/// The following parameter controls collinear safety. For the set of 
+/// particles used in the search of stable cones, we gather particles
+/// if their distance in eta and phi is smaller than EPSILON_COLLINEAR.
+///
+/// NB: for things to behave sensibly one requires 
+///        1e-15 << EPSILON_COCIRCULAR << EPSILON_COLLINEAR << 1
+///
+/// among the scales that appear in practice (e.g. in deciding to use
+/// special strategies), we have EPSILON_COLLINEAR, EPSILON_COCIRCULAR,
+/// sqrt(EPSILON_COCIRCULAR) and EPSILON_COLLINEAR / EPSILON_COCIRCULAR.
+///
+#define EPSILON_COLLINEAR 1e-8
+
+
+/// The following parameter controls cocircular situations.
+/// When consecutive particles in the ordered vicinity list are separated
+/// (in angle) by less that that limit, we consider that we face a situation
+/// of cocircularity.
+#define EPSILON_COCIRCULAR 1e-12
+
+
+/// The following define enables you to allow for identical protocones
+/// to be merged automatically after each split-merge step before
+/// anything else happens. Whether this happens depends on teh value
+/// of the merge_identical_protocones flag in Csplit_merge.
+///
+/// It we allow such a merging and define allow 
+/// MERGE_IDENTICAL_PROTOCONES_DEFAULT_TRUE then the
+/// 'merge_identical_protocones' flag in Csplit_merge to be set to
+/// 'true'. It may be manually reset to false in which case the
+/// merging of identical protocones (protojets) will be turned off.
+///
+/// Note that this merging identical protocones makes the algorithm
+/// infrared-unsafe, so it should be disabled except for testing
+/// purposes.
+//#define ALLOW_MERGE_IDENTICAL_PROTOCONES
+//#define MERGE_IDENTICAL_PROTOCONES_DEFAULT_TRUE
+
+
+/// if EPSILON_SPLITMERGE is defined then, during the split-merge
+/// step, when two jets are found with PTs that are identical to
+/// within a relative difference of EPSILON_SPLITMERGE they are
+/// compared element-by-element to see where the differences are, and
+/// one then uses pt1^2-pt2^2 = (pt1-pt2).(pt1+pt2) as an estimator of
+/// which is harder. NB: in unfortunate cases, this can take the split
+/// merge step up to N n * ln N time, though on normal events there
+/// don't seem to have been any major problems yet.
+#define EPSILON_SPLITMERGE 1e-12
+
+/// definition of 2*M_PI which is useful a bit everyhere!
+const double twopi = 6.283185307179586476925286766559005768394;
+
+/// debugging information
+//#define DEBUG_STABLE_CONES   ///< debug messages in stable cones search
+//#define DEBUG_SPLIT_MERGE    ///< debug messages in split-merge
+//#define DEBUG                ///< all debug messages !
+
+// in case all debug massages allowed, allow them in practice !
+#ifdef DEBUG
+#define DEBUG_STABLE_CONES
+#define DEBUG_SPLIT_MERGE
+#endif
+
+#endif  //  __DEFINES_H__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/fastjet/SISConeBasePlugin.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/fastjet/SISConeBasePlugin.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/fastjet/SISConeBasePlugin.hh	(revision 5)
@@ -0,0 +1,191 @@
+#ifndef __SISCONEBASEPLUGIN_HH__
+#define __SISCONEBASEPLUGIN_HH__
+
+#include "fastjet/JetDefinition.hh"
+#include "fastjet/ClusterSequence.hh"
+#include <vector>
+#include <memory>
+#include <cmath>
+
+#include <sstream>
+
+// questionable whether this should be in fastjet namespace or not...
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+//
+/// \if internal_doc
+/// @ingroup internal
+/// \class SISConeBasePlugin
+/// Implementation of the SISCone algorithm, base class (plugin for fastjet v2.1 upwards)
+///
+/// SISConeBasePlugin is a plugin for fastjet (v2.1 upwards) that
+/// provides a base interface to SISCone-type cone jet finder by
+/// Gregory Soyez and Gavin Salam.
+///
+/// This is a purely virtual class that needs to be overloaded
+/// for the specific implementations of SISCone (i.e. regular or
+/// spherical as of July 16th 2008).
+///
+/// any derived plugin MUST overload the following methods:
+///   description()
+///   run_siscone_clustering()
+///   reset_stored_plugin()
+///
+/// For further details, see the derived plugins or
+/// http://projects.hepforge.com/siscone
+///
+/// \endif
+//
+class SISConeBasePlugin : public JetDefinition::Plugin {
+public:
+  /// default ctor
+  SISConeBasePlugin (){
+    _use_jet_def_recombiner = false;
+  }
+
+  /// copy constructor
+  SISConeBasePlugin (const SISConeBasePlugin & plugin) {
+    *this = plugin;
+  }
+
+  /// the cone radius
+  double cone_radius        () const {return _cone_radius        ;}
+
+  /// Fraction of overlap energy in a jet above which jets are merged
+  /// and below which jets are split.
+  double overlap_threshold  () const {return _overlap_threshold  ;}
+
+  /// the maximum number of passes of stable-cone searching (<=0 is same
+  /// as infinity).
+  int n_pass_max  () const {return _n_pass_max  ;}
+
+  /// set the "split_merge_stopping_scale": if the scale variable for
+  /// all protojets is below this, then stop the split-merge procedure
+  /// and keep only those jets found so far. This is useful in
+  /// determination of areas of hard jets because it can be used to
+  /// avoid running the split-merging on the pure ghost-part of the
+  /// event.
+  void set_split_merge_stopping_scale(double scale) {
+    _split_merge_stopping_scale = scale;}
+
+  /// return the value of the split_merge_stopping_scale (see
+  /// set_split_merge_stopping_scale(...) for description)
+  double split_merge_stopping_scale() {return _split_merge_stopping_scale;}
+
+  /// allow the user to decide if one uses the jet_def's own recombination scheme
+  void set_use_jet_def_recombiner(bool choice) {_use_jet_def_recombiner = choice;}
+
+  /// indicate if the jet_def's recombination scheme is being used
+  bool use_jet_def_recombiner() const {return _use_jet_def_recombiner;}
+
+  /// indicates whether caching is turned on or not.
+  bool caching() const {return _caching ;}
+
+  /// the plugin mechanism's standard way of accessing the jet radius
+  virtual double R() const {return cone_radius();}
+
+  /// return true since there is specific support for the measurement
+  /// of passive areas, in the sense that areas determined from all
+  /// particles below the ghost separation scale will be a passive
+  /// area. 
+  virtual bool supports_ghosted_passive_areas() const {
+    return true;
+  }
+  
+  /// set the ghost separation scale for passive area determinations
+  /// _just_ in the next run (strictly speaking that makes the routine
+  /// a non const, so related internal info must be stored as a mutable)
+  virtual void set_ghost_separation_scale(double scale) const {
+    _ghost_sep_scale = scale;
+  }
+
+  virtual double ghost_separation_scale() const {
+    return _ghost_sep_scale;
+  }
+
+  // the things that one MUST overload required by base class
+  //---------------------------------------------------------
+
+  /// plugin description
+  virtual std::string description () const =0;
+
+  /// really do the clustering work
+  virtual void run_clustering(ClusterSequence &) const = 0;
+
+protected:
+  double _cone_radius, _overlap_threshold;
+  int    _n_pass_max;
+  bool   _caching;//, _split_merge_on_transverse_mass;
+  double _split_merge_stopping_scale;
+  bool   _use_jet_def_recombiner;
+
+  mutable double _ghost_sep_scale;
+
+  // the part that HAS to be overloaded
+  /// call the re-clustering itself 
+  virtual void reset_stored_plugin() const =0;
+
+};
+
+
+//======================================================================
+/// @ingroup extra_info
+/// \class SISConeBaseExtras
+/// Class that provides extra information about a SISCone clustering
+///
+/// This is only the base class that the "regular" and "spherical"
+/// implementations of SISCone will have to overload. The only thing
+/// that needs to be done for the derived classes is to define
+/// '_jet_def_plugin', implement
+///   jet_def_plugin();
+/// and add the corresponding plugin class as a friend
+class SISConeBaseExtras : public ClusterSequence::Extras {
+public:
+
+  /// constructor
+  //  it just initialises the pass information 
+  SISConeBaseExtras(int nparticles) : _pass(nparticles*2,-1) {}
+
+  /// purely virtual destructor
+  inline virtual ~SISConeBaseExtras()=0;
+
+  /// returns a reference to the vector of stable cones (aka protocones)
+  const std::vector<PseudoJet> & stable_cones() const {return _protocones;}
+
+  /// an old name for getting the vector of stable cones (aka protocones)
+  const std::vector<PseudoJet> & protocones() const {return _protocones;}
+
+  /// return the # of the pass at which a given jet was found; will
+  /// return -1 if the pass is invalid
+  int pass(const PseudoJet & jet) const {return _pass[jet.cluster_hist_index()];}
+
+  /// return a brief summary of the contents of the extras object
+  /// (specifically, the number of protocones.
+  std::string description() const{
+    std::ostringstream ostr;
+    ostr << "This SISCone clustering found " << protocones().size()
+	 << " stable protocones";
+    return ostr.str();
+  };
+
+  /// return the smallest difference in squared distance encountered
+  /// during splitting between a particle and two overlapping
+  /// protojets.
+  inline double most_ambiguous_split() const {return _most_ambiguous_split;}
+
+protected:
+  std::vector<PseudoJet> _protocones;
+  std::vector<int>       _pass;
+  double                _most_ambiguous_split;
+  const SISConeBasePlugin * _jet_def_plugin;
+};
+
+/// give the destructor its required implementation
+inline SISConeBaseExtras::~SISConeBaseExtras(){}
+
+
+FASTJET_END_NAMESPACE        // defined in fastjet/internal/base.hh
+
+#endif // __SISCONEBASEPLUGIN_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/fastjet/SISConePlugin.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/fastjet/SISConePlugin.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/fastjet/SISConePlugin.hh	(revision 5)
@@ -0,0 +1,220 @@
+#ifndef __SISCONEPLUGIN_HH__
+#define __SISCONEPLUGIN_HH__
+
+#include "SISConeBasePlugin.hh"
+
+// forward declaration of the siscone classes we'll need
+namespace siscone{
+  class Csiscone;
+}
+
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+//
+/// @ingroup plugins
+/// \class SISConePlugin
+/// Implementation of the SISCone algorithm (plugin for fastjet v2.1 upwards)
+///
+/// SISConePlugin is a plugin for fastjet (v2.1 upwards) that provides
+/// an interface to the seedless infrared safe cone jet finder by
+/// Gregory Soyez and Gavin Salam.
+///
+/// SISCone uses geometrical techniques to exhaustively consider all
+/// possible distinct cones. It then finds out which ones are stable
+/// and sends the result to the Tevatron Run-II type split-merge
+/// procedure for overlapping cones.
+///
+/// Four parameters govern the "physics" of the algorithm:
+///
+///  - the cone_radius (this should be self-explanatory!)
+///
+///  - the overlap_threshold is the parameter which dictates how much
+///    two jets must overlap (pt_overlap/min(pt1,pt2)) if they are to be 
+///    merged
+///
+///  - Not all particles are in stable cones in the first round of
+///    searching for stable cones; one can therefore optionally have the
+///    the jet finder carry out additional passes of searching for
+///    stable cones among particles that were in no stable cone in
+///    previous passes --- the maximum number of passes carried out is
+///    n_pass_max. If this is zero then additional passes are carried
+///    out until no new stable cones are found.
+///
+///  - Protojet ptmin: protojets that are below this ptmin
+///    (default = 0) are discarded before each iteration of the
+///    split-merge loop.
+///
+/// One parameter governs some internal algorithmic shortcuts: 
+///
+/// - if "caching" is turned on then the last event clustered by
+///   siscone is stored -- if the current event is identical and the
+///   cone_radius and n_pass_mass are identical, then the only part of
+///   the clustering that needs to be rerun is the split-merge part,
+///   leading to significant speed gains; there is a small (O(N) storage
+///   and speed) penalty for caching, so it should be kept off
+///   (default) if only a single overlap_threshold is used.
+///
+/// The final jets can be accessed by requestion the
+/// inclusive_jets(...) from the ClusterSequence object. Note that
+/// these PseudoJets have their user_index() set to the index of the
+/// pass in which they were found (first pass = 0). NB: This does not
+/// currently work for jets that consist of a single particle.
+///
+/// For further information on the details of the algorithm see the
+/// SISCone paper, arXiv:0704.0292 [JHEP 0705:086,2007].
+///
+/// For documentation about the implementation, see the
+/// siscone/doc/html/index.html file.
+//
+class SISConePlugin : public SISConeBasePlugin{
+public:
+
+  /// enum for the different split-merge scale choices;
+  /// Note that order _must_ be the same as in siscone
+  enum SplitMergeScale {SM_pt,     ///< transverse momentum (E-scheme), IR unsafe
+                        SM_Et,     ///< transverse energy (E-scheme), not long. boost invariant
+                                   ///< original run-II choice [may not be implemented]
+                        SM_mt,     ///< transverse mass (E-scheme), IR safe except
+                                   ///< in decays of two identical narrow heavy particles
+                        SM_pttilde ///< pt-scheme pt = \sum_{i in jet} |p_{ti}|, should
+                                   ///< be IR safe in all cases
+  };
+
+
+  /// Main constructor for the SISCone Plugin class.  
+  ///
+  /// Note: wrt version prior to 2.4 this constructor differs in that a 
+  /// the default value has been removed for overlap_threshold. The
+  /// former has been removed because the old default of 0.5 was found
+  /// to be unsuitable in high-noise environments; so the user should
+  /// now explicitly think about the value for this -- we recommend
+  /// 0.75.
+  ///
+  SISConePlugin (double cone_radius_in,
+                 double overlap_threshold_in,
+                 int    n_pass_max_in = 0,
+                 double protojet_ptmin_in = 0.0, 
+                 bool   caching_in = false,
+                 SplitMergeScale  split_merge_scale_in = SM_pttilde,
+                 double split_merge_stopping_scale_in = 0.0){
+    _cone_radius           = cone_radius_in;
+    _overlap_threshold     = overlap_threshold_in;
+    _n_pass_max            = n_pass_max_in;
+    _protojet_ptmin        = protojet_ptmin_in;
+    _caching               = caching_in;   
+    _split_merge_scale     = split_merge_scale_in;
+    _split_merge_stopping_scale = split_merge_stopping_scale_in;
+    _ghost_sep_scale       = 0.0;
+    _use_pt_weighted_splitting = false;}
+
+
+  /// Backwards compatible constructor for the SISCone Plugin class
+  SISConePlugin (double cone_radius_in,
+                 double overlap_threshold_in,
+                 int    n_pass_max_in,
+                 double protojet_ptmin_in, 
+                 bool   caching_in,
+                 bool   split_merge_on_transverse_mass_in){
+    _cone_radius           = cone_radius_in;
+    _overlap_threshold     = overlap_threshold_in;
+    _n_pass_max            = n_pass_max_in;
+    _protojet_ptmin        = protojet_ptmin_in;
+    _caching               = caching_in;
+    _split_merge_stopping_scale = 0.0;
+    _split_merge_scale     = split_merge_on_transverse_mass_in ? SM_mt : SM_pttilde;
+    _ghost_sep_scale       = 0.0;}
+  
+  /// backwards compatible constructor for the SISCone Plugin class
+  /// (avoid using this in future).
+  SISConePlugin (double cone_radius_in,
+                 double overlap_threshold_in,
+                 int    n_pass_max_in,
+                 bool   caching_in) {
+    _cone_radius           = cone_radius_in;
+    _overlap_threshold     = overlap_threshold_in;
+    _n_pass_max            = n_pass_max_in;
+    _protojet_ptmin        = 0.0;
+    _caching               = caching_in;   
+    _split_merge_scale     = SM_mt;
+    _split_merge_stopping_scale = 0.0;
+    _ghost_sep_scale       = 0.0;
+    _use_pt_weighted_splitting = false;}
+
+  /// minimum pt for a protojet to be considered in the split-merge step
+  /// of the algorithm
+  double protojet_ptmin  () const {return _protojet_ptmin  ;}
+
+  /// return the scale to be passed to SISCone as the protojet_ptmin
+  /// -- if we have a ghost separation scale that is above the
+  /// protojet_ptmin, then the ghost_separation_scale becomes the
+  /// relevant one to use here
+  double protojet_or_ghost_ptmin  () const {return std::max(_protojet_ptmin,
+                                                            _ghost_sep_scale);}
+
+  /// indicates scale used in split-merge
+  SplitMergeScale split_merge_scale() const {return _split_merge_scale;}
+  /// sets scale used in split-merge
+  void set_split_merge_scale(SplitMergeScale sms) {_split_merge_scale = sms;}
+
+  /// indicates whether the split-merge orders on transverse mass or not.
+  /// retained for backwards compatibility with 2.1.0b3
+  bool split_merge_on_transverse_mass() const {return _split_merge_scale == SM_mt ;}
+  void set_split_merge_on_transverse_mass(bool val) {
+    _split_merge_scale = val  ? SM_mt : SM_pt;}
+
+  /// indicates whether the split-merge orders on transverse mass or not.
+  /// retained for backwards compatibility with 2.1.0b3
+  bool split_merge_use_pt_weighted_splitting() const {return _use_pt_weighted_splitting;}
+  void set_split_merge_use_pt_weighted_splitting(bool val) {
+    _use_pt_weighted_splitting = val;}
+
+  // the things that are required by base class
+  virtual std::string description () const;
+  virtual void run_clustering(ClusterSequence &) const ;
+
+protected:
+  virtual void reset_stored_plugin() const;
+
+private:
+  double _protojet_ptmin;
+  SplitMergeScale _split_merge_scale;
+
+  bool _use_pt_weighted_splitting;
+
+  // part needed for the cache 
+  // variables for caching the results and the input
+  static std::auto_ptr<SISConePlugin          > stored_plugin;
+  static std::auto_ptr<std::vector<PseudoJet> > stored_particles;
+  static std::auto_ptr<siscone::Csiscone      > stored_siscone;
+};
+
+
+//======================================================================
+/// @ingroup extra_info
+/// \class SISConeExtras
+/// Class that provides extra information about a SISCone clustering
+class SISConeExtras : public SISConeBaseExtras {
+public:
+  /// constructor
+  //  it just initialises the pass information 
+  SISConeExtras(int nparticles)
+    : SISConeBaseExtras(nparticles){}
+
+  /// access to the siscone jet def plugin (more convenient than
+  /// getting it from the original jet definition, because here it's
+  /// directly of the right type (rather than the base type)
+  const SISConePlugin* jet_def_plugin() const {
+    return dynamic_cast<const SISConePlugin*>(_jet_def_plugin);
+  }
+
+private:
+  // let us be written to by SISConePlugin
+  friend class SISConePlugin;
+};
+
+FASTJET_END_NAMESPACE        // defined in fastjet/internal/base.hh
+
+#endif // __SISCONEPLUGIN_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/fastjet/SISConeSphericalPlugin.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/fastjet/SISConeSphericalPlugin.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/fastjet/SISConeSphericalPlugin.hh	(revision 5)
@@ -0,0 +1,195 @@
+#ifndef __SISCONESPHERICALPLUGIN_HH__
+#define __SISCONESPHERICALPLUGIN_HH__
+
+#include "SISConeBasePlugin.hh"
+
+// forward declaration of the siscone classes we'll need
+namespace siscone_spherical{
+  class CSphsiscone;
+}
+
+// questionable whether this should be in fastjet namespace or not...
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+//
+/// @ingroup plugins
+/// \class SISConeSphericalPlugin
+/// Implementation of the spherical version of the SISCone algorithm
+/// (plugin for fastjet v2.1 upwards)
+///
+/// SISConeSphericalPlugin is a plugin for fastjet (v2.1 upwards) that
+/// provides an interface to the seedless infrared safe cone jet
+/// finder by Gregory Soyez and Gavin Salam.
+///
+/// This is the version of SISCone using spherical coordinates. Compared
+/// to the original cylindrical version:
+///
+///  - Particles are within a cone if their opening angle relative to the
+///    centre of the cone is less than R
+///
+///  - The split-merge step uses the total energy in the protojet as the
+///    ordering and overlap-measure variable
+///
+///  - The IR safety of the split-merge step is _not_ guaranteed for
+///    events consisting of two back-to-back identical heavy particles
+///    that decay. This is because of potential degeneracies in the
+///    ordering for the split-merge step. 
+///
+///    For moderate values of R the problem should not be too severe
+///    (or may even be absent for some values of the overlap
+///    parameter), however the user should be aware of the issue.
+///
+///    The default split-merge scale may change at a later date to
+///    resolve this issue.
+///
+///
+/// SISCone uses geometrical techniques to exhaustively consider all
+/// possible distinct cones. It then finds out which ones are stable
+/// and sends the result to the Tevatron Run-II type split-merge
+/// procedure for overlapping cones.
+///
+/// Four parameters govern the "physics" of the algorithm:
+///
+///  - the cone_radius (this should be self-explanatory!)
+///
+///  - the overlap_threshold is the parameter which dictates how much
+///    two jets must overlap (E_overlap/min(E1,E2)) if they are to be 
+///    merged
+///
+///  - Not all particles are in stable cones in the first round of
+///    searching for stable cones; one can therefore optionally have the
+///    the jet finder carry out additional passes of searching for
+///    stable cones among particles that were in no stable cone in
+///    previous passes --- the maximum number of passes carried out is
+///    n_pass_max. If this is zero then additional passes are carried
+///    out until no new stable cones are found.
+///
+///  - Protojet Emin: protojets that are below this Emin
+///    (default = 0) are discarded before each iteration of the
+///    split-merge loop.
+///
+/// One parameter governs some internal algorithmic shortcuts: 
+///
+/// - if "caching" is turned on then the last event clustered by
+///   siscone is stored -- if the current event is identical and the
+///   cone_radius and n_pass_max are identical, then the only part of
+///   the clustering that needs to be rerun is the split-merge part,
+///   leading to significant speed gains; there is a small (O(N) storage
+///   and speed) penalty for caching, so it should be kept off
+///   (default) if only a single overlap_threshold is used.
+///
+/// The final jets can be accessed by requestion the
+/// inclusive_jets(...) from the ClusterSequence object. Note that
+/// these PseudoJets have their user_index() set to the index of the
+/// pass in which they were found (first pass = 0). NB: This does not
+/// currently work for jets that consist of a single particle.
+///
+/// For further information on the details of the algorithm see the
+/// SISCone paper, arXiv:0704.0292 [JHEP 0705:086,2007].
+///
+/// For documentation about the implementation, see the
+/// siscone/doc/html/index.html file.
+//
+class SISConeSphericalPlugin : public SISConeBasePlugin{
+public:
+
+  /// enum for the different split-merge scale choices;
+  /// Note that order _must_ be the same as in siscone
+  enum SplitMergeScale {SM_E,        ///< Energy (IR unsafe with momentum conservation)
+			SM_Etilde    ///< sum_{i \in jet} E_i [1+sin^2(theta_iJ)]
+  };
+
+
+  /// Main constructor for the SISConeSpherical Plugin class.  
+  ///
+  ///
+  SISConeSphericalPlugin (double cone_radius_in,
+			  double overlap_threshold_in,
+			  int    n_pass_max_in = 0,
+			  double protojet_Emin_in = 0.0, 
+			  bool   caching_in = false,
+			  SplitMergeScale  split_merge_scale_in = SM_Etilde,
+			  double split_merge_stopping_scale_in = 0.0){
+    _cone_radius           =cone_radius_in;
+    _overlap_threshold     =overlap_threshold_in;
+    _n_pass_max            =n_pass_max_in;
+    _protojet_Emin         =protojet_Emin_in;
+    _caching               =caching_in;
+    _split_merge_scale     =split_merge_scale_in;
+    _split_merge_stopping_scale = split_merge_stopping_scale_in;
+    _ghost_sep_scale       = 0.0;
+    _use_E_weighted_splitting = false;
+  }
+
+  /// minimum energy for a protojet to be considered in the split-merge step
+  /// of the algorithm
+  double protojet_Emin  () const {return _protojet_Emin  ;}
+
+  /// return the scale to be passed to SISCone as the protojet_Emin
+  /// -- if we have a ghost separation scale that is above the
+  /// protojet_ptmin, then the ghost_separation_scale becomes the
+  /// relevant one to use here
+  double protojet_or_ghost_Emin  () const {return std::max(_protojet_Emin,
+                                                           _ghost_sep_scale);}
+
+  /// indicates scale used in split-merge
+  SplitMergeScale split_merge_scale() const {return _split_merge_scale;}
+  /// sets scale used in split-merge
+  void set_split_merge_scale(SplitMergeScale sms) {_split_merge_scale = sms;}
+
+  /// indicate if the splittings are done using the anti-kt distance
+  bool split_merge_use_E_weighted_splitting() const {return _use_E_weighted_splitting;}
+  void set_split_merge_use_E_weighted_splitting(bool val) {
+    _use_E_weighted_splitting = val;}
+
+  /// overload the default as we don't provide support 
+  /// for passive areas.
+  virtual bool supports_ghosted_passive_areas() const {return true;}
+  
+  // the things that are required by base class
+  virtual std::string description () const;
+  virtual void run_clustering(ClusterSequence &) const ;
+
+protected:
+  virtual void reset_stored_plugin() const;
+
+private:
+  double _protojet_Emin;
+  SplitMergeScale _split_merge_scale;
+  bool _use_E_weighted_splitting;
+
+  // part needed for the cache 
+  // variables for caching the results and the input
+  static std::auto_ptr<SISConeSphericalPlugin        > stored_plugin;
+  static std::auto_ptr<std::vector<PseudoJet>        > stored_particles;
+  static std::auto_ptr<siscone_spherical::CSphsiscone> stored_siscone;
+};
+
+//======================================================================
+/// @ingroup extra_info
+/// \class SISConeSphericalExtras
+/// Class that provides extra information about a SISCone clustering
+class SISConeSphericalExtras : public SISConeBaseExtras {
+public:
+  /// constructor
+  //  it just initialises the pass information 
+  SISConeSphericalExtras(int nparticles)
+    : SISConeBaseExtras(nparticles){}
+
+  /// access to the siscone jet def plugin (more convenient than
+  /// getting it from the original jet definition, because here it's
+  /// directly of the right type (rather than the base type)
+  const SISConeSphericalPlugin* jet_def_plugin() const {
+    return dynamic_cast<const SISConeSphericalPlugin*>(_jet_def_plugin);
+  }
+
+private:
+  // let us be written to by SISConePlugin
+  friend class SISConeSphericalPlugin;
+};
+
+FASTJET_END_NAMESPACE        // defined in fastjet/internal/base.hh
+
+#endif // __SISCONEPLUGIN_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/geom_2d.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/geom_2d.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/geom_2d.cc	(revision 5)
@@ -0,0 +1,150 @@
+///////////////////////////////////////////////////////////////////////////////
+// File: geom_2d.cpp                                                         //
+// Description: source file for two-dimensional geometry tools               //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "geom_2d.h"
+#include <algorithm>
+
+namespace siscone{
+
+#define PHI_RANGE_MASK 0xFFFFFFFF
+
+/*********************************************************
+ * class Ceta_phi_range implementation                   *
+ * class for holding a covering range in eta-phi         *
+ *                                                       *
+ * This class deals with ranges in the eta-phi plane. It *
+ * implements methods to test if two ranges overlap and  *
+ * to take the union of two overlapping intervals.       *
+ *********************************************************/
+
+using namespace std;
+
+// static member default init
+//----------------------------
+double Ceta_phi_range::eta_min = -100.0;
+double Ceta_phi_range::eta_max = 100.0;
+
+// default ctor
+//--------------
+Ceta_phi_range::Ceta_phi_range(){
+  eta_range = 0;
+  phi_range = 0;
+}
+
+// ctor with initialisation
+// we initialise with a centre (in eta,phi) and a radius
+//  - c_eta   eta coordinate of the centre
+//  - c_phi   phi coordinate of the centre
+//  - R       radius
+//-------------------------------------------------------
+Ceta_phi_range::Ceta_phi_range(double c_eta, double c_phi, double R){
+  // determination of the eta range
+  //-------------------------------
+  double xmin = max(c_eta-R,eta_min+0.0001);
+  double xmax = min(c_eta+R,eta_max-0.0001);
+
+  unsigned int cell_min = get_eta_cell(xmin);
+  unsigned int cell_max = get_eta_cell(xmax);
+
+  // warning: if cell_max==2^31, 2*cell_max==0 hence, 
+  // even if the next formula is formally (2*cell_max-cell_min),
+  // expressing it as (cell_max-cell_min)+cell_max is safe.
+  eta_range = (cell_max-cell_min)+cell_max;
+
+  // determination of the phi range
+  // !! taking care of periodicity !!
+  //---------------------------------
+  xmin = phi_in_range(c_phi-R);
+  xmax = phi_in_range(c_phi+R);
+
+  cell_min = get_phi_cell(xmin);
+  cell_max = get_phi_cell(xmax);
+
+  // Also, if the interval goes through pi, inversion is needed
+  if (xmax>xmin)
+    phi_range = (cell_max-cell_min)+cell_max;
+  else {
+    phi_range = (cell_min==cell_max) 
+      ? PHI_RANGE_MASK
+      : ((PHI_RANGE_MASK^(cell_min-cell_max)) + cell_max);
+  }
+}
+
+// assignment of range
+//  - r   range to assign to current one
+//---------------------------------------
+Ceta_phi_range& Ceta_phi_range::operator = (const Ceta_phi_range &r){
+  eta_range = r.eta_range;
+  phi_range = r.phi_range;
+
+  return *this;
+}
+
+// add a particle to the range
+//  - eta  eta coordinate of the particle
+//  - phi  phi coordinate of the particle
+// \return 0 on success, 1 on error
+//----------------------------------------
+int Ceta_phi_range::add_particle(const double eta, const double phi){
+  // deal with the eta coordinate
+  eta_range |= get_eta_cell(eta);
+
+  // deal with the phi coordinate
+  phi_range |= get_phi_cell(phi);
+
+  return 0;
+}
+
+
+// test overlap
+//  - r1  first range
+//  - r2  second range
+// return true if overlap, false otherwise.
+//------------------------------------------
+bool is_range_overlap(const Ceta_phi_range &r1, const Ceta_phi_range &r2){
+  // check overlap in eta AND phi
+  return ((r1.eta_range & r2.eta_range) && (r1.phi_range & r2.phi_range));
+}
+
+// compute union
+// Note: we assume that the two intervals overlap
+//  - r1  first range
+//  - r2  second range
+// \return union of the two ranges
+//------------------------------------------
+const Ceta_phi_range range_union (const Ceta_phi_range &r1, const Ceta_phi_range &r2){
+  Ceta_phi_range tmp;
+
+  // compute union in eta
+  tmp.eta_range = r1.eta_range | r2.eta_range;
+
+  // compute union in phi
+  tmp.phi_range = r1.phi_range | r2.phi_range;
+
+  return tmp;
+}
+
+}
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/geom_2d.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/geom_2d.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/geom_2d.h	(revision 5)
@@ -0,0 +1,179 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: geom_2d.h                                                           //
+// Description: header file for two-dimensional geometry tools               //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __GEOM_2D_H__
+#define __GEOM_2D_H__
+
+#include <iostream>
+#include <math.h>
+#include "defines.h"
+
+#ifndef M_PI
+#define M_PI 3.141592653589793238462643383279502884197
+#endif
+
+namespace siscone{
+
+/// return a result that corresponds to phi, but in the
+/// range (-pi..pi]; the result is only correct if -3pi < phi <= 3pi
+inline double phi_in_range(double phi) {
+  if      (phi <= -M_PI) phi += twopi;
+  else if (phi >   M_PI) phi -= twopi;
+  return phi;
+}
+
+/// return the difference between the two phi values, 
+/// placed in the correct range (-pi..pi], , assuming that phi1,phi2
+/// are already in the correct range.
+inline double dphi(double phi1, double phi2) {
+  return phi_in_range(phi1-phi2);
+}
+
+
+/// return the absolute difference between the two phi values, 
+/// placed in the correct range, assuming that phi1,phi2 are already
+/// in the correct range.
+inline double abs_dphi(double phi1, double phi2) {
+  double delta = fabs(phi1-phi2);
+  return delta > M_PI ? twopi-delta : delta;
+}
+
+/// return the square of the argument
+inline double pow2(double x) {return x*x;}
+
+
+/** 
+ * \class Ctwovect
+ * \brief class for holding a two-vector
+ */
+class Ctwovect {
+public:
+  /// default ctor
+  Ctwovect() : x(0.0), y(0.0) {}
+
+  /// ctor with initialisation
+  /// \param _x   first coordinate
+  /// \param _y   second coordinate
+  Ctwovect(double _x, double _y) : x(_x), y(_y) {}
+
+  /// vector coordinates
+  double x, y;
+
+  /// norm (modulud square) of the vector
+  inline double mod2() const {return pow2(x)+pow2(y);}
+
+  /// modulus of the vector
+  inline double modulus() const {return sqrt(mod2());}
+};
+
+
+/// dot product of two 2-vectors
+/// \param a   first 2-vect
+/// \param b   second 2-vect
+/// \return a.b is returned
+inline double dot_product(const Ctwovect & a, const Ctwovect & b) {
+  return a.x*b.x + a.y*b.y;
+}
+
+
+/// cross product of two 2-vectors
+/// \param a   first 2-vect
+/// \param b   second 2-vect
+/// \return a x b is returned
+inline double cross_product(const Ctwovect & a, const Ctwovect & b) {
+  return a.x*b.y - a.y*b.x;
+}
+
+
+/** 
+ * \class Ceta_phi_range
+ * \brief class for holding a covering range in eta-phi
+ *
+ * This class deals with ranges in the eta-phi plane. It
+ * implements methods to test if two ranges overlap and
+ * to take the union of two overlapping intervals.
+ */
+class Ceta_phi_range{
+public:
+  /// default ctor
+  Ceta_phi_range();
+
+  /// ctor with initialisation
+  /// we initialise with a centre (in eta,phi) and a radius
+  /// \param c_eta   eta coordinate of the centre
+  /// \param c_phi   phi coordinate of the centre
+  /// \param R       radius
+  Ceta_phi_range(double c_eta, double c_phi, double R);
+
+  /// assignment of range
+  /// \param r   range to assign to current one
+  Ceta_phi_range& operator = (const Ceta_phi_range &r);
+
+  /// add a particle to the range
+  /// \param eta  eta coordinate of the particle
+  /// \param phi  phi coordinate of the particle
+  /// \return 0 on success, 1 on error
+  int add_particle(const double eta, const double phi);
+
+  /// eta range as a binary coding of covered cells
+  unsigned int eta_range;     
+
+  /// phi range as a binary coding of covered cells
+  unsigned int phi_range;     
+
+  // extremal value for eta
+  static double eta_min;  ///< minimal value for eta
+  static double eta_max;  ///< maximal value for eta
+
+private:
+  /// return the cell index corrsponding to an eta value
+  inline unsigned int get_eta_cell(double eta){
+    return (unsigned int) (1 << ((int) (32*((eta-eta_min)/(eta_max-eta_min)))));
+  }
+
+  /// return the cell index corrsponding to a phi value
+  inline unsigned int get_phi_cell(double phi){
+    return (unsigned int) (1 << ((int) (32*phi/twopi+16)%32));
+  }
+};
+
+/// test overlap
+/// \param  r1  first range
+/// \param  r2  second range
+/// \return true if overlap, false otherwise.
+bool is_range_overlap(const Ceta_phi_range &r1, const Ceta_phi_range &r2);
+
+/// compute union
+/// Note: we assume that the two intervals overlap
+/// \param  r1  first range
+/// \param  r2  second range
+/// \return union of the two ranges
+const Ceta_phi_range range_union(const Ceta_phi_range &r1, const Ceta_phi_range &r2);
+
+}
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/hash.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/hash.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/hash.cc	(revision 5)
@@ -0,0 +1,230 @@
+///////////////////////////////////////////////////////////////////////////////
+// File: hash.cpp                                                            //
+// Description: source file for classes hash_element and hash_cones          //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <math.h>
+#include <stdio.h>
+#include "hash.h"
+#include <iostream>
+
+namespace siscone{
+
+using namespace std;
+
+/**************************************************************
+ * implementation of hash_cones                               *
+ * list of cones candidates.                                  *
+ * We store in this class all the hash_elements and give      *
+ * functions to manipulate them.                              *
+ **************************************************************/
+
+// constructor with initialisation
+//  - _Np  number of particles
+//  - _R2  cone radius (squared)
+//-----------------------------------
+hash_cones::hash_cones(int _Np, double _R2){
+  int i;
+
+  n_cones = 0;
+#ifdef DEBUG_STABLE_CONES
+  n_occupied_cells = 0;
+#endif
+
+  // determine hash size
+  // for a ymax=5 and R=0.7, we observed an occupancy around 1/8 N^2 ~ N2 R2/4
+  //mask = 1 << (int) (2*log(double(_Np))/log(2.0));
+  //if (mask<=1) mask=2;
+  int nbits = (int) (log(_Np*_R2*_Np/4.0)/log(2.0));
+  if (nbits<1) nbits=1;
+  mask = 1 << nbits;
+
+  // create hash
+  hash_array = new hash_element*[mask];
+  mask--;
+
+  // set the array to 0
+  //? needed ?
+  for (i=0;i<mask+1;i++)
+    hash_array[i] = NULL;
+
+  R2 = _R2;
+}
+
+// destructor
+//------------
+hash_cones::~hash_cones(){
+  int i;
+  hash_element *elm;
+
+  for (i=0;i<mask+1;i++){
+    while (hash_array[i]!=NULL){
+      elm = hash_array[i];
+      hash_array[i] = hash_array[i]->next;
+      delete elm;
+    }
+  }
+
+  delete[] hash_array;
+}
+
+
+/*
+ * insert a new candidate into the hash.
+ *  - v       4-momentum of the cone to add
+ *  - parent  parent particle defining the cone
+ *  - child   child particle defining the cone
+ *  - p_io    whether the parent has to belong to the cone or not
+ *  - c_io    whether the child has to belong to the cone or not
+ * return 0 on success, 1 on error
+ ***********************************************************************/
+int hash_cones::insert(Cmomentum *v, Cmomentum *parent, Cmomentum *child, bool p_io, bool c_io){
+  hash_element *elm;
+  int index = (v->ref.ref[0]) & mask;
+
+  // check the array cell corresponding to our reference
+  elm = hash_array[index];
+
+#ifdef DEBUG_STABLE_CONES
+  if (elm==NULL)
+    n_occupied_cells++;
+#endif
+
+  do{
+    // if it is not present, add it
+    if (elm==NULL){
+      // create element
+      elm = new hash_element;
+
+      // set its varibles
+      // Note: at this level, eta and phi have already been computed
+      //       through Cmomentum::build_etaphi.
+      elm->ref = v->ref;
+      
+      //compute vectors centre
+      v->build_etaphi();
+      elm->eta = v->eta;
+      elm->phi = v->phi;
+      // if at least one of the two is_inside tests gives a result != from the expected,
+      // the || will be true hence !(...) false as wanted
+      elm->is_stable = !((is_inside(v, parent)^p_io)||(is_inside(v, child)^c_io));
+      //cout << "-- new status of " <<  v->ref[0] << ":" << elm->is_stable << endl;
+
+      // update hash
+      elm->next = hash_array[index];
+      hash_array[index] = elm;
+      
+      n_cones++;
+      return 0;
+    }
+
+    // if the cone is already there, simply update stability status
+    if (v->ref == elm->ref){
+      // there is only an update to perform to see if the cone is still stable
+      if (elm->is_stable){
+	v->build_etaphi();
+	elm->is_stable = !((is_inside(v, parent)^p_io)||(is_inside(v, child)^c_io));
+        //cout << " parent/child: " 
+        //     << parent->ref[0] << ":" << is_inside(v, parent) << ":" << p_io << " "
+        //     << child->ref[0] << ":" << is_inside(v, child) << ":" << c_io << endl;
+        //cout << "-- rep status of " <<  v->ref[0] << ":" << elm->is_stable << endl;
+        //cout << v->eta << " " << v->phi << endl;
+        //cout << (child->eta) << " " << child->phi << endl;
+      }
+      return 0;
+    }
+
+    elm = elm->next;
+  } while (1);
+
+  return 1;
+}
+
+/*
+ * insert a new candidate into the hash.
+ *  - v       4-momentum of te cone to add
+ * Note, in this case, we assume stability. We also assume
+ * that eta and phi are computed for v
+ * return 0 on success, 1 on error
+ ***********************************************************************/
+int hash_cones::insert(Cmomentum *v){
+  hash_element *elm;
+  int index = (v->ref.ref[0]) & mask;
+  //cout << "-- stable candidate: " << v->ref[0] << ":" << endl;
+
+  // check the array cell corresponding to our reference
+  elm = hash_array[index];
+  do{
+    // if it is not present, add it
+    if (elm==NULL){
+      // create element
+      elm = new hash_element;
+
+      // set its varibles
+      // Note: at this level, eta and phi have already been computed
+      //       through Cmomentum::build_etaphi.
+      elm->ref = v->ref;
+      elm->eta = v->eta;
+      elm->phi = v->phi;
+      elm->is_stable = true;
+
+      // update hash
+      elm->next = hash_array[index];
+      hash_array[index] = elm;
+      
+      n_cones++;
+      return 0;
+    }
+
+    // if the cone is already there, we have nothing to do
+    if (v->ref == elm->ref){
+      return 0;
+    }
+
+    elm = elm->next;
+  } while (1);
+
+  return 1;
+}
+
+/*
+ * test if a particle is inside a cone of given centre.
+ * check if the particle of coordinates 'v' is inside the circle of radius R 
+ * centered at 'centre'.
+ *  - centre   centre of the circle
+ *  - v        particle to test
+ * return true if inside, false if outside
+ ******************************************************************************/
+inline bool hash_cones::is_inside(Cmomentum *centre, Cmomentum *v){
+  double dx, dy;
+
+  dx = centre->eta - v->eta;
+  dy = fabs(centre->phi - v->phi);
+  if (dy>M_PI) 
+    dy -= 2.0*M_PI;
+      
+  return dx*dx+dy*dy<R2;
+}
+
+}
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/hash.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/hash.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/hash.h	(revision 5)
@@ -0,0 +1,122 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: hash.h                                                              //
+// Description: header file for classes hash_element and hash_cones          //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __HASH_H__
+#define __HASH_H__
+
+#include "momentum.h"
+#include "reference.h"
+
+namespace siscone{
+
+/**
+ * \class hash_element
+ * information on store cones candidates.
+ *
+ * We store in this class the information used to count all 
+ * protocones in a first pass. This first pass only count
+ * cones with different references and test their stbility
+ * with the parent-child particles (border particles).
+ */
+class hash_element{
+ public:
+  Creference ref;      ///< reference
+  double eta;          ///< centre: eta coordinate
+  double phi;          ///< centre: phi coordinate
+  bool is_stable;      ///< true if stable w.r.t. "border particles"
+
+  hash_element *next;  ///< pointer to the next element
+};
+
+/**
+ * \class hash_cones
+ * list of cones candidates.
+ *
+ * We store in this class all the hash_elements and give
+ * functions to manipulate them.
+ */
+class hash_cones{
+ public:
+  /// constructor with initialisation
+  /// \param _Np  number of particles
+  /// \param _R2  cone radius (squared)
+  hash_cones(int _Np, double _R2);
+
+  /// destructor
+  ~hash_cones();
+
+  /**
+   * insert a new candidate into the hash.
+   * \param v       4-momentum of te cone to add
+   * \param parent  parent particle defining the cone
+   * \param child   child particle defining the cone
+   * \param p_io    whether the parent has to belong to the cone or not
+   * \param c_io    whether the child has to belong to the cone or not
+   * \return 0 on success, 1 on error
+   */
+  int insert(Cmomentum *v, Cmomentum *parent, Cmomentum *child, bool p_io, bool c_io);
+
+  /**
+   * insert a new candidate into the hash.
+   * \param v       4-momentum of te cone to add
+   * Note, in this case, we assume stability. We also assume
+   * that eta and phi are computed for v
+   * \return 0 on success, 1 on error
+   */
+  int insert(Cmomentum *v);
+
+  /// the cone data itself
+  hash_element **hash_array;
+
+  /// number of elements
+  int n_cones;
+
+  /// number of occupied cells
+#ifdef DEBUG_STABLE_CONES
+  int n_occupied_cells;
+#endif
+
+  /// number of cells-1
+  int mask;
+
+  /// circle radius (squared)
+  /// NOTE: need to be set before any call to 'insert'
+  double R2;
+
+  /**
+   * test if a particle is inside a cone of given centre.
+   * check if the particle of coordinates 'v' is inside the circle of radius R 
+   * centered at 'centre'.
+   * \param centre   centre of the circle
+   * \param v        particle to test
+   * \return true if inside, false if outside
+   */
+  inline bool is_inside(Cmomentum *centre, Cmomentum *v);
+};
+
+}
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/momentum.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/momentum.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/momentum.cc	(revision 5)
@@ -0,0 +1,161 @@
+///////////////////////////////////////////////////////////////////////////////
+// File: momentum.cpp                                                        //
+// Description: source file for 4-momentum class Cmomentum                   //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "momentum.h"
+#include <math.h>
+#include <stdlib.h>
+
+namespace siscone{
+
+/*************************************************************************
+ * class Cmomentum                                                       *
+ * This class contains the information for particle or group of          *
+ * particles management.                                                 *
+ * It includes all Lorentz properties as well as tools for summing them. *
+ *************************************************************************/
+ 
+// default ctor
+//--------------
+Cmomentum::Cmomentum(){
+  eta = 0.0;
+  phi = 0.0;
+  px = py = pz = E = 0.0;
+  ref = Creference();
+  index = -1;
+}
+
+// ctor with initialisation
+//--------------------------
+Cmomentum::Cmomentum(double _px, double _py, double _pz, double _E){
+  px = _px;
+  py = _py;
+  pz = _pz;
+  E  = _E;
+
+  // compute eta and phi
+  build_etaphi();
+  ref = Creference();
+}
+
+// ctor with detailed initialisation
+//-----------------------------------
+Cmomentum::Cmomentum(double _eta, double _phi, Creference _ref){
+  eta = _eta;
+  phi = _phi;
+
+  ref = _ref;
+}
+
+// default dtor
+//--------------
+Cmomentum::~Cmomentum(){
+
+}
+
+// assignment of vectors
+//-----------------------
+Cmomentum& Cmomentum::operator = (const Cmomentum &v){
+  px = v.px;
+  py = v.py;
+  pz = v.pz;
+  E  = v.E;
+
+  eta = v.eta;
+  phi = v.phi;
+
+  ref = v.ref;
+  return *this;
+}
+
+// addition of vectors
+// !!! WARNING !!! no updating of eta and phi !!!
+//------------------------------------------------
+const Cmomentum Cmomentum::operator + (const Cmomentum &v){
+  Cmomentum tmp = *this;
+  return tmp+=v;
+}
+
+// incrementation of vectors
+// !!! WARNING !!! no updating of eta and phi !!!
+//------------------------------------------------
+Cmomentum& Cmomentum::operator += (const Cmomentum &v){
+  px+=v.px;
+  py+=v.py;
+  pz+=v.pz;
+  E +=v.E;
+
+  ref+=v.ref;
+
+  return *this;
+}
+
+// incrementation of vectors
+// !!! WARNING !!! no updating of eta and phi !!!
+//------------------------------------------------
+Cmomentum& Cmomentum::operator -= (const Cmomentum &v){
+  px-=v.px;
+  py-=v.py;
+  pz-=v.pz;
+  E -=v.E;
+
+  ref-=v.ref;
+  return *this;
+}
+
+// build eta-phi from 4-momentum info
+// !!!                WARNING                   !!!
+// !!! computing eta and phi is time-consuming  !!!
+// !!! use this whenever you need eta or phi    !!!
+// !!! automatically called for single-particle !!!
+//--------------------------------------------------
+void Cmomentum::build_etaphi(){
+  // note: the factor n (ref.nb) cancels in all expressions !!
+  eta = 0.5*log((E+pz)/(E-pz));
+  phi = atan2(py,px);
+}
+
+
+// ordering of two vectors
+// the default ordering is w.r.t. their references
+//-------------------------------------------------
+bool operator < (const Cmomentum &v1, const Cmomentum &v2){
+  return v1.ref < v2.ref;
+}
+
+// ordering of vectors in eta (e.g. used in collinear tests)
+//-----------------------------------------------------------
+bool momentum_eta_less(const Cmomentum &v1, const Cmomentum &v2){
+  return v1.eta < v2.eta;
+}
+
+// ordering of vectors in pt
+//---------------------------
+bool momentum_pt_less(const Cmomentum &v1, const Cmomentum &v2){
+  return v1.perp2() < v2.perp2();
+}
+
+}
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/momentum.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/momentum.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/momentum.h	(revision 5)
@@ -0,0 +1,157 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: momentum.h                                                          //
+// Description: header file for 4-momentum class Cmomentum                   //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __VECTOR_H__
+#define __VECTOR_H__
+
+#include <vector>
+#include <math.h>
+#include "reference.h"
+#include "geom_2d.h"
+#include "defines.h"
+
+namespace siscone{
+
+/**
+ * \class Cmomentum
+ * \brief base class for dynamic coordinates management
+ *
+ * This class contains the information for particle or group of
+ * particles management.
+ * It includes all Lorentz properties as well as tools for summing them.
+ * Note: 'sums' over phi angles are indeed averages. This allows to
+ *       deal with periodicity at each step
+ */
+class Cmomentum{
+ public:
+  /// default ctor
+  Cmomentum();
+
+  /// ctor with initialisation
+  Cmomentum(double _px, double _py, double _pz, double _E);
+
+  /// ctor with detailed initialisation
+  Cmomentum(double _eta, double _phi, Creference _ref);
+
+  /// default dtor
+  ~Cmomentum();
+
+  /// computes pT
+  inline double perp() const {return sqrt(perp2());}
+
+  /// computes pT^2
+  inline double perp2() const {return px*px+py*py;}
+
+  /// computes m
+  inline double mass() const {return sqrt(mass2());}
+
+  /// computes m^2
+  inline double mass2() const {return perpmass2()-perp2();}
+
+  /// transverse mass, mt = sqrt(pt^2+m^2) = sqrt(E^2 - pz^2)
+  inline double perpmass() const {return sqrt((E-pz)*(E+pz));}
+
+  /// transverse mass squared, mt^2 = pt^2+m^2 = E^2 - pz^2
+  inline double perpmass2() const {return (E-pz)*(E+pz);}
+
+  /// computes transverse energy
+  inline double Et() const {return E/sqrt(1.0+pz*pz/perp2());}
+
+  /// computes transverse energy (squared)
+  inline double Et2() const {return E*E/(1.0+pz*pz/perp2());}
+
+  /// assignment of vectors
+  Cmomentum& operator = (const Cmomentum &v);
+
+  /// addition of vectors
+  /// !!! WARNING !!! no updating of eta and phi !!!
+  const Cmomentum operator + (const Cmomentum &v);
+
+  /// incrementation of vectors
+  /// !!! WARNING !!! no updating of eta and phi !!!
+  Cmomentum& operator += (const Cmomentum &v);
+
+  /// decrementation of vectors
+  /// !!! WARNING !!! no updating of eta and phi !!!
+  Cmomentum& operator -= (const Cmomentum &v);
+
+  /// build eta-phi from 4-momentum info
+  /// !!!                WARNING                   !!!
+  /// !!! computing eta and phi is time-consuming  !!!
+  /// !!! use this whenever you need eta or phi    !!!
+  /// !!! automatically called for single-particle !!!
+  void build_etaphi();
+
+  double px;        ///< x-momentum
+  double py;        ///< y-momentum
+  double pz;        ///< z-momentum
+  double E;         ///< energy
+
+  double eta;       ///< particle pseudo-rapidity 
+  double phi;       ///< particle azimuthal angle
+  int parent_index; ///< particle number in the parent list
+  int index;        ///< internal particle number
+
+  //////////////////////////////////////////////
+  // the following part is used for checksums //
+  //////////////////////////////////////////////
+  Creference ref;   ///< reference number for the vector
+};
+
+/// ordering of two vectors
+/// this is by default done w.r.t. their references
+bool operator < (const Cmomentum &v1, const Cmomentum &v2);
+
+/// ordering of vectors in eta (e.g. used in collinear tests)
+bool momentum_eta_less(const Cmomentum &v1, const Cmomentum &v2);
+
+/// ordering of vectors in pt
+bool momentum_pt_less(const Cmomentum &v1, const Cmomentum &v2);
+
+
+//////////////////////////
+// some handy utilities //
+//////////////////////////
+
+/// get distance between to eta-phi points
+/// \param eta  eta coordinate of first point
+/// \param phi  phi coordinate of first point
+/// \param v    vector defining the second point
+inline double get_distance(double eta, double phi, Cmomentum *v){
+  double dx, dy;
+
+  dx = eta - v->eta;
+  dy = fabs(phi - v->phi);
+  if (dy>M_PI) 
+    dy -= twopi;
+
+  return dx*dx+dy*dy;
+}
+
+}
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/protocones.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/protocones.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/protocones.cc	(revision 5)
@@ -0,0 +1,849 @@
+///////////////////////////////////////////////////////////////////////////////
+// File: protocones.cpp                                                      //
+// Description: source file for stable cones determination (Cstable_cones)   //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+/*******************************************************
+ * Introductory note:                                  *
+ * Since this file has many member functions, we have  *
+ * structured them in categories:		       *
+ * INITIALISATION FUNCTIONS                            *
+ *  - ctor()                                           *
+ *  - ctor(particle_list)                              *
+ *  - dtor()                                           *
+ *  - init(particle_list)                              *
+ * ALGORITHM MAIN ENTRY                                *
+ *  - get_stable_cone(radius)                          *
+ * ALGORITHM MAIN STEPS                                *
+ *  - init_cone()                                      *
+ *  - test_cone()                                      *
+ *  - update_cone()                                    *
+ *  - proceed_with_stability()                         *
+ * ALGORITHM MAIN STEPS FOR COCIRCULAR SITUATIONS      *
+ *  - cocircular_pt_less(v1, v2)                       *
+ *  - prepare_cocircular_list()                        *
+ *  - test_cone_cocircular()                           *
+ *  - test_stability(candidate, border_list)           *
+ *  - updat_cone_cocircular()                          *
+ * RECOMPUTATION OF CONE CONTENTS                      *
+ *  - compute_cone_contents()                          *
+ *  - recompute_cone_contents()                        *
+ *  - recompute_cone_contents_if_needed()              *
+ * VARIOUS TOOLS                                       *
+ *  - circle_intersect()                               *
+ *  - is_inside()                                      *
+ *  - abs_dangle()                                     *
+ *******************************************************/
+
+#include "protocones.h"
+#include "siscone_error.h"
+#include "defines.h"
+#include <math.h>
+#include <iostream>
+#include "circulator.h"
+#include <algorithm>
+
+namespace siscone{
+
+using namespace std;
+
+/**********************************************************************
+ * Cstable_cones implementation                                       *
+ * Computes the list of stable comes from a particle list.            *
+ * This class does the first fundamental task of te cone algorithm:   *
+ * it is used to compute the list of stable cones given a list        *
+ * of particles.                                                      *
+ **********************************************************************/
+
+////////////////////////////////////////////////////////
+// INITIALISATION FUNCTIONS                           //
+//  - ctor()                                          //
+//  - ctor(particle_list)                             //
+//  - dtor()                                          //
+//  - init(particle_list)                             //
+////////////////////////////////////////////////////////
+
+// default ctor
+//--------------
+Cstable_cones::Cstable_cones(){
+  nb_tot = 0;
+  hc = NULL;
+}
+
+// ctor with initialisation
+//--------------------------
+Cstable_cones::Cstable_cones(vector<Cmomentum> &_particle_list)
+  : Cvicinity(_particle_list){
+
+  nb_tot = 0;
+  hc = NULL;
+}
+
+// default dtor
+//--------------
+Cstable_cones::~Cstable_cones(){
+  if (hc!=NULL) delete hc;
+}
+
+/*
+ * initialisation
+ *  - _particle_list  list of particles
+ *  - _n              number of particles
+ *********************************************************************/
+void Cstable_cones::init(vector<Cmomentum> &_particle_list){
+  // check already allocated mem
+  if (hc!=NULL){
+    delete hc;
+  }
+  if (protocones.size()!=0)
+    protocones.clear();
+
+  multiple_centre_done.clear();
+
+  // initialisation
+  set_particle_list(_particle_list);
+}
+
+
+////////////////////////////////////////////////////////
+// ALGORITHM MAIN ENTRY                               //
+//  - get_stable_cone(radius)                         //
+////////////////////////////////////////////////////////
+
+/*
+ * compute stable cones.
+ * This function really does the job i.e. computes
+ * the list of stable cones (in a seedless way)
+ *  - _radius:  radius of the cones
+ * The number of stable cones found is returned
+ *********************************************************************/
+int Cstable_cones::get_stable_cones(double _radius){
+  int p_idx;
+
+  // check if everything is correctly initialised
+  if (n_part==0){
+    return 0;
+  }
+
+  R  = _radius;
+  R2 = R*R;
+
+  // allow hash for cones candidates
+  hc = new hash_cones(n_part, R2);
+
+  // browse all particles
+  for (p_idx=0;p_idx<n_part;p_idx++){
+    // step 0: compute the child list CL.
+    //         Note that this automatically sets the parent P
+    build(&plist[p_idx], 2.0*R);
+
+    // special case: 
+    //   if the vicinity is empty, the parent particle is a 
+    //   stable cone by itself. Add it to protocones list.
+    if (vicinity_size==0){
+      protocones.push_back(*parent);
+      continue;
+    }
+
+    // step 1: initialise with the first cone candidate
+    init_cone();
+
+    do{
+      // step 2: test cone stability for that pair (P,C)
+      test_cone();
+
+      // step 3: go to the next cone child candidate C
+    } while (!update_cone());
+  }
+
+  return proceed_with_stability();
+}
+
+
+////////////////////////////////////////////////////////
+// ALGORITHM MAIN STEPS                               //
+//  - init_cone()                                     //
+//  - test_cone()                                     //
+//  - update_cone()                                   //
+//  - proceed_with_stability()                        //
+////////////////////////////////////////////////////////
+
+/*
+ * initialise the cone.
+ * We take the first particle in the angular ordering to compute 
+ * this one
+ * return 0 on success, 1 on error
+ *********************************************************************/
+int Cstable_cones::init_cone(){
+  // The previous version of the algorithm was starting the 
+  // loop around vicinity elements with the "most isolated" child.
+  // given the nodist method to calculate the cone contents, we no
+  // longer need to worry about which cone comes first...
+  first_cone=0;
+
+  // now make sure we have lists of the cocircular particles
+  prepare_cocircular_lists();
+
+  //TODO? deal with a configuration with only degeneracies ? 
+  // The only possibility seems a regular hexagon with a parent point
+  // in the centre. And this situation is by itself unclear.
+  // Hence, we do nothing here !
+
+  // init set child C
+  centre = vicinity[first_cone];
+  child = centre->v;
+  centre_idx = first_cone;
+
+  // build the initial cone (nodist: avoids calculating distances --
+  // just deduces contents by circulating around all in/out operations)
+  // this function also sets the list of included particles
+  compute_cone_contents();
+  
+  return 0;
+}
+
+
+/*
+ * test cones.
+ * We check if the cone(s) built with the present parent and child 
+ * are stable
+ * return 0 on success 1 on error
+ *********************************************************************/
+int Cstable_cones::test_cone(){
+  Creference weighted_cone_ref;
+  
+  // depending on the side we are taking the child particle,
+  // we test different configuration.
+  // Each time, two configurations are tested in such a way that
+  // all 4 possible cases (parent or child in or out the cone)
+  // are tested when taking the pair of particle parent+child
+  // and child+parent.
+
+  // here are the tests entering the first series:
+  //  1. check if the cone is already inserted
+  //  2. check cone stability for the parent and child particles
+  
+  if (centre->side){
+    // test when both particles are not in the cone
+    // or when both are in.
+    // Note: for the totally exclusive case, test emptyness before
+    cone_candidate = cone;
+    if (cone.ref.not_empty()){
+      hc->insert(&cone_candidate, parent, child, false, false);
+    }
+
+    cone_candidate = cone;
+    cone_candidate+= *parent + *child;
+    hc->insert(&cone_candidate, parent, child, true, true);
+  } else {
+    // test when 1! of the particles is in the cone
+    cone_candidate = cone + *parent;
+    hc->insert(&cone_candidate, parent, child, true, false);
+
+    cone_candidate = cone + *child;
+    hc->insert(&cone_candidate, parent, child, false, true);
+  }
+
+  nb_tot+=2;
+
+  return 0;
+}
+
+
+/*
+ * update the cone
+ * go to the next child for that parent and update 'cone' appropriately
+ * return 0 if update candidate found, 1 otherwise
+ ***********************************************************************/
+int Cstable_cones::update_cone(){
+  // get the next child and centre
+  centre_idx++;
+  if (centre_idx==vicinity_size)
+    centre_idx=0;
+  if (centre_idx==first_cone)
+    return 1;
+
+  // update the cone w.r.t. the old child
+  // only required if the old child is entering inside in which
+  // case we need to add it. We also know that the child is 
+  // inside iff its side is -.
+  if (!centre->side){
+    // update cone
+    cone += (*child);
+
+    // update info on particles inside
+    centre->is_inside->cone = true;
+
+    // update stability check quantities
+    dpt += fabs(child->px)+fabs(child->py);
+  }
+
+  // update centre and child to correspond to the new position
+  centre = vicinity[centre_idx];
+  child = centre->v;
+
+  // check cocircularity
+  // note that if cocirculaity is detected (i.e. if we receive 1
+  // in the next test), we need to recall 'update_cone' directly
+  // since tests and remaining part of te update has been performed
+  //if (cocircular_check())
+  if (cocircular_check())
+    return update_cone();
+
+
+  // update the cone w.r.t. the new child
+  // only required if the new child was already inside in which
+  // case we need to remove it. We also know that the child is 
+  // inside iff its side is +.
+  if ((centre->side) && (cone.ref.not_empty())){
+    // update cone
+    cone -= (*child);
+
+    // update info on particles inside
+    centre->is_inside->cone = false;
+
+    // update stability check quantities
+    dpt += fabs(child->px)+fabs(child->py); //child->perp2();
+  }
+
+  // check that the addition and subtraction of vectors does
+  // not lead to too much rounding error
+  // for that, we compute the sum of pt modifications and of |pt|
+  // since last recomputation and once the ratio overpasses a threshold
+  // we recompute vicinity.
+  if ((dpt>PT_TSHOLD*(fabs(cone.px)+fabs(cone.py))) && (cone.ref.not_empty())){
+    recompute_cone_contents();
+  }
+  if (cone.ref.is_empty()){
+    cone = Cmomentum();
+    dpt=0.0;
+  }
+
+  return 0; 
+}
+
+
+/*
+ * compute stability of all enumerated candidates.
+ * For all candidate cones which are stable w.r.t. their border particles,
+ * pass the last test: stability with quadtree intersection
+ ************************************************************************/
+int Cstable_cones::proceed_with_stability(){
+  int i; // ,n;
+  hash_element *elm;
+
+  //n=0;
+  for (i=0;i<=hc->mask;i++){
+    // test ith cell of the hash array
+    elm = hc->hash_array[i];
+
+    // browse elements therein
+    while (elm!=NULL){
+      // test stability
+      if (elm->is_stable){
+	// stability is not ensured by all pairs of "edges" already browsed
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+	//  => testing stability with quadtree intersection
+	if (quadtree->circle_intersect(elm->eta, elm->phi, R2)==elm->ref){
+#else
+	//  => testing stability with the particle-list intersection
+	if (circle_intersect(elm->eta, elm->phi)==elm->ref){
+#endif
+	  // add it to the list of protocones
+	  // note that in its present form, we do not allocate the 
+	  // 4-vector components of the momentum. There's no need to
+	  // do it here as it will be recomputed in
+	  //   Csplit_merge::add_protocones
+	  protocones.push_back(Cmomentum(elm->eta, elm->phi, elm->ref));
+	}
+      }
+      
+      // jump to the next one
+      elm = elm->next;
+    }
+  }
+  
+  // free hash
+  // we do that at this level because hash eats rather a lot of memory
+  // we want to free it before running the split/merge algorithm
+#ifdef DEBUG_STABLE_CONES
+  nb_hash_cones = hc->n_cones;
+  nb_hash_occupied = hc->n_occupied_cells;
+#endif
+
+  delete hc;
+  hc=NULL;
+
+  return protocones.size();
+}
+
+
+////////////////////////////////////////////////////////
+// ALGORITHM MAIN STEPS FOR COCIRCULAR SITUATIONS     //
+//  - cocircular_pt_less(v1, v2)                      //
+//  - prepare_cocircular_list()                       //
+//  - test_cone_cocircular()                          //
+//  - test_stability(candidate, border_vect)          //
+//  - updat_cone_cocircular()                         //
+////////////////////////////////////////////////////////
+
+/// pt-ordering of momenta used for the cocircular case
+bool cocircular_pt_less(Cmomentum *v1, Cmomentum *v2){
+  return v1->perp2() < v2->perp2();
+}
+
+/*
+ * run through the vicinity of the current parent and for each child
+ * establish which other members are cocircular... Note that the list
+ * associated with each child contains references to vicinity
+ * elements: thus two vicinity elements each associated with one given
+ * particle may appear in a list -- this needs to be watched out for
+ * later on... 
+ **********************************************************************/
+void Cstable_cones::prepare_cocircular_lists() {
+  circulator<vector<Cvicinity_elm*>::iterator > here(vicinity.begin(), 
+                                                     vicinity.begin(), 
+                                                     vicinity.end());
+
+  circulator<vector<Cvicinity_elm*>::iterator > search(here);
+
+  do {
+    Cvicinity_elm* here_pntr = *here();
+    search.set_position(here);
+
+    // search forwards for things that should have "here" included in
+    // their cocircularity list
+    while (true) {
+      ++search;
+      if ( abs_dphi((*search())->angle, here_pntr->angle) < 
+                                 here_pntr->cocircular_range 
+           && search() != here()) {
+        (*search())->cocircular.push_back(here_pntr);
+      } else {
+        break;
+      }
+    }
+
+    // search backwards
+    search.set_position(here);
+    while (true) {
+      --search;
+      if ( abs_dphi((*search())->angle, here_pntr->angle) < 
+                                 here_pntr->cocircular_range 
+           && search() != here()) {
+        (*search())->cocircular.push_back(here_pntr);
+      } else {
+        break;
+      }
+    }
+
+    ++here;
+  } while (here() != vicinity.begin());
+
+}
+
+/* 
+ * Testing cocircular configurations in p^3 time,
+ * rather than 2^p time; we will test all contiguous subsets of points
+ * on the border --- note that this is till probably overkill, since
+ * in principle we only have to test situations where up to a
+ * half-circle is filled (but going to a full circle is simpler)
+ ******************************************************************/
+void Cstable_cones::test_cone_cocircular(Cmomentum & borderless_cone,
+					 list<Cmomentum *> & border_list) {
+  vector<Cborder_store> border_vect;
+
+  border_vect.reserve(border_list.size());
+  for (list<Cmomentum *>::iterator it = border_list.begin();
+       it != border_list.end(); it++) {
+    border_vect.push_back(Cborder_store(*it, centre->eta, centre->phi));
+  }
+
+  // get them into order of angle
+  sort(border_vect.begin(), border_vect.end());
+
+  // set up some circulators, since these will help us go around the
+  // circle easily
+  circulator<vector<Cborder_store>::iterator > 
+    start(border_vect.begin(), border_vect.begin(),border_vect.end());
+  circulator<vector<Cborder_store>::iterator > mid(start), end(start);
+  
+  // test the borderless cone
+  Cmomentum candidate = borderless_cone;
+  candidate.build_etaphi();
+  if (candidate.ref.not_empty())
+    test_stability(candidate, border_vect);
+
+  do {
+    // reset status wrt inclusion in the cone
+    mid = start;
+    do {
+      mid()->is_in = false;
+    } while (++mid != start);
+
+    // now run over all inclusion possibilities with this starting point
+    candidate = borderless_cone;
+    while (++mid != start) { 
+      // will begin with start+1 and go up to start-1
+      mid()->is_in = true;
+      candidate += *(mid()->mom);
+      test_stability(candidate, border_vect);
+    }
+
+  } while (++start != end);
+
+  // mid corresponds to momentum that we need to include to get the
+  // full cone
+  mid()->is_in = true;
+  candidate += *(mid()->mom);
+  test_stability(candidate, border_vect);
+}
+
+
+/**
+ * carry out the computations needed for the stability check of the
+ * candidate, using the border_vect to indicate which particles
+ * should / should not be in the stable cone; if the cone is stable
+ * insert it into the hash.
+ **********************************************************************/
+void Cstable_cones::test_stability(Cmomentum & candidate, const vector<Cborder_store> & border_vect) {
+  
+  // this almost certainly has not been done...
+  candidate.build_etaphi();
+
+  bool stable = true;
+  for (unsigned i = 0; i < border_vect.size(); i++) {
+    if (is_inside(&candidate, border_vect[i].mom) ^ (border_vect[i].is_in)) {
+      stable = false;
+      break; // it's unstable so there's no point continuing
+    }
+  }
+
+  if (stable) hc->insert(&candidate);
+}
+
+/*
+ * check if we are in a situation of cocircularity.
+ * if it is the case, update and test in the corresponding way
+ * return 'false' if no cocircularity detected, 'true' otherwise
+ * Note that if cocircularity is detected, we need to 
+ * recall 'update' from 'update' !!!
+ ***************************************************************/
+bool Cstable_cones::cocircular_check(){
+  // check if many configurations have the same centre.
+  // if this is the case, branch on the algorithm for this
+  // special case.
+  // Note that those situation, being considered separately in 
+  // test_cone_multiple, must only be considered here if all
+  // angles are on the same side (this avoid multiple counting)
+
+  if (centre->cocircular.empty()) return false;
+
+  // first get cone into status required at end...
+  if ((centre->side) && (cone.ref.not_empty())){
+    // update cone
+    cone -= (*child);
+
+    // update info on particles inside
+    centre->is_inside->cone = false;
+
+    // update stability check quantities
+    dpt += fabs(child->px)+fabs(child->py); //child->perp2();
+  }
+
+
+  // now establish the list of unique children in the list
+  // first make sure parent and child are in!
+
+  list<Cvicinity_inclusion *> removed_from_cone;
+  list<Cvicinity_inclusion *> put_in_border;
+  list<Cmomentum *> border_list;
+  
+  Cmomentum cone_removal;
+  Cmomentum border = *parent;
+  border_list.push_back(parent);
+
+  // make sure child appears in the border region
+  centre->cocircular.push_back(centre);
+
+  // now establish the full contents of the cone minus the cocircular
+  // region and of the cocircular region itself
+  for(list<Cvicinity_elm *>::iterator it = centre->cocircular.begin();
+      it != centre->cocircular.end(); it++) {
+
+    if ((*it)->is_inside->cone) {
+      cone_removal           += *((*it)->v);
+      (*it)->is_inside->cone  = false;
+      removed_from_cone.push_back((*it)->is_inside);
+    }
+
+    // if a point appears twice (i.e. with + and - sign) in the list of 
+    // points on the border, we take care not to include it twice.
+    // Note that this situation may appear when a point is at a distance
+    // close to 2R from the parent
+    if (!(*it)->is_inside->cocirc) {
+      border += *((*it)->v);
+      (*it)->is_inside->cocirc  = true;
+      put_in_border.push_back((*it)->is_inside);
+      border_list.push_back((*it)->v);
+    }
+  }
+
+
+  // figure out whether this pairing has been observed before
+  Cmomentum borderless_cone = cone;
+  borderless_cone -= cone_removal;
+  bool consider = true;
+  for (unsigned int i=0;i<multiple_centre_done.size();i++){
+    if ((multiple_centre_done[i].first ==borderless_cone.ref) &&
+	(multiple_centre_done[i].second==border.ref))
+      consider = false;
+  }
+
+  // now prepare the hard work
+  if (consider) {
+    // record the fact that we've now seen this combination
+    multiple_centre_done.push_back(pair<Creference,Creference>(borderless_cone.ref, 
+                                                               border.ref));
+
+    // first figure out whether our cone momentum is good
+    double local_dpt = fabs(cone_removal.px) + fabs(cone_removal.py);
+    double total_dpt = dpt + local_dpt;
+
+    recompute_cone_contents_if_needed(borderless_cone, total_dpt);
+    if (total_dpt == 0) {
+      // a recomputation has taken place -- so take advantage of this
+      // and update the member cone momentum
+      cone = borderless_cone + cone_removal;
+      dpt  = local_dpt;
+    }
+
+    test_cone_cocircular(borderless_cone, border_list);
+  }
+
+
+  // relabel things that were in the cone but got removed
+  for(list<Cvicinity_inclusion *>::iterator is_in = removed_from_cone.begin();
+      is_in != removed_from_cone.end(); is_in++) {
+    (*is_in)->cone = true;
+  }
+
+  // relabel things that got put into the border 
+  for(list<Cvicinity_inclusion *>::iterator is_in = put_in_border.begin();
+      is_in != put_in_border.end(); is_in++) {
+    (*is_in)->cocirc = false;
+  }
+
+  // we're done with everything -- return true to signal to user that we've
+  // been through the co-circularity rigmarole
+  return true;
+}
+
+
+////////////////////////////////////////////////////////
+// RECOMPUTATION OF CONE CONTENTS                     //
+//  - compute_cone_contents()                         //
+//  - recompute_cone_contents()                       //
+//  - recompute_cone_contents_if_needed()             //
+////////////////////////////////////////////////////////
+
+/**
+ * compute the cone contents by going once around the full set of
+ * circles and tracking the entry/exit status each time 
+ * given parent, child and centre compute the momentum
+ * of the particle inside the cone
+ * This sets up the inclusion information, which can then be directly 
+ * used to calculate the cone momentum.
+ **********************************************************************/
+void Cstable_cones::compute_cone_contents() {
+  circulator<vector<Cvicinity_elm*>::iterator > 
+    start(vicinity.begin()+first_cone, vicinity.begin(), vicinity.end());
+
+  circulator<vector<Cvicinity_elm*>::iterator > here(start);
+
+  // note that in the following algorithm, the cone contents never includes
+  // the child. Indeed, if it has positive sign, then it will be set as
+  // outside at the last step in the loop. If it has negative sign, then the 
+  // loop will at some point go to the corresponding situation with positive
+  // sign and set the inclusion status to 0.
+
+  do {
+    // as we leave this position a particle enters if its side is
+    // negative (i.e. the centre is the one at -ve angle wrt to the
+    // parent-child line
+    if (!(*here())->side) ((*here())->is_inside->cone) = 1;
+    
+    // move on to the next position
+    ++here;
+    
+    // as we arrive at this position a particle leaves if its side is positive
+    if ((*here())->side) ((*here())->is_inside->cone) = 0;
+  } while (here != start);
+
+  // once we've reached the start the 'is_inside' information should be
+  // 100% complete, so we can use it to calculate the cone contents
+  // and then exit
+  recompute_cone_contents();
+  return;
+
+}
+
+
+/*
+ * compute the cone momentum from particle list.
+ * in this version, we use the 'pincluded' information
+ * from the Cvicinity class
+ */
+void Cstable_cones::recompute_cone_contents(){
+  unsigned int i;
+
+  // set momentum to 0
+  cone = Cmomentum();
+
+  // Important note: we can browse only the particles
+  // in vicinity since all particles in the cone are
+  // withing a distance 2R w.r.t. parent hence in vicinity.
+  // Among those, we only add the particles for which 'is_inside' is true !
+  // This methos rather than a direct comparison avoids rounding errors
+  for (i=0;i<vicinity_size;i++){
+    // to avoid double-counting, only use particles with + angle
+    if ((vicinity[i]->side) && (vicinity[i]->is_inside->cone))
+      cone += *vicinity[i]->v;
+  }
+  
+  // set check variables back to 0
+  dpt = 0.0;
+}
+
+
+/*
+ * if we have gone beyond the acceptable threshold of change, compute
+ * the cone momentum from particle list.  in this version, we use the
+ * 'pincluded' information from the Cvicinity class, but we don't
+ * change the member cone, only the locally supplied one
+ */
+void Cstable_cones::recompute_cone_contents_if_needed(Cmomentum & this_cone, 
+                                                      double & this_dpt){
+  
+  if (this_dpt > PT_TSHOLD*(fabs(this_cone.px)+fabs(this_cone.py))) {
+    if (cone.ref.is_empty()) {
+      this_cone = Cmomentum();
+    } else {
+      // set momentum to 0
+      this_cone = Cmomentum();
+      
+      // Important note: we can browse only the particles
+      // in vicinity since all particles in the this_cone are
+      // withing a distance 2R w.r.t. parent hence in vicinity.
+      // Among those, we only add the particles for which 'is_inside' is true !
+      // This methos rather than a direct comparison avoids rounding errors
+      for (unsigned int i=0;i<vicinity_size;i++){
+        // to avoid double-counting, only use particles with + angle
+        if ((vicinity[i]->side) && (vicinity[i]->is_inside->cone))
+          this_cone += *vicinity[i]->v;
+      }
+      
+    }
+    // set check variables back to 0
+    this_dpt = 0.0;
+  }
+
+}
+
+
+////////////////////////////////////////////////////////
+// VARIOUS TOOLS                                      //
+//  - circle_intersect()                              //
+//  - is_inside()                                     //
+//  - abs_dangle()                                    //
+////////////////////////////////////////////////////////
+
+
+/*
+ * circle intersection.
+ * computes the intersection with a circle of given centre and radius.
+ * The output takes the form of a checkxor of the intersection's particles
+ *  - cx    circle centre x coordinate
+ *  - cy    circle centre y coordinate
+ * return the checkxor for the intersection
+ ******************************************************************/
+Creference Cstable_cones::circle_intersect(double cx, double cy){
+  Creference intersection;
+  int i;
+  double dx, dy;
+
+  for (i=0;i<n_part;i++){
+    // compute the distance of the i-th particle with the parent
+    dx = plist[i].eta - cx;
+    dy = fabs(plist[i].phi - cy);
+    
+    // pay attention to the periodicity in phi !
+    if (dy>M_PI) 
+      dy -= twopi;
+    
+    // really check if the distance is less than VR
+    if (dx*dx+dy*dy<R2)
+      intersection+=plist[i].ref;
+  }
+  
+  return intersection;
+}
+
+/*
+ * test if a particle is inside a cone of given centre.
+ * check if the particle of coordinates 'v' is inside the circle of radius R 
+ * centered at 'centre'.
+ *  - centre   centre of the circle
+ *  - v        particle to test
+ * return true if inside, false if outside
+ *****************************************************************************/
+inline bool Cstable_cones::is_inside(Cmomentum *centre_in, Cmomentum *v){
+  double dx, dy;
+
+  dx = centre_in->eta - v->eta;
+  dy = fabs(centre_in->phi - v->phi);
+  if (dy>M_PI) 
+    dy -= twopi;
+      
+  return dx*dx+dy*dy<R2;
+}
+
+/*
+ * compute the absolute value of the difference between 2 angles.
+ * We take care of the 2pi periodicity
+ *  - angle1   first angle
+ *  - angle2   second angle
+ * return the absolute value of the difference between the angles
+ *****************************************************************/
+inline double abs_dangle(double &angle1, double &angle2){
+  double dphi;
+
+  dphi = fabs(angle1-angle2);
+  if (dphi>M_PI) 
+    dphi = dphi-twopi;
+      
+  return dphi;
+}
+  
+}
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/protocones.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/protocones.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/protocones.h	(revision 5)
@@ -0,0 +1,271 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: protocones.h                                                        //
+// Description: header file for stable cones determination (Cstable_cones)   //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __PROTOCONES_H__
+#define __PROTOCONES_H__
+
+#include "momentum.h"
+#include "vicinity.h"
+#include <stdio.h>
+#include <vector>
+#include <list>
+#include "hash.h"
+
+#include "defines.h"
+
+namespace siscone{
+
+/**
+ * \class Cborder_store
+ * 
+ * class for storing a border momentum (in context of co-circularity
+ * checks).
+
+ * This class essentially calculates angle of border point w.r.t.
+ * circle center (eta & phi), and provides a store of information
+ * about whether we are currently including this point in the
+ * candidate 
+ */
+class Cborder_store{
+public:
+  /// default ctor
+  Cborder_store(Cmomentum * momentum, double centre_eta, double centre_phi) : 
+    mom(momentum),  is_in(false) {
+    angle = atan2(mom->phi - centre_phi, mom->eta - centre_eta);
+  }
+
+  Cmomentum * mom;  ///< particle momentum
+  double angle;     ///< angle w.r.t. circle centre
+  bool   is_in;     ///< inclusion status of the particle
+};
+
+
+/// allows easy sorting of Cborder_store objects (which need to be
+/// ordered in angle).
+inline bool operator<(const Cborder_store & a, const Cborder_store & b) {
+  return a.angle < b.angle;
+}
+
+
+/**
+ * \class Cstable_cones
+ * \brief Computes the list of stable comes from a particle list.
+ *
+ * This class does the first fundamental task of te cone algorithm:
+ * it is used to compute the list of stable cones given a list
+ * of particles.
+ */
+class Cstable_cones : public Cvicinity{
+ public:
+  /// default ctor
+  Cstable_cones();
+
+  /// ctor with initialisation (sse init for details)
+  Cstable_cones(std::vector<Cmomentum> &_particle_list);
+
+  /// default dtor
+  ~Cstable_cones();
+
+  /**
+   * initialisation
+   * \param _particle_list  list of particles
+   */
+  void init(std::vector<Cmomentum> &_particle_list);
+
+  /**
+   * compute stable cones.
+   * This function really does the job i.e. computes
+   * the list of stable cones (in a seedless way)
+   * \param _radius   radius of the cones
+   * \return The number of stable cones found is returned
+   */
+  int get_stable_cones(double _radius);
+
+  /// list of stable cones
+  std::vector<Cmomentum> protocones;
+
+  /// list of candidates
+  hash_cones *hc;
+
+  /// total number of tested cones
+  int nb_tot;
+#ifdef DEBUG_STABLE_CONES
+  int nb_hash_cones, nb_hash_occupied;
+#endif
+
+ protected:
+  /// cone radius
+  double R;
+
+  /// cone radius SQUARED
+  double R2;
+
+ private:
+  /// cone with a given particle as parent
+  /// this reduction to a single vector assumes we trust the checksums
+  Cmomentum cone;
+
+  /// child particle, taken in the 'vicinity' list
+  Cmomentum *child;
+
+  /// centre of the tested cone 
+  Cvicinity_elm *centre;
+
+  /// index in the particle list;
+  unsigned int centre_idx;
+
+  /// first cone used in the vicinity list
+  unsigned int first_cone;
+
+  /**
+   * initialise the cone.
+   * We take the first particle in the angular ordering to compute this one
+   * \return 0 on success, 1 on error
+   */
+  int init_cone();
+
+  /**
+   * test cones.
+   * We check if the cone(s) build with the present parent and child 
+   * are stable
+   * \return 0 on success 1 on error
+   */
+  int test_cone();
+
+  /**
+   * update the cone
+   * go to the next child for that parent and update 'cone' appropriately
+   * \return 0 if update candidate found, 1 otherwise
+   */
+  int update_cone();
+
+  /*
+   * run through the vicinity of the current parent and for each child
+   * indicate which members are cocircular...
+   */
+  void prepare_cocircular_lists();
+
+  /**
+   * check if we are in a situation of cocircularity.
+   * if it is the case, update and test in the corresponding way
+   * \return 'false' if no cocircularity detected, 'true' otherwise
+   * Note that if cocircularity is detected, we need to 
+   * recall 'update' from 'update' !!!
+   */
+  bool cocircular_check();
+
+  /**
+   * Routine for testing cocircular configurations in p^3 time,
+   * rather than 2^p time;
+   */
+  void test_cone_cocircular(Cmomentum & borderless_cone, 
+			    std::list<Cmomentum *> & border_list);
+
+  /**
+   * carry out the computations needed for the stability check of the
+   * candidate, using the border_vect to indicate which particles
+   * should / should not be in the stable cone; if the cone is stable
+   * insert it into the hash.
+   */
+  void test_stability(Cmomentum & candidate, 
+                      const std::vector<Cborder_store> & border_vect);
+
+  /**
+   * compute the cone contents by going once around the full set of
+   * circles and tracking the entry/exit status each time -- this sets
+   * up the inclusion information, which can then be directly used to
+   * calculate the cone momentum.
+   */
+  void compute_cone_contents();
+
+  /**
+   * compute the cone momentum from particle list.
+   * in this version, we use the 'pincluded' information
+   * from the Cviinity class
+   */
+  void recompute_cone_contents();
+
+  /*
+   * if we have gone beyond the acceptable threshold of change, compute
+   * the cone momentum from particle list.  in this version, we use the
+   * 'pincluded' information from the Cvicinity class, but we don't
+   * change the member cone, only the locally supplied one
+   */
+  void recompute_cone_contents_if_needed(Cmomentum & this_cone, double & this_dpt);
+
+  /**
+   * compute stability of all enumerated candidates.
+   * For all candidate cones which are stable w.r.t. their border particles,
+   * pass the last test: stability with quadtree intersection
+   */
+  int proceed_with_stability();
+
+  /*
+   * circle intersection.
+   * computes the intersection with a circle of given centre and radius.
+   * The output takes the form of a checkxor of the intersection's particles
+   *  - cx    circle centre x coordinate
+   *  - cy    circle centre y coordinate
+   * return the checkxor for the intersection
+   ******************************************************************/
+  Creference circle_intersect(double cx, double cy);
+
+  /// present candidate cone
+  Cmomentum cone_candidate;
+
+  /// in case of co-circular points, vector for them
+  std::vector<Cmomentum*> child_list;
+
+  /// list of cocircular enclusures already studied
+  /// first element if cone contents, second is cone border
+  std::vector< std::pair<Creference,Creference> > multiple_centre_done;
+
+  // information for updating cone contents to avoid rounding errors
+  double dpt;          ///< sums of Delta P_t
+
+  /**
+   * test if a particle is inside a cone of given centre.
+   * check if the particle of coordinates 'v' is inside the circle of radius R 
+   * centered at 'centre'.
+   * \param centre   centre of the circle
+   * \param v        particle to test
+   * \return true if inside, false if outside
+   */
+  inline bool is_inside(Cmomentum *centre, Cmomentum *v);
+};
+
+/*
+ * compute the absolute value of the difference between 2 angles.
+ * We take care of the 2pi periodicity
+ * \param angle1   first angle
+ * \param angle2   second angle
+ * \return the absolute value of the difference between the angles
+ *****************************************************************/
+inline double abs_dangle(double &angle1, double &angle2);
+
+}
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/quadtree.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/quadtree.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/quadtree.cc	(revision 5)
@@ -0,0 +1,304 @@
+///////////////////////////////////////////////////////////////////////////////
+// File: quadtree.cpp                                                        //
+// Description: source file for quadtree management (Cquadtree class)        //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "quadtree.h"
+#include <math.h>
+#include <stdio.h>
+#include <iostream>
+
+namespace siscone{
+
+using namespace std;
+
+/*******************************************************************
+ * Cquadtree implementation                                        *
+ * Implementation of a 2D quadtree.                                *
+ * This class implements the traditional two-dimensional quadtree. *
+ * The elements at each node are of 'Cmomentum' type.              *
+ *******************************************************************/
+
+// default ctor
+//--------------
+Cquadtree::Cquadtree(){
+  v = NULL;
+
+  children[0][0] = children[0][1] = children[1][0] = children[1][1] = NULL;
+  has_child = false;
+}
+
+
+// ctor with initialisation (see init for details)
+//--------------------------
+Cquadtree::Cquadtree(double _x, double _y, double _half_size_x, double _half_size_y){
+  v = NULL;
+
+  children[0][0] = children[0][1] = children[1][0] = children[1][1] = NULL;
+  has_child = false;
+
+  init(_x, _y, _half_size_x, _half_size_y);
+}
+
+
+// default destructor
+// at destruction, everything is destroyed except 
+// physical values at the leaves
+//------------------------------------------------
+Cquadtree::~Cquadtree(){
+  if (has_child){
+    if (v!=NULL) delete v;
+    delete children[0][0];
+    delete children[0][1];
+    delete children[1][0];
+    delete children[1][1];
+  }
+}
+
+
+/*
+ * init the tree.
+ * By initializing the tree, we mean setting the cell parameters
+ * and preparing the object to act as a seed for a new tree.
+ *  - _x           x-position of the center
+ *  - _y           y-position of the center
+ *  - half_size_x  half x-size of the cell
+ *  - half_size_y  half y-size of the cell
+ * return 0 on success, 1 on error. Note that if the cell
+ *        is already filled, we return an error.
+ ******************************************************************/
+int Cquadtree::init(double _x, double _y, double _half_size_x, double _half_size_y){
+  if (v!=NULL)
+    return 1;
+
+  centre_x = _x;
+  centre_y = _y;
+  half_size_x = _half_size_x;
+  half_size_y = _half_size_y;
+
+  return 0;
+}
+
+
+/*
+ * adding a particle to the tree.
+ * This method adds one vector to the quadtree structure which 
+ * is updated consequently.
+ *  - v   vector to add
+ * return 0 on success 1 on error
+ ******************************************************************/
+int Cquadtree::add(Cmomentum *v_add){
+  // Description of the method:
+  // --------------------------
+  // the addition process goes as follows:
+  //  1. check if the cell is empty, in which case, add the particle 
+  //     here and leave.
+  //  2. If there is a unique particle already inside,
+  //      (a) create children
+  //      (b) forward the existing particle to the appropriate child
+  //  3. Add current particle to this cell and forward to the 
+  //     adequate child
+  // NOTE: we assume in the whole procedure that the particle is 
+  //       indeed inside the cell !
+
+  // step 1: the case of empty cells
+  if (v==NULL){
+    v = v_add;
+    return 0;
+  }
+
+  // step 2: additional work if 1! particle already present
+  //         we use the fact that only 1-particle systems have no child
+  if (!has_child){
+    double new_half_size_x = 0.5*half_size_x;
+    double new_half_size_y = 0.5*half_size_y;
+    // create children
+    children[0][0] = new Cquadtree(centre_x-new_half_size_x, centre_y-new_half_size_y,
+				   new_half_size_x, new_half_size_y);
+    children[0][1] = new Cquadtree(centre_x-new_half_size_x, centre_y+new_half_size_y,
+				   new_half_size_x, new_half_size_y);
+    children[1][0] = new Cquadtree(centre_x+new_half_size_x, centre_y-new_half_size_y,
+				   new_half_size_x, new_half_size_y);
+    children[1][1] = new Cquadtree(centre_x+new_half_size_x, centre_y+new_half_size_y,
+				   new_half_size_x, new_half_size_y);
+
+    has_child = true;
+
+    // forward to child
+    //? The following line assumes 'true'==1 and 'false'==0
+    // Note: v being a single particle, eta and phi are correct
+    children[v->eta>centre_x][v->phi>centre_y]->add(v);
+
+    // copy physical params
+    v = new Cmomentum(*v);
+  }
+
+  // step 3: add new particle
+  // Note: v_add being a single particle, eta and phi are correct
+  children[v_add->eta>centre_x][v_add->phi>centre_y]->add(v_add);
+  *v+=*v_add;
+
+  return 0;
+}
+
+
+/*
+ * circle intersection.
+ * computes the intersection with a circle of given centre and radius.
+ * The output takes the form of a quadtree with all squares included 
+ * in the circle.
+ *  - cx    circle centre x coordinate
+ *  - cy    circle centre y coordinate
+ *  - cR2   circle radius SQUARED
+ * return the checksum for the intersection
+ ******************************************************************/
+Creference Cquadtree::circle_intersect(double cx, double cy, double cR2){
+  // Description of the method:
+  // --------------------------
+  // 1. check if cell is empty => no intersection
+  // 2. if cell has 1! particle, check if it is inside the circle.
+  //    If yes, add it and return, if not simply return.
+  // 3. check if the circle intersects the square. If not, return.
+  // 4. check if the square is inside the circle. 
+  //    If yes, add it to qt and return.
+  // 5. check intersections with children.
+
+  // step 1: if there is no particle inside te square, no reason to go further
+  if (v==NULL)
+    return Creference();
+
+  double dx, dy;
+
+  // step 2: if there is only one particle inside the square, test if it is in
+  //         the circle, in which case return associated reference
+  if (!has_child){
+    // compute the distance
+    // Note: v has only one particle => eta and phi are defined
+    dx = cx - v->eta;
+    dy = fabs(cy - v->phi);
+    if (dy>M_PI) 
+      dy -= 2.0*M_PI;
+
+    // test distance
+    if (dx*dx+dy*dy<cR2){
+      return v->ref;
+    }
+
+    return Creference();
+  }
+
+  // step 3: check if there is an intersection
+  //double ryp, rym;
+  double dx_c, dy_c;
+
+  // store distance with the centre of the square
+  dx_c = fabs(cx-centre_x);
+  dy_c = fabs(cy-centre_y);
+  if (dy_c>M_PI) dy_c = 2.0*M_PI-dy_c;
+
+  // compute (minimal) the distance (pay attention to the periodicity in phi).
+  dx = dx_c-half_size_x;
+  if (dx<0) dx=0;
+  dy = dy_c-half_size_y;
+  if (dy<0) dy=0;
+
+  // check the distance 
+  if (dx*dx+dy*dy>=cR2){
+    // no intersection
+    return Creference();
+  }
+
+  // step 4: check if included
+
+  // compute the (maximal) distance
+  dx = dx_c+half_size_x;
+  dy = dy_c+half_size_y;
+  if (dy>M_PI) dy = M_PI;
+
+  // compute the distance
+  if (dx*dx+dy*dy<cR2){
+    return v->ref;
+  }
+
+  // step 5: the square is not fully in. Recurse to children
+  return children[0][0]->circle_intersect(cx, cy, cR2)
+    + children[0][1]->circle_intersect(cx, cy, cR2)
+    + children[1][0]->circle_intersect(cx, cy, cR2)
+    + children[1][1]->circle_intersect(cx, cy, cR2);
+}
+
+
+/*
+ * output a data file for drawing the grid.
+ * This can be used to output a data file containing all the
+ * grid subdivisions. The file contents is as follows:
+ * first and second columns give center of the cell, the third 
+ * gives the size.
+ *  - flux  opened stream to write to
+ * return 0 on success, 1 on error
+ ******************************************************************/
+int Cquadtree::save(FILE *flux){
+
+  if (flux==NULL)
+    return 1;
+
+  if (has_child){
+    fprintf(flux, "%e\t%e\t%e\t%e\n", centre_x, centre_y, half_size_x, half_size_y);
+    children[0][0]->save(flux);
+    children[0][1]->save(flux);
+    children[1][0]->save(flux);
+    children[1][1]->save(flux);
+  }
+
+  return 0;
+}
+
+
+/*
+ * output a data file for drawing the tree leaves.
+ * This can be used to output a data file containing all the
+ * tree leaves. The file contents is as follows:
+ * first and second columns give center of the cell, the third 
+ * gives the size.
+ *  - flux  opened stream to write to
+ * return 0 on success, 1 on error
+ ******************************************************************/
+int Cquadtree::save_leaves(FILE *flux){
+
+  if (flux==NULL)
+    return 1;
+
+  if (has_child){
+    if (children[0][0]!=NULL) children[0][0]->save_leaves(flux);
+    if (children[0][1]!=NULL) children[0][1]->save_leaves(flux);
+    if (children[1][0]!=NULL) children[1][0]->save_leaves(flux);
+    if (children[1][1]!=NULL) children[1][1]->save_leaves(flux);
+  } else {
+    fprintf(flux, "%e\t%e\t%e\t%e\n", centre_x, centre_y, half_size_x, half_size_y);
+  }
+
+  return 0;
+}
+
+}
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/quadtree.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/quadtree.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/quadtree.h	(revision 5)
@@ -0,0 +1,124 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: quadtree.h                                                          //
+// Description: header file for quadtree management (Cquadtree class)        //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __QUADTREE_H__
+#define __QUADTREE_H__
+
+#include "momentum.h"
+#include <stdio.h>
+
+namespace siscone{
+
+/**
+ * \class Cquadtree
+ * \brief Implementation of a 2D quadtree.
+ *
+ * This class implements the traditional two-dimensional quadtree.
+ * The elements at each node are of 'Cmomentum' type.
+ */
+class Cquadtree{
+ public:
+  /// default ctor
+  Cquadtree();
+
+  /// ctor with initialisation (see init for details)
+  Cquadtree(double _x, double _y, double _half_size_x, double _half_size_y);
+
+  /// default destructor
+  /// at destruction, everything is destroyed except 
+  /// physical values at the leaves
+  ~Cquadtree();
+
+  /**
+   * init the tree.
+   * By initializing the tree, we mean setting the cell parameters
+   * and preparing the object to act as a seed for a new tree.
+   * \param _x            x-position of the center
+   * \param _y            y-position of the center
+   * \param _half_size_x  x-size of the cell
+   * \param _half_size_y  y-size of the cell
+   * \return 0 on success, 1 on error. Note that if the cell or its 
+   *         parent is already filled, we return an error.
+   */
+  int init(double _x, double _y, double _half_size_x, double _half_size_y);
+
+  /**
+   * adding a particle to the tree.
+   * This method adds one vector to the quadtree structure which 
+   * is updated consequently.
+   * \param v_add   vector to add
+   * \return 0 on success 1 on error
+   */
+  int add(Cmomentum *v_add);
+
+  /**
+   * circle intersection.
+   * computes the intersection with a circle of given centre and radius.
+   * The output takes the form of a quadtree with all squares included 
+   * in the circle.
+   * \param cx    circle centre x coordinate
+   * \param cy    circle centre y coordinate
+   * \param cR2   circle radius SQUARED
+   * \return the checksum for that intersection
+   */
+  Creference circle_intersect(double cx, double cy, double cR2);
+
+  /**
+   * output a data file for drawing the grid.
+   * This can be used to output a data file containing all the
+   * grid subdivisions. The file contents is as follows:
+   * first and second columns give center of the cell, the third 
+   * gives the size.
+   * \param flux  opened stream to write to
+   * \return 0 on success, 1 on error
+   */
+  int save(FILE *flux);
+
+  /**
+   * output a data file for drawing the tree leaves.
+   * This can be used to output a data file containing all the
+   * tree leaves. The file contents is as follows:
+   * first and second columns give center of the cell, the third 
+   * gives the size.
+   * \param flux  opened stream to write to
+   * \return 0 on success, 1 on error
+   */
+  int save_leaves(FILE *flux);
+
+  double centre_x;           ///< x-position of the centre of the cell
+  double centre_y;           ///< y-position of the centre of the cell
+  double half_size_x;        ///< HALF size of the cell
+  double half_size_y;        ///< HALF size of the cell
+
+  Cmomentum *v;              ///< physical contents
+
+  Cquadtree* children[2][2]; ///< sub-cells ( 0,1->left-right; 0,1->bottom,top)
+  bool has_child;            ///< true if not a leaf
+};
+
+}
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/ranlux.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/ranlux.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/ranlux.cc	(revision 5)
@@ -0,0 +1,171 @@
+// file: ranlux.xpp
+#include "ranlux.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+/* This is a lagged fibonacci generator with skipping developed by Luescher.
+   The sequence is a series of 24-bit integers, x_n, 
+
+   x_n = d_n + b_n
+
+   where d_n = x_{n-10} - x_{n-24} - c_{n-1}, b_n = 0 if d_n >= 0 and
+   b_n = 2^24 if d_n < 0, c_n = 0 if d_n >= 0 and c_n = 1 if d_n < 0,
+   where after 24 samples a group of p integers are "skipped", to
+   reduce correlations. By default p = 199, but can be increased to
+   365.
+
+   The period of the generator is around 10^171. 
+
+   From: M. Luescher, "A portable high-quality random number generator
+   for lattice field theory calculations", Computer Physics
+   Communications, 79 (1994) 100-110.
+
+   Available on the net as hep-lat/9309020 at http://xxx.lanl.gov/
+
+   See also,
+
+   F. James, "RANLUX: A Fortran implementation of the high-quality
+   pseudo-random number generator of Luscher", Computer Physics
+   Communications, 79 (1994) 111-114
+
+   Kenneth G. Hamilton, F. James, "Acceleration of RANLUX", Computer
+   Physics Communications, 101 (1997) 241-248
+
+   Kenneth G. Hamilton, "Assembler RANLUX for PCs", Computer Physics
+   Communications, 101 (1997) 249-253  */
+
+namespace siscone{
+
+static const unsigned long int mask_lo = 0x00ffffffUL;  // 2^24 - 1
+static const unsigned long int mask_hi = ~0x00ffffffUL;
+static const unsigned long int two24 = 16777216;        // 2^24
+
+
+// internal generator structure
+//------------------------------
+typedef struct {
+  unsigned int i;
+  unsigned int j;
+  unsigned int n;
+  unsigned int skip;
+  unsigned int carry;
+  unsigned long int u[24];
+} ranlux_state_t;
+
+
+// internal generator state
+//--------------------------
+ranlux_state_t local_ranlux_state;
+
+
+// incrementation of the generator state
+//---------------------------------------
+static inline unsigned long int increment_state(){
+  unsigned int i = local_ranlux_state.i;
+  unsigned int j = local_ranlux_state.j;
+  long int delta = local_ranlux_state.u[j] - local_ranlux_state.u[i] 
+    - local_ranlux_state.carry;
+
+  if (delta & mask_hi){
+    local_ranlux_state.carry = 1;
+    delta &= mask_lo;
+  } else {
+    local_ranlux_state.carry = 0;
+  }
+
+  local_ranlux_state.u[i] = delta;
+  
+  if (i==0)
+    i = 23;
+  else
+    i--;
+
+  local_ranlux_state.i = i;
+
+  if (j == 0)
+    j = 23;
+  else
+    j--;
+
+  local_ranlux_state.j = j;
+
+  return delta;
+}
+
+
+// set generator state
+//---------------------
+static void ranlux_set(unsigned long int s){
+  int i;
+  long int seed;
+  
+  if (s==0)
+    s = 314159265;      /* default seed is 314159265 */
+  
+  seed = s;
+  
+  /* This is the initialization algorithm of F. James, widely in use
+     for RANLUX. */
+
+  for (i=0;i<24;i++){
+    unsigned long int k = seed/53668;
+    seed = 40014*(seed-k*53668)-k*12211;
+    if (seed<0){
+      seed += 2147483563;
+    }
+    local_ranlux_state.u[i] = seed%two24;
+  }
+
+  local_ranlux_state.i = 23;
+  local_ranlux_state.j = 9;
+  local_ranlux_state.n = 0;
+  local_ranlux_state.skip = 389-24; // 389 => best decorrelation
+
+  if (local_ranlux_state.u[23]&mask_hi){
+    local_ranlux_state.carry = 1;
+  } else {
+    local_ranlux_state.carry = 0;
+  }
+}
+
+
+// generator initialization
+//--------------------------
+void ranlux_init(){
+  // seed the generator
+  ranlux_set(0);
+}
+
+
+// get random number
+//-------------------
+unsigned long int ranlux_get(){
+  const unsigned int skip = local_ranlux_state.skip;
+  unsigned long int r = increment_state();
+  
+  local_ranlux_state.n++;
+
+  if (local_ranlux_state.n == 24){
+    unsigned int i;
+    local_ranlux_state.n = 0;
+    for (i = 0; i < skip; i++)
+      increment_state();
+  }
+
+  return r;
+}
+
+// print generator state
+//-----------------------
+void ranlux_print_state(){
+  size_t i;
+  unsigned char *p = (unsigned char *) (&local_ranlux_state);
+  const size_t n = sizeof (ranlux_state_t);
+
+  for (i=0;i<n;i++){
+    /* FIXME: we're assuming that a char is 8 bits */
+    printf("%.2x", *(p+i));
+  }
+}
+
+}
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/ranlux.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/ranlux.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/ranlux.h	(revision 5)
@@ -0,0 +1,49 @@
+//! \file ranlux.h
+
+#ifndef __RANLUX_H__
+#define __RANLUX_H__
+
+/* This is a lagged fibonacci generator with skipping developed by Luescher.
+   The sequence is a series of 24-bit integers, x_n, 
+
+   x_n = d_n + b_n
+
+   where d_n = x_{n-10} - x_{n-24} - c_{n-1}, b_n = 0 if d_n >= 0 and
+   b_n = 2^24 if d_n < 0, c_n = 0 if d_n >= 0 and c_n = 1 if d_n < 0,
+   where after 24 samples a group of p integers are "skipped", to
+   reduce correlations. By default p = 199, but can be increased to
+   365.
+
+   The period of the generator is around 10^171. 
+
+   From: M. Luescher, "A portable high-quality random number generator
+   for lattice field theory calculations", Computer Physics
+   Communications, 79 (1994) 100-110.
+
+   Available on the net as hep-lat/9309020 at http://xxx.lanl.gov/
+
+   See also,
+
+   F. James, "RANLUX: A Fortran implementation of the high-quality
+   pseudo-random number generator of Luscher", Computer Physics
+   Communications, 79 (1994) 111-114
+
+   Kenneth G. Hamilton, F. James, "Acceleration of RANLUX", Computer
+   Physics Communications, 101 (1997) 241-248
+
+   Kenneth G. Hamilton, "Assembler RANLUX for PCs", Computer Physics
+   Communications, 101 (1997) 249-253  */
+
+namespace siscone{
+
+/// initialize 'ranlux' generator
+void ranlux_init();
+
+/// generate random value (24 bits)
+unsigned long int ranlux_get();
+
+/// save state of the generator
+void ranlux_print_state();
+
+}
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/reference.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/reference.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/reference.cc	(revision 5)
@@ -0,0 +1,120 @@
+///////////////////////////////////////////////////////////////////////////////
+// File: reference.cpp                                                       //
+// Description: source file for checkxor management (Creference class)       //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "reference.h"
+#include "ranlux.h"
+#include <stdlib.h>
+
+namespace siscone{
+
+/*******************************************************
+ * Creference implementation                           *
+ * references used for checksums.                      *
+ *                                                     *
+ * This class implements some reference variable       *
+ * that can be used for checksums. Those checksums     *
+ * are useful to disentengle between contents of two   *
+ * cones without looking into their explicit particle  *
+ * contents.                                           *
+ *******************************************************/
+
+// default constructor
+//////////////////////
+Creference::Creference(){
+  ref[0] = ref[1] = ref[2] = 0;
+}
+
+  //static unsigned int reference_bit = 1;
+
+// create a random reference
+//---------------------------
+void Creference::randomize(){
+//  ref[0] = reference_bit;
+//  ref[1] = 0;
+//  ref[2] = 0;
+//  reference_bit <<= 1;
+
+  unsigned int r1 = ranlux_get();
+  unsigned int r2 = ranlux_get();
+  unsigned int r3 = ranlux_get();
+  unsigned int r4 = ranlux_get();
+  // since ranlux only produces 24 bits, take r4 and add 8 bits
+  // from it to each of r1,r2, r3 to get 3*32 bits.
+  ref[0] = r1+((r4 & 0x00ff0000) <<  8);
+  ref[1] = r2+((r4 & 0x0000ff00) << 16);
+  ref[2] = r3+((r4 & 0x000000ff) << 24);
+
+  if (is_empty()) randomize();
+}
+
+// test emptyness
+//----------------
+bool Creference::is_empty(){
+  return (ref[0]==0) && (ref[1]==0) && (ref[2]==0);
+}
+
+// test non-emptyness
+//--------------------
+bool Creference::not_empty(){
+  return (ref[0]!=0) || (ref[1]!=0) || (ref[2]!=0);
+}
+
+// assignment of reference
+//-------------------------
+Creference& Creference::operator = (const Creference &r){
+  ref[0] = r.ref[0];  
+  ref[1] = r.ref[1];
+  ref[2] = r.ref[2];
+  return *this;
+}
+
+// addition of reference
+//-----------------------
+Creference Creference::operator + (const Creference &r){
+  Creference tmp = *this;
+  return tmp+=r;
+}
+
+// incrementation of reference
+//-----------------------------
+Creference& Creference::operator += (const Creference &r){
+  ref[0] ^= r.ref[0];  
+  ref[1] ^= r.ref[1];
+  ref[2] ^= r.ref[2];
+  return *this; 
+}
+
+// decrementation of reference
+//-----------------------------
+Creference& Creference::operator -= (const Creference &r){
+  ref[0] ^= r.ref[0];  
+  ref[1] ^= r.ref[1];
+  ref[2] ^= r.ref[2];
+  return *this; 
+}
+
+}
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/reference.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/reference.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/reference.h	(revision 5)
@@ -0,0 +1,111 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: reference.h                                                         //
+// Description: header file for checkxor management (Creference class)       //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __REFERENCE_H__
+#define __REFERENCE_H__
+
+namespace siscone{
+
+/**
+ * \class Creference
+ * \brief references used for checksums.
+ *
+ * This class implements some reference variable
+ * that can be used for checksums. Those checksums
+ * are useful to disentengle between contents of two
+ * cones without looking into their explicit particle
+ * contents.
+ */
+class Creference{
+ public:
+  /// default constructor
+  Creference();
+
+  /// create a random reference
+  void randomize();
+
+  /// test emptyness
+  bool is_empty();
+
+  /// test non-emptyness
+  bool not_empty();
+
+  /// assignment of reference
+  Creference& operator = (const Creference &r);
+
+  /// addition of reference
+  Creference operator + (const Creference &r);
+
+  /// incrementation of reference
+  Creference& operator += (const Creference &r);
+
+  /// decrementation of reference
+  Creference& operator -= (const Creference &r);
+
+  /// accessing the reference
+  inline unsigned int operator[] (int i) {return ref[i];}
+
+  unsigned int ref[3];   ///< actual data for the reference
+};
+
+/// addition of two references
+Creference operator + (Creference &r1, Creference &r2);
+
+/// equality test of two references
+bool operator == (const Creference &r1, const Creference &r2);
+
+/// difference test of two references
+bool operator != (const Creference &r1, const Creference &r2);
+
+/// ordering of two references
+bool operator < (const Creference &r1, const Creference &r2);
+
+
+//=============== inline material ================
+
+// equality test for two references
+//----------------------------------
+inline bool operator == (const Creference &r1, const Creference &r2){
+  return (r1.ref[0]==r2.ref[0]) && (r1.ref[1]==r2.ref[1]) && (r1.ref[2]==r2.ref[2]);
+}
+
+// difference test for two references
+//----------------------------------
+inline bool operator != (const Creference &r1, const Creference &r2){
+  return (r1.ref[0]!=r2.ref[0]) || (r1.ref[1]!=r2.ref[1]) || (r1.ref[2]!=r2.ref[2]);
+}
+
+// difference test for two references
+//----------------------------------
+inline bool operator < (const Creference &r1, const Creference &r2){
+  return (r1.ref[0]<r2.ref[0]) || ((r1.ref[0]==r2.ref[0]) && 
+				   ((r1.ref[1]<r2.ref[1]) || ((r1.ref[1]==r2.ref[1]) && (r1.ref[2]<r2.ref[2]))
+				    ));
+}
+
+}
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/siscone.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/siscone.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/siscone.cc	(revision 5)
@@ -0,0 +1,232 @@
+///////////////////////////////////////////////////////////////////////////////
+// File: siscone.cpp                                                         //
+// Description: source file for the main SISCone class                       //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+//#ifdef HAVE_CONFIG_H
+#include "config.h"
+//#else
+//#define PACKAGE_NAME "SISCone"
+//#define VERSION "1.4.0-devel"
+//#warning "No config.h file available, using preset values"
+//#endif
+
+#include "ranlux.h"
+#include "momentum.h"
+#include "defines.h"
+#include "siscone.h"
+#include "siscone_error.h"
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+namespace siscone{
+using namespace std;
+
+/***************************************************************
+ * Csiscone implementation                                     *
+ * final class: gather everything to compute the jet contents. *
+ *                                                             *
+ * This is the class user should use.                          *
+ * It computes the jet contents of a list of particles         *
+ * given a cone radius and a threshold for splitting/merging.  *
+ ***************************************************************/
+
+// default ctor
+//--------------
+Csiscone::Csiscone(){
+  rerun_allowed = false;
+}
+
+// default dtor
+//--------------
+Csiscone::~Csiscone(){
+  rerun_allowed = false;
+}
+
+bool Csiscone::init_done=false;
+std::ostream* Csiscone::_banner_ostr = &cout;
+
+/*
+ * compute the jets from a given particle set doing multiple passes
+ * such pass N looks for jets among all particles not put into jets
+ * during previous passes.
+ *  - _particles   list of particles
+ *  - _radius      cone radius
+ *  - _f           shared energy threshold for splitting&merging
+ *  - _n_pass_max  maximum number of runs
+ *  - _ptmin       minimum pT of the protojets
+ *  - _split_merge_scale    the scale choice for the split-merge procedure
+ *    NOTE: using pt leads to IR unsafety for some events with momentum
+ *          conservation. So we strongly advise not to change the default
+ *          value.
+ * return the number of jets found.
+ **********************************************************************/
+int Csiscone::compute_jets(vector<Cmomentum> &_particles, double _radius, double _f, 
+			   int _n_pass_max, double _ptmin,
+			   Esplit_merge_scale _split_merge_scale){
+  // initialise random number generator
+  if (!init_done){
+    // initialise random number generator
+    ranlux_init();
+
+    // do not do this again
+    init_done=true;
+
+    // print the banner
+    if (_banner_ostr != 0){
+      (*_banner_ostr) << "#ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" << endl;
+      (*_banner_ostr) << "#                    SISCone   version " << setw(28) << left << siscone_version() << "o" << endl;
+      (*_banner_ostr) << "#              http://projects.hepforge.org/siscone                o" << endl;
+      (*_banner_ostr) << "#                                                                  o" << endl;
+      (*_banner_ostr) << "# This is SISCone: the Seedless Infrared Safe Cone Jet Algorithm   o" << endl;
+      (*_banner_ostr) << "# SISCone was written by Gavin Salam and Gregory Soyez             o" << endl;
+      (*_banner_ostr) << "# It is released under the terms of the GNU General Public License o" << endl;
+      (*_banner_ostr) << "#                                                                  o" << endl;
+      (*_banner_ostr) << "# A description of the algorithm is available in the publication   o" << endl;
+      (*_banner_ostr) << "# JHEP 05 (2007) 086 [arXiv:0704.0292 (hep-ph)].                   o" << endl;
+      (*_banner_ostr) << "# Please cite it if you use SISCone.                               o" << endl;
+      (*_banner_ostr) << "#ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" << endl;
+      (*_banner_ostr) << endl;
+
+      _banner_ostr->flush();
+    }
+  }
+
+  // run some general safety tests (NB: f will be checked in split-merge)
+  if (_radius <= 0.0 || _radius >= 0.5*M_PI) {
+    ostringstream message;
+    message << "Illegal value for cone radius, R = " << _radius 
+            << " (legal values are 0<R<pi/2)";
+    throw Csiscone_error(message.str());
+  }
+
+
+
+  ptcomparison.split_merge_scale = _split_merge_scale;
+  partial_clear(); // make sure some things are initialised properly
+
+  // init the split_merge algorithm with the initial list of particles
+  // this initialises particle list p_left of remaining particles to deal with
+  init_particles(_particles);
+
+  bool finished = false;
+
+  rerun_allowed = false;
+  protocones_list.clear();
+
+#ifdef DEBUG_STABLE_CONES
+  nb_hash_cones_total = 0;
+  nb_hash_occupied_total = 0;
+#endif
+
+  do{
+    // initialise stable_cone finder
+    // here we use the list of remaining particles
+    // AFTER COLLINEAR CLUSTERING !!!!!!
+    Cstable_cones::init(p_uncol_hard);
+
+    // get stable cones
+    if (get_stable_cones(_radius)){
+      // we have some new protocones; add them to candidates
+      // Note that add_protocones has to be called first
+      // if we want the 4-vect components to be available
+      // on top of eta and phi.
+      add_protocones(&protocones, R2, _ptmin);
+      protocones_list.push_back(protocones);
+#ifdef DEBUG_STABLE_CONES
+      nb_hash_cones_total += nb_hash_cones;
+      nb_hash_occupied_total += nb_hash_occupied;
+#endif
+    } else {
+      // no new protocone: leave
+      finished=true;
+    }
+
+    _n_pass_max--;
+  } while ((!finished) && (n_left>0) && (_n_pass_max!=0));
+
+  rerun_allowed = true;
+
+  // split & merge
+  return perform(_f, _ptmin);
+}
+
+/*
+ * recompute the jets with a different overlap parameter.
+ * we use the same particles and R as in the preceeding call.
+ *  - _f           shared energy threshold for splitting&merging
+ *  - _ptmin       minimum pT of the protojets
+ *  - _split_merge_scale    the scale choice for the split-merge procedure
+ *    NOTE: using pt leads to IR unsafety for some events with momentum
+ *          conservation. So we strongly advise not to change the default
+ *          value.
+ * return the number of jets found, -1 if recomputation not allowed.
+ ********************************************************************/
+int Csiscone::recompute_jets(double _f, double _ptmin,
+			     Esplit_merge_scale _split_merge_scale){
+  if (!rerun_allowed)
+    return -1;
+
+  ptcomparison.split_merge_scale = _split_merge_scale;
+
+  // restore particle list
+  partial_clear();
+  init_pleft();
+
+  // initialise split/merge algorithm
+  unsigned int i;
+  for (i=0;i<protocones_list.size();i++)
+    add_protocones(&(protocones_list[i]), R2, _ptmin);
+
+  // split & merge
+  return perform(_f, _ptmin);
+}  
+
+
+// finally, a bunch of functions to access to 
+// basic information (package name, version)
+//---------------------------------------------
+
+/* 
+ * return SISCone package name.
+ * This is nothing but "SISCone", it is a replacement to the
+ * PACKAGE_NAME string defined in config.h and which is not
+ * public by default.
+ * return the SISCone name as a string
+ */
+string siscone_package_name(){
+  return PACKAGE_NAME;
+}
+
+/* 
+ * return SISCone version number.
+ * return a string of the form "X.Y.Z" with possible additional tag
+ *        (alpha, beta, devel) to mention stability status
+ */
+string siscone_version(){
+  return VERSION;
+}
+
+}
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/siscone.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/siscone.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/siscone.h	(revision 5)
@@ -0,0 +1,151 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: siscone.h                                                           //
+// Description: header file for the main SISCone class                       //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SISCONE_H__
+#define __SISCONE_H__
+
+#include "protocones.h"
+#include "split_merge.h"
+
+namespace siscone{
+
+/**
+ * \class Csiscone
+ * final class: gather everything to compute the jet contents.
+ * 
+ * This is the class user should use.
+ * It computes the jet contents of a list of particles
+ * given a cone radius and a threshold for splitting/merging.
+ *
+ * After the call to 'perform', the vector jets is filled with
+ * the jets found. the 'contents' field of each jets contains
+ * the indices of the particles included in that jet. 
+ */
+class Csiscone : public Cstable_cones, public Csplit_merge{
+ public:
+  /// default ctor
+  Csiscone();
+
+  /// default dtor
+  ~Csiscone();
+
+  /**
+   * compute the jets from a given particle set.
+   * We are doing multiple passes such pass n_pass looks for jets among 
+   * all particles not put into jets during previous passes.
+   * By default the number of passes is infinite (0). 
+   * \param _particles   list of particles
+   * \param _radius      cone radius
+   * \param _f           shared energy threshold for splitting&merging
+   * \param _n_pass_max  maximum number of passes (0=full search)
+   * \param _ptmin       minimum pT of the protojets
+   * \param _split_merge_scale    the scale choice for the split-merge procedure
+   *        NOTE: SM_pt leads to IR unsafety for some events with momentum conservation. 
+   *              SM_Et is IR safe but not boost invariant and not implemented(!)
+   *              SM_mt is IR safe for hadronic events, but not for decays of two 
+   *                    back-to-back particles of identical mass
+   *              SM_pttilde  
+   *                    is always IR safe, and also boost invariant (default)
+   *
+   * \return the number of jets found.
+   */
+  int compute_jets(std::vector<Cmomentum> &_particles, double _radius, double _f, 
+		   int _n_pass_max=0, double _ptmin=0.0,
+		   Esplit_merge_scale _split_merge_scale=SM_pttilde);
+
+  /**
+   * recompute the jets with a different overlap parameter.
+   * we use the same particles and R as in the preceeding call.
+   * \param _f           shared energy threshold for splitting&merging
+   * \param _ptmin       minimum pT of the protojets
+   * \param _split_merge_scale    the scale choice for the split-merge procedure
+   *                                           split--merge variable
+   *        NOTE: using pt leads to IR unsafety for some events with momentum
+   *              conservation. So we strongly advise not to change the default
+   *              value.
+   * \return the number of jets found, -1 if recomputation not allowed.
+   */
+  int recompute_jets(double _f, double _ptmin = 0.0,
+		     Esplit_merge_scale _split_merge_scale=SM_pttilde);
+
+  /// list of protocones found pass-by-pass
+  std::vector<std::vector<Cmomentum> > protocones_list;
+
+  // random number initialisation
+  static bool init_done;      ///< check random generator initialisation
+
+#ifdef DEBUG_STABLE_CONES
+  int nb_hash_cones_total, nb_hash_occupied_total;
+#endif
+
+  /**
+   * A call to this function modifies the stream
+   * used to print banners (by default cout).
+   *
+   * Please note that if you distribute 3rd party code
+   * that links with SISCone, that 3rd party code must not
+   * use this call turn off the printing of thw banner
+   * by default. This requirement reflects the spirit of
+   * clause 2c of the GNU Public License (v2), under which
+   * SISCone is distributed.
+   */
+  static void set_banner_stream(std::ostream * ostr) {_banner_ostr = ostr;}
+
+  /**
+   * returns a pointer to the stream to be used to print banners
+   * (cout by default)
+   */
+  static std::ostream * banner_stream() {return _banner_ostr;}
+
+ private:
+  bool rerun_allowed;         ///< is recompute_jets allowed ?
+  static std::ostream * _banner_ostr; ///< stream to use for banners
+};
+
+  
+// finally, a bunch of functions to access to 
+// basic information (package name, version)
+//---------------------------------------------
+
+/** 
+ * return SISCone package name.
+ * This is nothing but "SISCone", it is a replacement to the
+ * PACKAGE_NAME string defined in config.h and which is not
+ * public by default.
+ * \return the SISCone name as a string
+ */
+std::string siscone_package_name();
+
+/** 
+ * return SISCone version number.
+ * \return a string of the form "X.Y.Z" with possible additional tag
+ *         (alpha, beta, devel) to mention stability status
+ */
+std::string siscone_version();
+
+}
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/siscone_error.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/siscone_error.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/siscone_error.cc	(revision 5)
@@ -0,0 +1,33 @@
+///////////////////////////////////////////////////////////////////////////////
+// File: siscone_error.cpp                                                   //
+// Description: source file for SISCone error messages (Csiscone_error)      //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "siscone_error.h"
+
+namespace siscone{
+
+bool Csiscone_error::m_print_errors = true;
+
+}
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/siscone_error.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/siscone_error.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/siscone_error.h	(revision 5)
@@ -0,0 +1,64 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: siscone_error.h                                                     //
+// Description: header file for SISCone error messages (Csiscone_error)      //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SISCONE_ERROR_H__
+#define __SISCONE_ERROR_H__
+
+#include<iostream>
+#include<string>
+
+namespace siscone{
+
+/// \class Csiscone_error
+/// class corresponding to errors that will be thrown by siscone
+class Csiscone_error {
+public:
+  /// default ctor
+  Csiscone_error() {;};
+
+  /// ctor with a given error message
+  ///  \param message_in   the error message to be printed
+  Csiscone_error(const std::string & message_in) {
+    m_message = message_in; 
+    if (m_print_errors) std::cerr << "siscone::Csiscone_error: "<< message_in << std::endl;
+  };
+
+  /// access to the error message
+  std::string message() const {return m_message;};
+
+  /// switch on/off the error message printing
+  ///  \param print_errors   errors will be printed when true
+  static void setm_print_errors(bool print_errors) {
+    m_print_errors = print_errors;};
+
+private:
+  std::string m_message;       ///< the error message
+  static bool m_print_errors;  ///< do we print error messages?
+};
+
+}
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/split_merge.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/split_merge.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/split_merge.cc	(revision 5)
@@ -0,0 +1,1037 @@
+///////////////////////////////////////////////////////////////////////////////
+// File: split_merge.cpp                                                     //
+// Description: source file for splitting/merging (contains the CJet class)  //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "split_merge.h"
+#include "siscone_error.h"
+#include "momentum.h"
+#include <math.h>
+#include <limits>   // for max
+#include <iostream>
+#include <algorithm>
+#include <sstream>
+#include <cassert>
+
+namespace siscone{
+
+using namespace std;
+
+/********************************************************
+ * class Cjet implementation                            *
+ * real Jet information.                                *
+ * This class contains information for one single jet.  *
+ * That is, first, its momentum carrying information    *
+ * about its centre and pT, and second, its particle    *
+ * contents                                             *
+ ********************************************************/
+// default ctor
+//--------------
+Cjet::Cjet(){
+  n = 0;
+  v = Cmomentum();
+  pt_tilde = 0.0;
+  sm_var2 = 0.0;
+}
+
+// default dtor
+//--------------
+Cjet::~Cjet(){
+
+}
+
+// ordering of jets in pt (e.g. used in final jets ordering)
+//-----------------------------------------------------------
+bool jets_pt_less(const Cjet &j1, const Cjet &j2){
+  return j1.v.perp2() > j2.v.perp2();
+}
+
+
+/********************************************************
+ * Csplit_merge_ptcomparison implementation             *
+ * This deals with the ordering of the jets candidates  *
+ ********************************************************/
+
+// odering of two jets
+// The variable of the ordering is pt or mt 
+// depending on 'split_merge_scale' choice
+//
+// with EPSILON_SPLITMERGE defined, this attempts to identify
+// delicate cases where two jets have identical momenta except for
+// softish particles -- the difference of pt's may not be correctly
+// identified normally and so lead to problems for the fate of the
+// softish particle.
+//
+// NB: there is a potential issue in momentum-conserving events,
+// whereby the harder of two jets becomes ill-defined when a soft
+// particle is emitted --- this may have a knock-on effect on
+// subsequent split-merge steps in cases with sufficiently large R
+// (but we don't know what the limit is...)
+//------------------------------------------------------------------
+bool Csplit_merge_ptcomparison::operator ()(const Cjet &jet1, const Cjet &jet2) const{
+  double q1, q2;
+
+  // compute the value for comparison for both jets
+  // This depends on the choice of variable (mt is the default)
+  q1 = jet1.sm_var2;
+  q2 = jet2.sm_var2;
+
+  bool res = q1 > q2;
+
+  // if we enable the refined version of the comparison (see defines.h),
+  // we compute the difference more precisely when the two jets are very
+  // close in the ordering variable.
+#ifdef EPSILON_SPLITMERGE
+  if ( (fabs(q1-q2) < EPSILON_SPLITMERGE*max(q1,q2)) &&
+       (jet1.v.ref != jet2.v.ref) ) {
+    // get the momentum of the difference
+    Cmomentum difference;
+    double pt_tilde_difference;
+    get_difference(jet1,jet2,&difference,&pt_tilde_difference);
+    
+    // use the following relation: pt1^2 - pt2^2 = (pt1+pt2)*(pt1-pt2)
+    double qdiff;
+    Cmomentum sum = jet1.v ;
+    sum +=  jet2.v;
+    double pt_tilde_sum = jet1.pt_tilde + jet2.pt_tilde;
+    
+    // depending on the choice of ordering variable, set the result
+    switch (split_merge_scale){
+    case SM_mt:
+      qdiff = sum.E*difference.E - sum.pz*difference.pz;
+      break;
+    case SM_pt:
+      qdiff = sum.px*difference.px + sum.py*difference.py;
+      break;
+    case SM_pttilde:  
+      qdiff = pt_tilde_sum*pt_tilde_difference;
+      break;
+    case SM_Et:
+      // diff = E^2 (dpt^2 pz^2- pt^2 dpz^2)
+      //      + dE^2 (pt^2+pz^2) pt2^2
+      // where, unless explicitely specified the variables
+      // refer to the first jet or differences jet1-jet2.
+      qdiff = jet1.v.E*jet1.v.E*
+	((sum.px*difference.px + sum.py*difference.py)*jet1.v.pz*jet1.v.pz
+	 -jet1.v.perp2()*sum.pz*difference.pz)
+	+sum.E*difference.E*(jet1.v.perp2()+jet1.v.pz*jet1.v.pz)*jet2.v.perp2();
+      break;
+    default:
+      throw Csiscone_error("Unsupported split-merge scale choice: "
+			   + SM_scale_name());
+    }
+    res = qdiff > 0;
+  }
+#endif  // EPSILON_SPLITMERGE
+
+  return res;
+}
+
+
+/// return a name for the sm scale choice 
+/// NB: used internally and also by fastjet
+std::string split_merge_scale_name(Esplit_merge_scale sms) {
+  switch(sms) {
+  case SM_pt:
+    return "pt (IR unsafe)";
+  case SM_Et:
+    return "Et (boost dep.)";
+  case SM_mt:
+    return "mt (IR safe except for pairs of identical decayed heavy particles)";
+  case SM_pttilde:
+    return "pttilde (scalar sum of pt's)";
+  default:
+    return "[SM scale without a name]";
+  }
+}
+
+
+// get the difference between 2 jets
+//  - j1         first jet
+//  - j2         second jet
+//  - v          jet1-jet2
+//  - pt_tilde   jet1-jet2 pt_tilde
+// return true if overlapping, false if disjoint
+//-----------------------------------------------
+void Csplit_merge_ptcomparison::get_difference(const Cjet &j1, const Cjet &j2, Cmomentum *v, double *pt_tilde) const {
+  int i1,i2;
+
+  // initialise
+  i1=i2=0;
+  *v = Cmomentum();
+  *pt_tilde = 0.0;
+
+  // compute overlap
+  // at the same time, we store union in indices
+  do{
+    if (j1.contents[i1]==j2.contents[i2]) {
+      i1++;
+      i2++;
+    } else if (j1.contents[i1]<j2.contents[i2]){
+      (*v) += (*particles)[j1.contents[i1]];
+      (*pt_tilde) += (*pt)[j1.contents[i1]];
+      i1++;
+    } else if (j1.contents[i1]>j2.contents[i2]){
+      (*v) -= (*particles)[j2.contents[i2]];
+      (*pt_tilde) -= (*pt)[j2.contents[i2]];
+      i2++;
+    } else {
+      throw Csiscone_error("get_non_overlap reached part it should never have seen...");
+    }
+  } while ((i1<j1.n) && (i2<j2.n));
+
+  // deal with particles at the end of the list...
+  while (i1 < j1.n) {
+    (*v) += (*particles)[j1.contents[i1]];
+    (*pt_tilde) += (*pt)[j1.contents[i1]];
+    i1++;
+  }
+  while (i2 < j2.n) {
+    (*v) -= (*particles)[j2.contents[i2]];
+    (*pt_tilde) -= (*pt)[j2.contents[i2]];
+    i2++;
+  }
+}
+
+
+/********************************************************
+ * class Csplit_merge implementation                    *
+ * Class used to split and merge jets.                  *
+ ********************************************************/
+// default ctor
+//--------------
+Csplit_merge::Csplit_merge(){
+  merge_identical_protocones = false;
+#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
+#ifdef MERGE_IDENTICAL_PROTOCONES_DEFAULT_TRUE
+  merge_identical_protocones = true;
+#endif
+#endif
+  indices = NULL;
+
+  // ensure that ptcomparison points to our set of particles (though params not correct)
+  ptcomparison.particles = &particles;
+  ptcomparison.pt = &pt;
+  candidates.reset(new multiset<Cjet,Csplit_merge_ptcomparison>(ptcomparison));
+
+  // no hardest cut (col-unsafe)
+  SM_var2_hardest_cut_off = -1.0;
+
+  // no pt cutoff for the particles to put in p_uncol_hard
+  stable_cone_soft_pt2_cutoff = -1.0;
+
+  // no pt-weighted splitting
+  use_pt_weighted_splitting = false;
+}
+
+
+// default dtor
+//--------------
+Csplit_merge::~Csplit_merge(){
+  full_clear();
+}
+
+
+// initialisation function
+//  - _particles  list of particles
+//  - protocones  list of protocones (initial jet candidates)
+//  - R2          cone radius (squared)
+//  - ptmin       minimal pT allowed for jets
+//-------------------------------------------------------------
+int Csplit_merge::init(vector<Cmomentum> & /*_particles*/, vector<Cmomentum> *protocones, double R2, double ptmin){
+  // browse protocones
+  return add_protocones(protocones, R2, ptmin);
+}
+
+
+// initialisation function for particle list
+//  - _particles  list of particles
+//-------------------------------------------------------------
+int Csplit_merge::init_particles(vector<Cmomentum> &_particles){
+  full_clear();
+
+  // compute the list of particles
+  // here, we do not need to throw away particles 
+  // with infinite rapidity (colinear with the beam)
+  particles = _particles;
+  n = particles.size();
+
+  // build the vector of particles' pt
+  pt.resize(n);
+  for (int i=0;i<n;i++)
+    pt[i] = particles[i].perp();
+
+  // ensure that ptcomparison points to our set of particles (though params not correct)
+  ptcomparison.particles = &particles;
+  ptcomparison.pt = &pt;
+
+  // set up the list of particles left.
+  init_pleft();
+
+  indices = new int[n];
+
+  return 0;
+}
+
+
+// build initial list of remaining particles
+//------------------------------------------
+int Csplit_merge::init_pleft(){
+  // at this level, we only rule out particles with 
+  // infinite rapidity
+  // in the parent particle list, index contain the run 
+  // at which particles are puts in jets:
+  //  - -1 means infinity rapidity
+  //  -  0 means not included
+  //  -  i mean included at run i
+  int i,j;
+
+  // copy particles removing the ones with infinite rapidity
+  // determine min,max eta
+  j=0;
+  double eta_min=0.0;  /// for the Ceta_phi_range static member!
+  double eta_max=0.0;  /// for the Ceta_phi_range static member!
+  p_remain.clear();
+  for (i=0;i<n;i++){
+    // set ref for checkxor
+    particles[i].ref.randomize();
+
+    // check if rapidity is not infinite or ill-defined
+    if (fabs(particles[i].pz) < (particles[i].E)){
+      p_remain.push_back(particles[i]);
+      // set up parent index for tracability
+      p_remain[j].parent_index = i;
+      // left particles are marked with a 1
+      // IMPORTANT NOTE: the meaning of index in p_remain is
+      //   somehow different as in the initial particle list.
+      //   here, within one pass, we use the index to track whether
+      //   a particle is included in the current pass (index set to 0
+      //   in add_protocones) or still remain (index still 1)
+      p_remain[j].index = 1;
+
+      j++;
+      // set up parent-particle index
+      particles[i].index = 0;
+
+      eta_min = min(eta_min, particles[i].eta);
+      eta_max = max(eta_max, particles[i].eta);
+    } else {
+      particles[i].index = -1;
+    }
+  }
+  n_left = p_remain.size();
+  n_pass = 0;
+
+  Ceta_phi_range epr;
+  epr.eta_min = eta_min-0.01;
+  epr.eta_max = eta_max+0.01;
+
+  merge_collinear_and_remove_soft();
+
+  return 0;
+}
+
+
+// partial clearance
+// we want to keep   particle list and indices
+// for future usage, so do not clear it !
+// this is done in full_clear
+//----------------------------------------
+int Csplit_merge::partial_clear(){
+  // release jets
+
+  // set up the auto_ptr for the multiset with the _current_ state of
+  // ptcomparison (which may have changed since we constructed the
+  // class)
+  candidates.reset(new multiset<Cjet,Csplit_merge_ptcomparison>(ptcomparison));
+
+  // start off with huge number
+  most_ambiguous_split = numeric_limits<double>::max();
+
+  jets.clear();
+#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
+  if (merge_identical_protocones)
+    cand_refs.clear();
+#endif
+
+  p_remain.clear();
+
+  return 0;
+}
+
+
+// full clearance
+//----------------
+int Csplit_merge::full_clear(){
+  partial_clear();
+
+  // clear previously allocated memory
+  if (indices != NULL){
+    delete[] indices;
+  }
+  particles.clear();
+
+  return 0;
+}
+
+
+// build the list 'p_uncol_hard' from p_remain by clustering collinear particles
+// note that thins in only used for stable-cone detection 
+// so the parent_index field is unnecessary
+//-------------------------------------------------------------------------
+int Csplit_merge::merge_collinear_and_remove_soft(){
+  int i,j;
+  vector<Cmomentum> p_sorted;
+  bool collinear;
+  double dphi;
+
+  p_uncol_hard.clear();
+
+  // we first sort the particles according to their rapidity
+  for (i=0;i<n_left;i++)
+    p_sorted.push_back(p_remain[i]);
+  sort(p_sorted.begin(), p_sorted.end(), momentum_eta_less);
+
+  // then we cluster particles looping over the particles in the following way
+  // if (a particle i has same eta-phi a one after (j))
+  // then add momentum i to j
+  // else add i to the p_uncol_hard list
+  i = 0;
+  while (i<n_left){
+    // check if the particle passes the stable_cone_soft_pt2_cutoff
+    if (p_sorted[i].perp2()<stable_cone_soft_pt2_cutoff) {
+      i++;
+      continue;
+    }
+
+    // check if there is(are) particle(s) with the 'same' eta
+    collinear = false;
+    j=i+1;
+    while ((j<n_left) && (fabs(p_sorted[j].eta-p_sorted[i].eta)<EPSILON_COLLINEAR) && (!collinear)){
+      dphi = fabs(p_sorted[j].phi-p_sorted[i].phi);
+      if (dphi>M_PI) dphi = twopi-dphi;
+      if (dphi<EPSILON_COLLINEAR){
+	// i is collinear with j; add the momentum (i) to the momentum (j) 
+	p_sorted[j] += p_sorted[i];
+	// set collinearity test to true
+	collinear = true;
+      }
+      j++;
+    }
+    // if no collinearity detected, add the particle to our list
+    if (!collinear)
+      p_uncol_hard.push_back(p_sorted[i]);
+    i++;
+  }
+
+  return 0;
+}
+
+
+// add a list of protocones
+//  - protocones  list of protocones (initial jet candidates)
+//  - R2          cone radius (squared)
+//  - ptmin       minimal pT allowed for jets
+//-------------------------------------------------------------
+int Csplit_merge::add_protocones(vector<Cmomentum> *protocones, double R2, double ptmin){
+  int i;
+  Cmomentum *c;
+  Cmomentum *v;
+  double eta, phi;
+  double dx, dy;
+  double R;
+  Cjet jet;
+
+  if (protocones->size()==0)
+    return 1;
+
+  pt_min2 = ptmin*ptmin;
+  R = sqrt(R2);
+
+  // browse protocones
+  // for each of them, build the list of particles in them
+  for (vector<Cmomentum>::iterator p_it = protocones->begin();p_it != protocones->end();p_it++){
+    // initialise variables
+    c = &(*p_it);
+
+    // note: cones have been tested => their (eta,phi) coordinates are computed
+    eta = c->eta;
+    phi = c->phi;
+
+    // browse particles to create cone contents
+    // note that jet is always initialised with default values at this level
+    jet.v = Cmomentum();
+    jet.pt_tilde=0;
+    jet.contents.clear();
+    for (i=0;i<n_left;i++){
+      v = &(p_remain[i]);
+      // for security, avoid including particles with infinite rapidity)
+      // NO NEEDED ANYMORE SINCE REMOVED FROM p_remain FROM THE BEGINNING
+      //if (fabs(v->pz)!=v->E){
+      dx = eta - v->eta;
+      dy = fabs(phi - v->phi);
+      if (dy>M_PI) 
+	dy -= twopi;
+      if (dx*dx+dy*dy<R2){
+	jet.contents.push_back(v->parent_index);
+	jet.v+= *v;
+	jet.pt_tilde+= pt[v->parent_index];
+	v->index=0;
+      }
+    }
+    jet.n=jet.contents.size();
+
+    // set the momentum in protocones 
+    // (it was only known through eta and phi up to now)
+    *c = jet.v;
+    c->eta = eta; // restore exact original coords
+    c->phi = phi; // to avoid rounding error inconsistencies
+
+    // set the jet range
+    jet.range=Ceta_phi_range(eta,phi,R);
+
+#ifdef DEBUG_SPLIT_MERGE
+    cout << "adding jet: ";
+    for (int i2=0;i2<jet.n;i2++)
+      cout << jet.contents[i2] << " ";
+    cout << endl;
+#endif
+
+    // add it to the list of jets
+    insert(jet);
+  }
+  
+  // update list of included particles
+  n_pass++;
+
+#ifdef DEBUG_SPLIT_MERGE
+  cout << "remaining particles: "; 
+#endif
+  int j=0;
+  for (i=0;i<n_left;i++){
+    if (p_remain[i].index){
+      // copy particle
+      p_remain[j]=p_remain[i];
+      p_remain[j].parent_index = p_remain[i].parent_index;
+      p_remain[j].index=1;
+      // set run in initial list
+      particles[p_remain[j].parent_index].index = n_pass;
+#ifdef DEBUG_SPLIT_MERGE
+      cout << p_remain[j].parent_index << " ";
+#endif
+      j++;
+    }
+  }
+#ifdef DEBUG_SPLIT_MERGE
+  cout << endl;
+#endif
+  n_left = j;
+  p_remain.resize(j);
+
+  merge_collinear_and_remove_soft();
+
+  return 0;
+}
+
+
+/*
+ * really do the splitting and merging
+ * At the end, the vector jets is filled with the jets found.
+ * the 'contents' field of each jets contains the indices
+ * of the particles included in that jet. 
+ *  - overlap_tshold    threshold for splitting/merging transition
+ *  - ptmin             minimal pT allowed for jets
+ * return the number of jets is returned
+ ******************************************************************/
+int Csplit_merge::perform(double overlap_tshold, double ptmin){
+  // iterators for the 2 jets
+  cjet_iterator j1;
+  cjet_iterator j2;
+
+  pt_min2 = ptmin*ptmin;
+
+  if (candidates->size()==0)
+    return 0;
+
+  if (overlap_tshold>=1.0 || overlap_tshold <= 0) {
+    ostringstream message;
+    message << "Illegal value for overlap_tshold, f = " << overlap_tshold;
+    message << "  (legal values are 0<f<1)";
+    throw Csiscone_error(message.str());
+  }
+
+  // overlap (the contents of this variable depends on the choice for
+  // the split--merge variable.)
+  // Note that the square of the ovelap is used
+  double overlap2;
+
+  // avoid to compute tshold*tshold at each overlap
+  double overlap_tshold2 = overlap_tshold*overlap_tshold;
+
+  do{
+    if (candidates->size()>0){
+      // browse for the first jet
+      j1 = candidates->begin();
+      
+      // if hardest jet does not pass threshold then nothing else will
+      // either so one stops the split merge.
+      if (j1->sm_var2<SM_var2_hardest_cut_off) {break;}
+
+      // browse for the second jet
+      j2 = j1;
+      j2++;
+      int j2_relindex = 1; // used only in ifdef, but costs little so keep it outside
+
+      while (j2 != candidates->end()){
+#ifdef DEBUG_SPLIT_MERGE
+	show();
+#endif
+	// check overlapping
+	if (get_overlap(*j1, *j2, &overlap2)){
+	  // check if overlapping energy passes threshold
+	  // Note that this depends on the ordering variable
+#ifdef DEBUG_SPLIT_MERGE
+          cout << "overlap between cdt 1 and cdt " << j2_relindex+1 << " with overlap " 
+               << sqrt(overlap2/j2->sm_var2) << endl<<endl;
+#endif
+	  if (overlap2<overlap_tshold2*j2->sm_var2){
+	    // split jets
+	    split(j1, j2);
+	    
+	    // update iterators
+	    j2 = j1 = candidates->begin();
+            j2_relindex = 0;
+	  } else {
+	    // merge jets
+	    merge(j1, j2);
+	    
+	    // update iterators
+	    j2 = j1 = candidates->begin();
+            j2_relindex = 0;
+	  }
+	}
+        // watch out: split/merge might have caused new jets with pt <
+        // ptmin to disappear, so the total number of jets may
+        // have changed by more than expected and j2 might already by
+        // the end of the candidates list...
+        j2_relindex++;
+	if (j2 != candidates->end()) j2++;
+      } // end of loop on the second jet
+      
+      if (j1 != candidates->end()) {
+        // all "second jet" passed without overlapping
+        // (otherwise we won't leave the j2 loop)
+        // => store jet 1 as real jet
+        jets.push_back(*j1);
+        jets[jets.size()-1].v.build_etaphi();
+        // a bug where the contents has non-zero size has been cropping
+        // up in many contexts -- so catch it!
+        assert(j1->contents.size() > 0);
+        jets[jets.size()-1].pass = particles[j1->contents[0]].index;
+#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
+        cand_refs.erase(j1->v.ref);
+#endif
+        candidates->erase(j1);
+
+	//// test that the hardest jet pass the potential cut-off
+	//if ((candidates->size()!=0) && 
+	//    (candidates->begin()->sm_var2<SM_var2_hardest_cut_off)){
+	//  candidates->clear();
+	//}
+      }
+    }
+  } while (candidates->size()>0);
+
+  // sort jets by pT
+  sort(jets.begin(), jets.end(), jets_pt_less);
+#ifdef DEBUG_SPLIT_MERGE
+      show();
+#endif
+
+  return jets.size();
+}
+
+
+
+// save the event on disk
+//  - flux   stream used to save jet contents
+//--------------------------------------------
+int Csplit_merge::save_contents(FILE *flux){
+  jet_iterator it_j;
+  Cjet *j1;
+  int i1, i2;
+
+  fprintf(flux, "# %d jets found\n", (int) jets.size());
+  fprintf(flux, "# columns are: eta, phi, pt and number of particles for each jet\n");
+  for (it_j = jets.begin(), i1=0 ; it_j != jets.end() ; it_j++, i1++){
+    j1 = &(*it_j);
+    j1->v.build_etaphi();
+    fprintf(flux, "%f\t%f\t%e\t%d\n", 
+	    j1->v.eta, j1->v.phi, j1->v.perp(), j1->n);
+  }
+  
+  fprintf(flux, "# jet contents\n");
+  fprintf(flux, "# columns are: eta, phi, pt, particle index and jet number\n");
+  for (it_j = jets.begin(), i1=0 ; it_j != jets.end() ; it_j++, i1++){
+    j1 = &(*it_j);
+    for (i2=0;i2<j1->n;i2++)
+      fprintf(flux, "%f\t%f\t%e\t%d\t%d\n", 
+      	      particles[j1->contents[i2]].eta, particles[j1->contents[i2]].phi,
+      	      particles[j1->contents[i2]].perp(), j1->contents[i2], i1);
+  }
+  
+  return 0;
+}
+
+
+// show current jets/candidate status
+//------------------------------------
+int Csplit_merge::show(){
+  jet_iterator it_j;
+  cjet_iterator it_c;
+  Cjet *j;
+  const Cjet *c;
+  int i1, i2;
+
+  for (it_j = jets.begin(), i1=0 ; it_j != jets.end() ; it_j++, i1++){
+    j = &(*it_j);
+    fprintf(stdout, "jet %2d: %e\t%e\t%e\t%e\t", i1+1,
+	    j->v.px, j->v.py, j->v.pz, j->v.E);
+    for (i2=0;i2<j->n;i2++)
+      fprintf(stdout, "%d ", j->contents[i2]);
+    fprintf(stdout, "\n");
+  }
+  
+  for (it_c = candidates->begin(), i1=0 ; it_c != candidates->end() ; it_c++, i1++){
+    c = &(*it_c);
+    fprintf(stdout, "cdt %2d: %e\t%e\t%e\t%e\t%e\t", i1+1,
+	    c->v.px, c->v.py, c->v.pz, c->v.E, sqrt(c->sm_var2));
+    for (i2=0;i2<c->n;i2++)
+      fprintf(stdout, "%d ", c->contents[i2]);
+    fprintf(stdout, "\n");
+  }
+  
+  fprintf(stdout, "\n");
+  return 0;
+}
+
+
+// get the overlap between 2 jets
+//  - j1        first jet
+//  - j2        second jet
+//  - overlap2  returned overlap^2 (determined by the choice of SM variable)
+// return true if overlapping, false if disjoint
+//---------------------------------------------------------------------
+bool Csplit_merge::get_overlap(const Cjet &j1, const Cjet &j2, double *overlap2){
+  // check if ranges overlap
+  if (!is_range_overlap(j1.range,j2.range))
+    return false;
+
+  int i1,i2;
+  bool is_overlap;
+
+  // initialise
+  i1=i2=idx_size=0;
+  is_overlap = false;
+  Cmomentum v;
+  double pt_tilde=0.0;
+
+  // compute overlap
+  // at the same time, we store union in indices
+  do{
+    if (j1.contents[i1]<j2.contents[i2]){
+      indices[idx_size] = j1.contents[i1];
+      i1++;
+    } else if (j1.contents[i1]>j2.contents[i2]){
+      indices[idx_size] = j2.contents[i2];
+      i2++;
+    } else { // (j1.contents[i1]==j2.contents[i2])
+      v += particles[j1.contents[i1]];
+      pt_tilde += pt[j1.contents[i1]];
+      indices[idx_size] = j1.contents[i1];
+      i1++;
+      i2++;
+      is_overlap = true;
+    }
+    idx_size++;
+  } while ((i1<j1.n) && (i2<j2.n));
+
+  // finish computing union
+  // (only needed if overlap !)
+  if (is_overlap){
+    while (i1<j1.n){
+      indices[idx_size] = j1.contents[i1];
+      i1++;
+      idx_size++;
+    }
+    while (i2<j2.n){
+      indices[idx_size] = j2.contents[i2];
+      i2++;
+      idx_size++;
+    }
+  }
+
+  // assign the overlapping var as return variable
+  (*overlap2) = get_sm_var2(v, pt_tilde);
+
+  return is_overlap;
+}
+
+
+
+// split the two given jet.
+// during this procedure, the jets j1 & j2 are replaced
+// by 2 new jets. Common particles are associted to the 
+// closest initial jet.
+//  - it_j1  iterator of the first jet in 'candidates'
+//  - it_j2  iterator of the second jet in 'candidates'
+//  - j1     first jet (Cjet instance)
+//  - j2     second jet (Cjet instance)
+// return true on success, false on error
+////////////////////////////////////////////////////////////////
+bool Csplit_merge::split(cjet_iterator &it_j1, cjet_iterator &it_j2){
+  int i1, i2;
+  Cjet jet1, jet2;
+  double eta1, phi1, pt1_weight, eta2, phi2, pt2_weight;
+  double dx1, dy1, dx2, dy2;
+  Cmomentum tmp;
+  Cmomentum *v;
+
+  // shorthand to avoid having "->" all over the place
+  const Cjet & j1 = * it_j1;
+  const Cjet & j2 = * it_j2;
+
+  i1=i2=0;
+  jet2.v = jet1.v = Cmomentum();
+  jet2.pt_tilde = jet1.pt_tilde = 0.0;
+
+  // compute centroids
+  // When use_pt_weighted_splitting is activated, the
+  // "geometrical" distance is weighted by the inverse
+  // of the pt of the protojet
+  // This is stored in pt{1,2}_weight
+  tmp = j1.v;
+  tmp.build_etaphi();
+  eta1 = tmp.eta;
+  phi1 = tmp.phi;
+  pt1_weight = (use_pt_weighted_splitting) ? 1.0/tmp.perp2() : 1.0;
+
+  tmp = j2.v;
+  tmp.build_etaphi();
+  eta2 = tmp.eta;
+  phi2 = tmp.phi;
+  pt2_weight = (use_pt_weighted_splitting) ? 1.0/tmp.perp2() : 1.0;
+
+  jet1.v = jet2.v = Cmomentum();  
+
+  // compute jet splitting
+  do{
+    if (j1.contents[i1]<j2.contents[i2]){
+      // particle i1 belong only to jet 1
+      v = &(particles[j1.contents[i1]]);
+      jet1.contents.push_back(j1.contents[i1]);
+      jet1.v += *v;
+      jet1.pt_tilde += pt[j1.contents[i1]];
+      i1++;
+      jet1.range.add_particle(v->eta,v->phi);
+    } else if (j1.contents[i1]>j2.contents[i2]){
+      // particle i2 belong only to jet 2
+      v = &(particles[j2.contents[i2]]);
+      jet2.contents.push_back(j2.contents[i2]);
+      jet2.v += *v;
+      jet2.pt_tilde += pt[j2.contents[i2]];
+      i2++;
+      jet2.range.add_particle(v->eta,v->phi);
+    } else { // (j1.contents[i1]==j2.contents[i2])
+      // common particle, decide which is the closest centre
+      v = &(particles[j1.contents[i1]]);
+
+      // distance w.r.t. centroid 1
+      dx1 = eta1 - v->eta;
+      dy1 = fabs(phi1 - v->phi);
+      if (dy1>M_PI) 
+	dy1 -= twopi;
+
+      // distance w.r.t. centroid 2
+      dx2 = eta2 - v->eta;
+      dy2 = fabs(phi2 - v->phi);
+      if (dy2>M_PI) 
+	dy2 -= twopi;
+
+      //? what when == ? 
+      // When use_pt_weighted_splitting is activated, the
+      // "geometrical" distance is weighted by the inverse
+      // of the pt of the protojet
+      double d1sq = (dx1*dx1+dy1*dy1)*pt1_weight;
+      double d2sq = (dx2*dx2+dy2*dy2)*pt2_weight;
+      // do bookkeeping on most ambiguous split
+      if (fabs(d1sq-d2sq) < most_ambiguous_split) 
+        most_ambiguous_split = fabs(d1sq-d2sq);
+
+      if (d1sq<d2sq){
+	// particle i1 belong only to jet 1
+	jet1.contents.push_back(j1.contents[i1]);
+	jet1.v += *v;
+	jet1.pt_tilde += pt[j1.contents[i1]];
+	jet1.range.add_particle(v->eta,v->phi);
+      } else {
+	// particle i2 belong only to jet 2
+	jet2.contents.push_back(j2.contents[i2]);
+	jet2.v += *v;
+	jet2.pt_tilde += pt[j2.contents[i2]];
+	jet2.range.add_particle(v->eta,v->phi);
+      }      
+
+      i1++;
+      i2++;
+    }
+  } while ((i1<j1.n) && (i2<j2.n));
+  
+  while (i1<j1.n){
+    v = &(particles[j1.contents[i1]]);
+    jet1.contents.push_back(j1.contents[i1]);
+    jet1.v += *v;
+    jet1.pt_tilde += pt[j1.contents[i1]];
+    i1++;
+    jet1.range.add_particle(v->eta,v->phi);
+  }
+  while (i2<j2.n){
+    v = &(particles[j2.contents[i2]]);
+    jet2.contents.push_back(j2.contents[i2]);
+    jet2.v += *v;
+    jet2.pt_tilde += pt[j2.contents[i2]];
+    i2++;
+    jet2.range.add_particle(v->eta,v->phi);
+  }
+
+  // finalise jets
+  jet1.n = jet1.contents.size();
+  jet2.n = jet2.contents.size();
+
+  //jet1.range = j1.range;
+  //jet2.range = j2.range;
+
+  // remove previous jets
+#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
+  cand_refs.erase(j1.v.ref);
+  cand_refs.erase(j2.v.ref);
+#endif
+  candidates->erase(it_j1);
+  candidates->erase(it_j2);
+
+  // reinsert new ones
+  insert(jet1);
+  insert(jet2);
+
+  return true;
+}
+
+// merge the two given jet.
+// during this procedure, the jets j1 & j2 are replaced
+// by 1 single jets containing both of them.
+//  - it_j1  iterator of the first jet in 'candidates'
+//  - it_j2  iterator of the second jet in 'candidates'
+// return true on success, false on error
+////////////////////////////////////////////////////////////////
+bool Csplit_merge::merge(cjet_iterator &it_j1, cjet_iterator &it_j2){
+  Cjet jet;
+  int i;
+
+  // build new jet
+  // note: particles within j1 & j2 have already been stored in indices
+  for (i=0;i<idx_size;i++){
+    jet.contents.push_back(indices[i]);
+    jet.v += particles[indices[i]];
+    jet.pt_tilde += pt[indices[i]];
+  }
+  jet.n = jet.contents.size();
+
+  // deal with ranges
+  jet.range = range_union(it_j1->range, it_j2->range);
+
+  // remove old candidates
+#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
+  if (merge_identical_protocones){
+    cand_refs.erase(it_j1->v.ref);
+    cand_refs.erase(it_j2->v.ref);
+  }
+#endif
+  candidates->erase(it_j1);
+  candidates->erase(it_j2);
+
+  // reinsert new candidate
+  insert(jet);
+
+  return true;
+}
+
+/**
+ * Check whether or not a jet has to be inserted in the 
+ * list of protojets. If it has, set its sm_variable and
+ * insert it to the list of protojets.
+ */
+bool Csplit_merge::insert(Cjet &jet){
+
+  // eventually check that no other candidate are present with the
+  // same cone contents. We recall that this automatic merging of
+  // identical protocones can lead to infrared-unsafe situations.
+#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
+  if ((merge_identical_protocones) && (!cand_refs.insert(jet.v.ref).second))
+    return false;
+#endif
+
+  // check that the protojet has large enough pt
+  if (jet.v.perp2()<pt_min2)
+    return false;
+
+  // assign SM variable
+  jet.sm_var2 = get_sm_var2(jet.v, jet.pt_tilde);
+
+  // insert the jet.
+  candidates->insert(jet);
+
+  return true;
+}
+
+/**
+ * given a 4-momentum and its associated pT, return the 
+ * variable that has to be used for SM
+ * \param v          4 momentum of the protojet
+ * \param pt_tilde   pt_tilde of the protojet
+ */
+double Csplit_merge::get_sm_var2(Cmomentum &v, double &pt_tilde){
+  switch(ptcomparison.split_merge_scale) {
+  case SM_pt:      return v.perp2();            
+  case SM_mt:      return v.perpmass2();        
+  case SM_pttilde: return pt_tilde*pt_tilde;
+  case SM_Et:      return v.Et2();
+  default:
+    throw Csiscone_error("Unsupported split-merge scale choice: "
+                                 + ptcomparison.SM_scale_name());
+  }
+
+  return 0.0;
+}
+
+}
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/split_merge.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/split_merge.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/split_merge.h	(revision 5)
@@ -0,0 +1,401 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: split_merge.h                                                       //
+// Description: header file for splitting/merging (contains the CJet class)  //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SPLIT_MERGE_H__
+#define __SPLIT_MERGE_H__
+
+#include "defines.h"
+#include "geom_2d.h"
+#include "momentum.h"
+#include <stdio.h>
+#include <vector>
+#include <set>
+#include <memory>
+#include <string>
+
+namespace siscone{
+
+/**
+ * \class Cjet
+ * real Jet information.
+ *
+ * This class contains information for one single jet. 
+ * That is, first, its momentum carrying information
+ * about its centre and pT, and second, its particle
+ * contents
+ */
+class Cjet{
+ public:
+  /// default ctor
+  Cjet();
+
+  /// default dtor
+  ~Cjet();
+
+  Cmomentum v;               ///< jet momentum
+  double pt_tilde;           ///< p-scheme pt
+  int n;                     ///< number of particles inside
+  std::vector<int> contents; ///< particle contents (list of indices)
+
+  /// ordering variable used for ordering and overlap in the
+  /// split--merge. This variable is automatically set either to
+  /// pt_tilde, or to mt or to pt, depending on the siscone
+  /// parameter. Note that the default behaviour is pt_tilde and that
+  /// other chices may lead to infrared unsafe situations.
+  /// Note: we use the square of the varible rather than the variable itself
+  double sm_var2;
+
+  /// covered range in eta-phi
+  Ceta_phi_range range;
+
+  /// pass at which the jet has been found
+  /// It starts at 0 (first pass), -1 means infinite rapidity
+  int pass;
+};
+
+/// ordering of jets in pt (e.g. used in final jets ordering)
+bool jets_pt_less(const Cjet &j1, const Cjet &j2);
+  
+
+/// the choices of scale variable that can be used in the split-merge
+/// step, both for ordering the protojets and for measuing their
+/// overlap; pt, Et and mt=sqrt(pt^2+m^2) are all defined in E-scheme
+/// (4-momentum) recombination; pttilde = \sum_{i\in jet} |p_{t,i}|
+///
+/// NB: if one changes the order here, one _MUST_ also change the order
+///     in the SISCone plugin
+enum Esplit_merge_scale {
+           SM_pt,     ///< transverse momentum (E-scheme), IR unsafe
+           SM_Et,     ///< transverse energy (E-scheme), not long. boost inv.
+                      ///< original run-II choice [may not be implemented]
+           SM_mt,     ///< transverse mass (E-scheme), IR safe except
+                      ///< in decays of two identical narrow heavy particles
+           SM_pttilde ///< pt-scheme pt = \sum_{i in jet} |p_{ti}|, should
+                      ///< be IR safe in all cases
+};
+
+/// return the name of the split-merge scale choice
+std::string split_merge_scale_name(Esplit_merge_scale sms);
+
+/**
+ * \class Csplit_merge_ptcomparison
+ * comparison of jets for split--merge ordering
+ *
+ * a class that allows us to carry out comparisons of pt of jets, using
+ * information from exact particle contents where necessary.
+ */
+class Csplit_merge_ptcomparison{
+public:
+  /// default ctor
+  Csplit_merge_ptcomparison() : 
+    particles(0), split_merge_scale(SM_pttilde){};
+
+  /// return the name corresponding to the SM scale variable
+  std::string SM_scale_name() const {
+    return split_merge_scale_name(split_merge_scale);}
+
+  std::vector<Cmomentum> * particles; ///< pointer to the list of particles
+  std::vector<double> * pt;           ///< pointer to the pt of the particles
+
+  /// comparison between 2 jets
+  bool operator()(const Cjet &jet1, const Cjet &jet2) const;
+
+  /**
+   * get the difference between 2 jets, calculated such that rounding
+   * errors will not affect the result even if the two jets have
+   * almost the same content (so that the difference is below the
+   * rounding errors)
+   *
+   * \param j1        first jet
+   * \param j2        second jet
+   * \param v         jet1-jet2
+   * \param pt_tilde  jet1-jet2 pt_tilde
+   */
+  void get_difference(const Cjet &j1, const Cjet &j2, Cmomentum *v, double *pt_tilde) const;
+
+  /// the following parameter controls the variable we're using for 
+  /// the split-merge process i.e. the variable we use for 
+  ///  1. ordering jet candidates;
+  ///  2. computing te overlap fraction of two candidates.
+  /// The default value uses pttile (p-scheme pt). Other alternatives are
+  /// pt, mt=sqrt(pt^2+m^2)=sqrt(E^2-pz^2) or Et. 
+  /// NOTE: Modifying the default choice can have nasty effects:
+  /// - using pt leads to some IR unsafety when we have two jets,
+  ///   e.g. back-to-back, with the same pt. In that case, their ordering
+  ///   in pt is random and can be affected by the addition of a
+  ///   soft particle.  Hence, we highly recommand to keep this to
+  ///   the default value i.e.  to use pt only for the purpose of
+  ///   investigating the IR issue
+  /// - using Et is safe but do not respect boost invariance
+  /// - using mt solves the IR unsafety issues with the pt variable
+  ///   for QCD jets but the IR unsafety remains for nack-to-back 
+  ///   jets of unstable narrow-width particles (e.g. Higgs).
+  /// Therefore, keeping the default value is strongly advised.
+  Esplit_merge_scale split_merge_scale;
+};
+
+
+// iterator types
+/// iterator definition for the jet candidates structure
+typedef std::multiset<siscone::Cjet,Csplit_merge_ptcomparison>::iterator cjet_iterator;
+
+/// iterator definition for the jet structure
+typedef std::vector<siscone::Cjet>::iterator jet_iterator;
+
+
+
+/**
+ * \class Csplit_merge
+ * Class used to split and merge jets.
+ */
+class Csplit_merge{
+ public:
+  /// default ctor
+  Csplit_merge();
+
+  /// default dtor
+  ~Csplit_merge();
+
+
+  //////////////////////////////
+  // initialisation functions //
+  //////////////////////////////
+
+  /**
+   * initialisation function
+   * \param _particles  list of particles
+   * \param protocones  list of protocones (initial jet candidates)
+   * \param R2          cone radius (squared)
+   * \param ptmin       minimal pT allowed for jets
+   * \return 0 on success, 1 on error
+   */
+  int init(std::vector<Cmomentum> &_particles, std::vector<Cmomentum> *protocones, double R2, double ptmin=0.0);
+
+  /**
+   * initialisation function for particle list
+   * \param _particles  list of particles
+   * \return 0 on success, 1 on error
+   */
+  int init_particles(std::vector<Cmomentum> &_particles);
+
+  /**
+   * build initial list of left particles
+   */
+  int init_pleft();
+
+  /**
+   * use a pt-dependent boundary for splitting
+   * When called with true, the criterium for splitting two protojets 
+   * will be to compare D1^2/kt1^2 vs. D2^2/kt2^2, the (anti-)kt-weighted 
+   * distance instead of the plain distance D1^2 vs. D2^2.
+   * This can be set in order to produce more circular hard jets, 
+   * with the same underlying philosophy as for the anti-kt algorithm.
+   * We thus expect a behaviour closer to the IterativeCone one. 
+   * By default, we use the standard D1^2 vs. D2^2 comparison and this 
+   * function is not called.
+   */
+  inline int set_pt_weighted_splitting(bool _use_pt_weighted_splitting){
+    use_pt_weighted_splitting = _use_pt_weighted_splitting;
+    return 0;
+  }
+
+  ////////////////////////
+  // cleaning functions //
+  ////////////////////////
+
+  /// partial clearance
+  int partial_clear();
+
+  /// full clearance
+  int full_clear();
+
+
+  /////////////////////////////////
+  // main parts of the algorithm //
+  /////////////////////////////////
+ 
+  /**
+   * build the list 'p_uncol_hard' from p_remain by clustering
+   * collinear particles and removing particles softer than
+   * stable_cone_soft_pt2_cutoff
+   * note that thins in only used for stable-cone detection 
+   * so the parent_index field is unnecessary
+   */
+  int merge_collinear_and_remove_soft();
+
+  /**
+   * add a list of protocones
+   * \param protocones  list of protocones (initial jet candidates)
+   * \param R2          cone radius (squared)
+   * \param ptmin       minimal pT allowed for jets
+   * \return 0 on success, 1 on error
+   */
+  int add_protocones(std::vector<Cmomentum> *protocones, double R2, double ptmin=0.0);
+
+  /**
+   * really do the splitting and merging
+   * At the end, the vector jets is filled with the jets found.
+   * the 'contents' field of each jets contains the indices
+   * of the particles included in that jet. 
+   * \param overlap_tshold  threshold for splitting/merging transition
+   * \param ptmin           minimal pT allowed for jets
+   * \return the number of jets is returned
+   */
+  int perform(double overlap_tshold, double ptmin=0.0);
+
+
+  //////////////////////////////
+  // save and debug functions //
+  //////////////////////////////
+
+  /// save final jets
+  /// \param flux   stream to save the jet contentss
+  int save_contents(FILE *flux);
+
+  /// show jets/candidates status
+  int show();
+
+  // particle information
+  int n;                               ///< number of particles
+  std::vector<Cmomentum> particles;    ///< list of particles
+  std::vector<double> pt;              ///< list of particles' pt
+  int n_left;                          ///< numer of particles that does not belong to any jet
+  std::vector<Cmomentum> p_remain;     ///< list of particles remaining to deal with
+  std::vector<Cmomentum> p_uncol_hard; ///< list of particles remaining with collinear clustering
+  int n_pass;                          ///< index of the run
+
+  /// minimal difference in squared distance between a particle and
+  /// two overlapping protojets when doing a split (useful when
+  /// testing approx. collinear safety)
+  double most_ambiguous_split; 
+
+  // jets information
+  std::vector<Cjet> jets;            ///< list of jets
+
+  // working entries
+  int *indices;                      ///< maximal size array for indices works
+  int idx_size;                      ///< number of elements in indices1
+
+  /// The following flag indicates that identical protocones
+  /// are to be merged automatically each time around the split-merge
+  /// loop and before anything else happens.
+  ///
+  /// This flag is only effective if ALLOW_MERGE_IDENTICAL_PROTOCONES
+  /// is set in 'defines.h'
+  /// Note that this lead to infrared-unsafety so it is disabled
+  /// by default
+  bool merge_identical_protocones;
+
+  /// member used for detailed comparisons of pt's
+  Csplit_merge_ptcomparison ptcomparison;
+
+  /// stop split--merge when the SM_var of the hardest protojet 
+  /// is below this cut-off. 
+  /// This is not collinear-safe so you should not use this
+  /// variable unless you really know what you are doing
+  /// Note that the cut-off is set on the variable squared.
+  double SM_var2_hardest_cut_off;
+
+  /// pt cutoff for the particles to put in p_uncol_hard 
+  /// this is meant to allow removing soft particles in the
+  /// stable-cone search.
+  double stable_cone_soft_pt2_cutoff;
+
+ private:
+  /**
+   * get the overlap between 2 jets
+   * \param j1   first jet
+   * \param j2   second jet
+   * \param v    returned overlap^2 (determined by the choice of SM variable)
+   * \return true if overlapping, false if disjoint
+   */
+  bool get_overlap(const Cjet &j1, const Cjet &j2, double *v);
+
+
+  /**
+   * split the two given jets.
+   * during this procedure, the jets j1 & j2 are replaced
+   * by 2 new jets. Common particles are associted to the 
+   * closest initial jet.
+   * \param it_j1  iterator of the first jet in 'candidates'
+   * \param it_j2  iterator of the second jet in 'candidates'
+   * \param j1     first jet (Cjet instance)
+   * \param j2     second jet (Cjet instance)
+   * \return true on success, false on error
+   */
+  bool split(cjet_iterator &it_j1, cjet_iterator &it_j2);
+
+  /**
+   * merge the two given jet.
+   * during this procedure, the jets j1 & j2 are replaced
+   * by 1 single jets containing both of them.
+   * \param it_j1  iterator of the first jet in 'candidates'
+   * \param it_j2  iterator of the second jet in 'candidates'
+   * \return true on success, false on error
+   */
+  bool merge(cjet_iterator &it_j1, cjet_iterator &it_j2);
+
+  /**
+   * Check whether or not a jet has to be inserted in the 
+   * list of protojets. If it has, set its sm_variable and
+   * insert it to the list of protojets.
+   * \param jet    jet to insert
+   */
+  bool insert(Cjet &jet);
+
+  /**
+   * given a 4-momentum and its associated pT, return the 
+   * variable tht has to be used for SM
+   * \param v          4 momentum of the protojet
+   * \param pt_tilde   pt_tilde of the protojet
+   */
+  double get_sm_var2(Cmomentum &v, double &pt_tilde);
+
+  // jet information
+  /// list of jet candidates
+  std::auto_ptr<std::multiset<Cjet,Csplit_merge_ptcomparison> > candidates;
+
+  /// minimal pt2
+  double pt_min2;
+
+  /**
+   * do we have or not to use the pt-weighted splitting
+   * (see description for set_pt_weighted_splitting)
+   * This will be false by default
+   */
+  bool use_pt_weighted_splitting;
+
+#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
+  /// checkxor for the candidates (to avoid having twice the same contents)
+  std::set<Creference> cand_refs;
+#endif
+};
+
+}
+
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/vicinity.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/vicinity.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/vicinity.cc	(revision 5)
@@ -0,0 +1,295 @@
+///////////////////////////////////////////////////////////////////////////////
+// File: vicinity.cpp                                                        //
+// Description: source file for particle vicinity (Cvicinity class)          //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "vicinity.h"
+#include <math.h>
+#include <algorithm>
+#include <iostream>
+
+namespace siscone{
+
+using namespace std;
+
+/*************************************************************
+ * Cvicinity_elm implementation                              *
+ * element in the vicinity of a parent.                      *
+ * class used to manage one points in the vicinity           *
+ * of a parent point.                                        *
+ *************************************************************/
+
+// ordering pointers to Cvicinity_elm
+//------------------------------------
+bool ve_less(Cvicinity_elm *ve1, Cvicinity_elm *ve2){
+  return ve1->angle < ve2->angle;
+}
+
+
+/*************************************************************
+ * Cvicinity implementation                                  *
+ * list of element in the vicinity of a parent.              *
+ * class used to manage the points which are in the vicinity *
+ * of a parent point. The construction of the list can be    *
+ * made from a list of points or from a quadtree.            *
+ *************************************************************/
+
+// default constructor
+//---------------------
+Cvicinity::Cvicinity(){
+  n_part = 0;
+
+  ve_list = NULL;
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+  quadtree = NULL;
+#endif
+
+  parent = NULL;
+  VR2 = VR = 0.0;
+
+}
+
+// constructor with initialisation
+//---------------------------------
+Cvicinity::Cvicinity(vector<Cmomentum> &_particle_list){
+  parent = NULL;
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+  quadtree = NULL;
+#endif
+  VR2 = VR = 0.0;
+
+  set_particle_list(_particle_list);
+}
+
+// default destructor
+//--------------------
+Cvicinity::~Cvicinity(){
+  if (ve_list!=NULL)
+    delete[] ve_list;
+
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+  if (quadtree!=NULL)
+    delete quadtree;
+#endif
+}
+
+/*
+ * set the particle_list
+ *  - particle_list   list of particles (type Cmomentum)
+ *  - n               number of particles in the list
+ ************************************************************/ 
+void Cvicinity::set_particle_list(vector<Cmomentum> &_particle_list){
+  int i,j;
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+  double eta_max=0.0;
+#endif
+  
+  // if the particle list is not empty, destroy it !
+  if (ve_list!=NULL){
+    delete[] ve_list;
+  }
+  vicinity.clear();
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+  if (quadtree!=NULL)
+    delete quadtree;
+#endif
+
+  // allocate memory array for particles
+  // Note: - we compute max for |eta|
+  //       - we allocate indices to particles
+  n_part = 0;
+  plist.clear();
+  pincluded.clear();
+  for (i=0;i<(int) _particle_list.size();i++){
+    // if a particle is colinear with the beam (infinite rapidity)
+    // we do not take it into account
+    if (fabs(_particle_list[i].pz)!=_particle_list[i].E){
+      plist.push_back(_particle_list[i]);
+      pincluded.push_back(Cvicinity_inclusion()); // zero inclusion status
+
+      // the parent_index is handled in the split_merge because 
+      // of our multiple-pass procedure.
+      // Hence, it is not required here any longer.
+      // plist[n_part].parent_index = i;
+      plist[n_part].index = n_part;
+
+      // make sure the reference is randomly created
+      plist[n_part].ref.randomize();
+
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+      if (fabs(plist[n_part].eta)>eta_max) eta_max=fabs(plist[n_part].eta);
+#endif
+
+      n_part++;
+    }
+  }
+
+  // allocate quadtree and vicinity_elm list
+  // note: we set phi in [-pi:pi] as it is the natural range for atan2!
+  ve_list = new Cvicinity_elm[2*n_part];
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+  eta_max+=0.1;
+  quadtree = new Cquadtree(0.0, 0.0, eta_max, M_PI);
+#endif
+
+  // append particle to the vicinity_elm list
+  j = 0;
+  for (i=0;i<n_part;i++){
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+    quadtree->add(&plist[i]);
+#endif
+    ve_list[j].v = ve_list[j+1].v = &plist[i];
+    ve_list[j].is_inside = ve_list[j+1].is_inside = &(pincluded[i]);
+    j+=2;
+  }
+
+}
+
+
+/*
+ * build the vicinity list from a list of points.
+ *  - _parent   reference particle
+ *  - _VR       vicinity radius
+ ************************************************************/
+void Cvicinity::build(Cmomentum *_parent, double _VR){
+  int i;
+
+  // set parent and radius
+  parent = _parent;
+  VR  = _VR;
+  VR2 = VR*VR;
+  R2  = 0.25*VR2;
+  R   = 0.5*VR;
+  inv_R_EPS_COCIRC  = 1.0 / R / EPSILON_COCIRCULAR;
+  inv_R_2EPS_COCIRC = 0.5 / R / EPSILON_COCIRCULAR;
+
+  // clear vicinity
+  vicinity.clear();
+
+  // init parent variables
+  pcx = parent->eta;
+  pcy = parent->phi;
+
+  // really browse the particle list
+  for (i=0;i<n_part;i++){
+    append_to_vicinity(&plist[i]);
+  }
+
+  // sort the vicinity
+  sort(vicinity.begin(), vicinity.end(), ve_less);
+
+  vicinity_size = vicinity.size();
+}
+
+
+/// strictly increasing function of the angle 
+inline double sort_angle(double s, double c){
+  if (s==0) return (c>0) ? 0.0 : 2.0;
+  double t=c/s;
+  return (s>0) ? 1-t/(1+fabs(t)) : 3-t/(1+fabs(t));
+}
+
+
+/*
+ * append a particle to the 'vicinity' list after
+ * having computed the angular-ordering quantities
+ *  - v   vector to test
+ **********************************************************/
+void Cvicinity::append_to_vicinity(Cmomentum *v){
+  double dx, dy, d2;
+
+  // skip the particle itself)
+  if (v==parent)
+    return;
+
+  int i=2*(v->index);
+
+  // compute the distance of the i-th particle with the parent
+  dx = v->eta - pcx;
+  dy = v->phi - pcy;
+    
+  // pay attention to the periodicity in phi !
+  if (dy>M_PI) 
+    dy -= twopi;
+  else if (dy<-M_PI) 
+    dy += twopi;
+
+  d2 = dx*dx+dy*dy;
+    
+  // really check if the distance is less than VR
+  if (d2<VR2){
+    double s,c,tmp;
+    
+    // compute the angles used for future ordering ...
+    //  - build temporary variables used for the computation
+    //d   = sqrt(d2);
+    tmp = sqrt(VR2/d2-1);
+
+    // first angle (+)
+    c = 0.5*(dx-dy*tmp);  // cosine of (parent,child) pair w.r.t. horizontal
+    s = 0.5*(dy+dx*tmp);  // sine   of (parent,child) pair w.r.t. horizontal
+    ve_list[i].angle = sort_angle(s,c);
+    ve_list[i].eta = pcx+c;
+    ve_list[i].phi = phi_in_range(pcy+s);
+    ve_list[i].side = true;
+    ve_list[i].cocircular.clear();
+    vicinity.push_back(&(ve_list[i]));
+
+    // second angle (-)    
+    c = 0.5*(dx+dy*tmp);  // cosine of (parent,child) pair w.r.t. horizontal
+    s = 0.5*(dy-dx*tmp);  // sine   of (parent,child) pair w.r.t. horizontal
+    ve_list[i+1].angle = sort_angle(s,c);
+    ve_list[i+1].eta = pcx+c;
+    ve_list[i+1].phi = phi_in_range(pcy+s);
+    ve_list[i+1].side = false;
+    ve_list[i+1].cocircular.clear();
+    vicinity.push_back(&(ve_list[i+1]));
+
+    // now work out the cocircularity range for the two points (range
+    // of angle within which the points stay within a distance
+    // EPSILON_COCIRCULAR of circule
+    // P = parent; C = child; O = Origin (center of circle)
+    Ctwovect OP(pcx - ve_list[i+1].eta, phi_in_range(pcy-ve_list[i+1].phi));
+    Ctwovect OC(v->eta - ve_list[i+1].eta, 
+                phi_in_range(v->phi-ve_list[i+1].phi));
+
+    // two sources of error are (GPS CCN29-19) epsilon/(R sin theta)
+    // and sqrt(2*epsilon/(R (1-cos theta))) and the way things work
+    // out, it is the _smaller_ of the two that is relevant [NB have
+    // changed definition of theta here relative to that used in
+    // CCN29] [NB2: write things so as to avoid zero denominators and
+    // to minimize the multiplications, divisions and above all sqrts
+    // -- that means that c & s are defined including a factor of VR2]
+    c = dot_product(OP,OC);
+    s = fabs(cross_product(OP,OC));
+    double inv_err1 = s * inv_R_EPS_COCIRC;
+    double inv_err2_sq = (R2-c) * inv_R_2EPS_COCIRC;
+    ve_list[i].cocircular_range = pow2(inv_err1) > inv_err2_sq ? 
+                                                     1.0/inv_err1 : 
+                                                     sqrt(1.0/inv_err2_sq);
+    ve_list[i+1].cocircular_range = ve_list[i].cocircular_range;
+  }
+}
+
+}
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/vicinity.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/vicinity.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/SISCone/vicinity.h	(revision 5)
@@ -0,0 +1,156 @@
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: vicinity.h                                                          //
+// Description: header file for particle vicinity (Cvicinity class)          //
+// This file is part of the SISCone project.                                 //
+// For more details, see http://projects.hepforge.org/siscone                //
+//                                                                           //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
+//                                                                           //
+// This program is free software; you can redistribute it and/or modify      //
+// it under the terms of the GNU General Public License as published by      //
+// the Free Software Foundation; either version 2 of the License, or         //
+// (at your option) any later version.                                       //
+//                                                                           //
+// This program is distributed in the hope that it will be useful,           //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
+// GNU General Public License for more details.                              //
+//                                                                           //
+// You should have received a copy of the GNU General Public License         //
+// along with this program; if not, write to the Free Software               //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+//                                                                           //
+// $Revision:: 859                                                          $//
+// $Date:: 2012-11-28 02:49:23 +0100 (Wed, 28 Nov 2012)                     $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __VICINITY_H__
+#define __VICINITY_H__
+
+#include <vector>
+#include <list>
+#include "momentum.h"
+#include "defines.h"
+#include "quadtree.h"
+
+namespace siscone{
+
+  
+
+/**
+ * \class Cvicinity_inclusion
+ * \brief a class to keep track of inclusion status in cone and in cocircular region
+ *        while using minimal resources
+ */
+class Cvicinity_inclusion {
+public:
+  /// default ctor
+  Cvicinity_inclusion() : cone(false), cocirc(false) {}
+
+  bool cone;    ///< flag for particle inclusion in the cone
+  bool cocirc;  ///< flag for particle inclusion in the border
+};
+
+
+/**
+ * \class Cvicinity_elm
+ * \brief element in the vicinity of a parent.
+ *
+ * class used to manage one points in the vicinity 
+ * of a parent point.
+ */
+class Cvicinity_elm{
+ public:
+  /// pointer to the second borderline particle
+  Cmomentum *v;
+
+  /// variable to tell if the particle is inside or outside the cone 
+  Cvicinity_inclusion *is_inside;   
+
+  // centre variables
+  double eta;              ///< eta coordinate of the center
+  double phi;              ///< phi coordinate of the center
+  double angle;            ///< angle with parent
+  bool side;               ///< true if angle on the positive side, false otherwise
+  double cocircular_range; ///< amount by which the angle can be varied while
+                           ///< maintaining this point within co-circularity margin
+
+  /// list of elements co-circular with this one
+  /// NB: empty list uses less mem than vector
+  std::list<Cvicinity_elm * > cocircular;                                          
+};
+
+/// ordering pointers to Cvicinity_elm
+bool ve_less(Cvicinity_elm *ve1, Cvicinity_elm *ve2);
+
+
+/**
+ * \class Cvicinity
+ * \brief list of element in the vicinity of a parent.
+ *
+ * class used to manage the points which are in the vicinity 
+ * of a parent point.
+ */
+class Cvicinity{
+ public:
+  /// default constructor
+  Cvicinity();
+
+  /// constructor with initialisation (see set_particle_list)
+  Cvicinity(std::vector<Cmomentum> &_particle_list);
+
+  /// default destructor
+  ~Cvicinity();
+
+  /**
+   * set the particle_list
+   * \param _particle_list   list of particles (type Cmomentum)
+   */ 
+  void set_particle_list(std::vector<Cmomentum> &_particle_list);
+
+  /**
+   * build the vicinity list from the list of points.
+   * \param _parent    reference particle
+   * \param _VR        vicinity radius
+   */
+  void build(Cmomentum *_parent, double _VR);
+
+  // cone kinematical information
+  Cmomentum *parent;         ///< parent vector
+  double VR;                 ///< radius of the vicinity
+  double VR2;                ///< squared radius of the vicinity
+  double R;                  ///< normal radius
+  double R2;                 ///< squared normal radius
+  double inv_R_EPS_COCIRC;   ///< R / EPSILON_COCIRCULAR
+  double inv_R_2EPS_COCIRC;  ///< R / (2*EPSILON_COCIRCULAR)
+
+  // particle list information
+  int n_part;                                 ///< number of particles
+  std::vector<Cmomentum> plist;               ///< the list of particles
+  std::vector<Cvicinity_inclusion> pincluded; ///< the inclusion state of particles
+  Cvicinity_elm *ve_list;                     ///< list of vicinity elements built from particle list (size=2*n)
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+  Cquadtree *quadtree;                        ///< quadtree used for final stability tests
+#endif
+
+  // vicinity information
+  std::vector<Cvicinity_elm*> vicinity;       ///< list of points in parent's vicinity
+  unsigned int vicinity_size;                 ///< number of elements in vicinity
+
+ protected:
+  /**
+   * append a particle to the 'vicinity' list after
+   * having tested it and computed the angular-ordering quantities
+   * \param v   vector to test
+   */
+  void append_to_vicinity(Cmomentum *v);
+
+  // internal variables
+  double pcx;    ///< parent centre (eta)
+  double pcy;    ///< parent centre (phi)
+};
+
+}
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/TrackJet/TrackJetPlugin.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/TrackJet/TrackJetPlugin.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/TrackJet/TrackJetPlugin.cc	(revision 5)
@@ -0,0 +1,209 @@
+//STARTHEADER
+// $Id: TrackJetPlugin.cc 859 2012-11-28 01:49:23Z pavel $
+//
+// Copyright (c) 2007-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet. It contains code that has been
+// obtained from the Rivet project by Leif Lonnblad, Andy Buckley and
+// Jon Butterworth. See http://www.hepforge.org/downloads/rivet.
+// Rivet is free software released under the terms of the GNU Public
+// License(v2).
+// Changes from the original file are listed below.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+// History of changes from the original TrackJet.cc file in Rivet <=1.1.2
+// 
+// 2011-01-28  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * Replaced the use of sort by stable_sort (see BUGS in the top
+//          FastJet dir)
+// 
+// 
+// 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * Aligned the var names with the previous conventions
+// 
+//        * Put the plugin in the fastjet::trackjet namespace
+// 
+// 
+// 2009-01-06  Gregory Soyez  <soyez@fastjet.fr>
+// 
+//        * Adapted the original code in a FastJet plugin class. 
+// 
+//        * Allowed for arbitrary recombination schemes (one for the
+//          recomstruction of the 'jet' --- i.e. summing the particles
+//          into a jet --- and one for the accumulation of particles in
+//          a 'track' --- i.e. the dynamics of the clustering)
+
+
+// fastjet stuff
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/TrackJetPlugin.hh"
+
+// other stuff
+#include <list>
+#include <memory>
+#include <cmath>
+#include <vector>
+#include <sstream>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+using namespace std;
+
+//------------------------------------------------------------------
+// helper class to sort the particles in pt
+//------------------------------------------------------------------
+class TrackJetParticlePtr{
+public:
+  TrackJetParticlePtr(int i_index, double i_perp2)
+    :  index(i_index), perp2(i_perp2){}
+
+  int index;
+  double perp2;
+
+  bool operator <(const TrackJetParticlePtr &other) const { 
+    return perp2>other.perp2;
+  }
+};
+
+//------------------------------------------------------------------
+// implementation of the TrackJet plugin
+//------------------------------------------------------------------
+
+bool TrackJetPlugin::_first_time = true;
+
+string TrackJetPlugin::description () const {
+  ostringstream desc;
+  desc << "TrackJet algorithm with R = " << R();
+  return desc.str();
+}
+
+void TrackJetPlugin::run_clustering(ClusterSequence & clust_seq) const {
+  // print a banner if we run this for the first time
+  _print_banner(clust_seq.fastjet_banner_stream());
+
+  // we first need to sort the particles in pt
+  vector<TrackJetParticlePtr> particle_list;
+
+  const vector<PseudoJet> & jets = clust_seq.jets();  
+  int index=0;
+  for (vector<PseudoJet>::const_iterator mom_it = jets.begin(); mom_it != jets.end(); mom_it++){
+    particle_list.push_back(TrackJetParticlePtr(index, mom_it->perp2()));
+    index++;
+  }
+
+  // sort the particles into decreasing pt
+  stable_sort(particle_list.begin(), particle_list.end());
+
+
+  // if we're using a recombination scheme different from the E scheme,
+  // we first need to update the particles' energy so that they
+  // are massless (and rapidity = pseudorapidity)
+  vector<PseudoJet> tuned_particles = clust_seq.jets();
+  vector<PseudoJet> tuned_tracks = clust_seq.jets();
+  for (vector<PseudoJet>::iterator pit = tuned_particles.begin();
+       pit != tuned_particles.end(); pit++)
+    _jet_recombiner.preprocess(*pit);
+  for (vector<PseudoJet>::iterator pit = tuned_tracks.begin();
+       pit != tuned_tracks.end(); pit++)
+    _track_recombiner.preprocess(*pit);
+
+
+  // we'll just need the particle indices for what follows
+  list<int> sorted_pt_index;
+  for (vector<TrackJetParticlePtr>::iterator mom_it = particle_list.begin();
+       mom_it != particle_list.end(); mom_it++)
+    sorted_pt_index.push_back(mom_it->index);
+  
+  // now start building the jets
+  while (sorted_pt_index.size()){
+    // note that here 'track' refers to the direction we're using to test if a particle belongs to the jet
+    // 'jet' refers to the momentum of the jet
+    // the difference between the two is in the recombination scheme used to compute the sum of 4-vectors
+    int current_jet_index = sorted_pt_index.front();
+    PseudoJet current_jet   = tuned_particles[current_jet_index];
+    PseudoJet current_track = tuned_tracks[current_jet_index];
+
+    // remove the first particle from the available ones    
+    list<int>::iterator index_it = sorted_pt_index.begin();
+    sorted_pt_index.erase(index_it);
+
+    // start browsing the remaining ones
+    index_it = sorted_pt_index.begin();
+    while (index_it != sorted_pt_index.end()){
+      const PseudoJet & current_particle = tuned_particles[*index_it];
+      const PseudoJet & current_particle_track = tuned_tracks[*index_it];
+
+      // check if the particle is within a distance R of the jet
+      double distance2 = current_track.plain_distance(current_particle_track);
+      if (distance2 <= _radius2){
+	// add the particle to the jet
+	PseudoJet new_track;
+	PseudoJet new_jet;
+	_jet_recombiner.recombine(current_jet, current_particle, new_jet);
+	_track_recombiner.recombine(current_track, current_particle_track, new_track);
+
+	int new_jet_index;
+	clust_seq.plugin_record_ij_recombination(current_jet_index, *index_it, distance2, new_jet, new_jet_index);
+
+	current_jet = new_jet;
+	current_track = new_track;
+	current_jet_index = new_jet_index;
+
+	// particle has been clustered so remove it from the list
+	sorted_pt_index.erase(index_it);
+
+	// and don't forget to start again from the beginning
+	//  as the jet axis may have changed
+	index_it = sorted_pt_index.begin();
+      } else {
+	index_it++;
+      }
+    }
+
+    // now we have a final jet, so cluster it with the beam
+    clust_seq.plugin_record_iB_recombination(current_jet_index, _radius2);
+  }
+    
+}
+
+// print a banner for reference to the 3rd-party code
+void TrackJetPlugin::_print_banner(ostream *ostr) const{
+  if (! _first_time) return;
+  _first_time=false;
+
+  // make sure the user has not set the banner stream to NULL
+  if (!ostr) return;  
+
+  (*ostr) << "#-------------------------------------------------------------------------" << endl;
+  (*ostr) << "# You are running the TrackJet plugin for FastJet. It is based on         " << endl;
+  (*ostr) << "# the implementation by Andy Buckley and Manuel Bahr that is to be        " << endl;
+  (*ostr) << "# found in Rivet 1.1.2. See http://www.hepforge.org/downloads/rivet.      " << endl;
+  (*ostr) << "#-------------------------------------------------------------------------" << endl;
+
+  // make sure we really have the output done.
+  ostr->flush();
+}
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/TrackJet/fastjet/TrackJetPlugin.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/TrackJet/fastjet/TrackJetPlugin.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/plugins/TrackJet/fastjet/TrackJetPlugin.hh	(revision 5)
@@ -0,0 +1,97 @@
+//STARTHEADER
+// $Id: TrackJetPlugin.hh 2758 2011-11-24 08:31:58Z soyez $
+//
+// Copyright (c) 2007-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __TRACKJETPLUGIN_HH__
+#define __TRACKJETPLUGIN_HH__
+
+#include "fastjet/JetDefinition.hh"
+
+// questionable whether this should be in fastjet namespace or not...
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+// another forward declaration to reduce includes
+class PseudoJet;
+
+//----------------------------------------------------------------------
+
+/// @ingroup plugins
+/// \class TrackJetPlugin
+/// Implementation of the TrackJet algorithm (plugin for fastjet v2.4 upwards)
+//
+class TrackJetPlugin : public JetDefinition::Plugin {
+public:
+  /// Main constructor for the TrackJet Plugin class.  
+  ///
+  /// The argument is an initialised list of jet algorithms
+  /// \param _radius  the distance at which point a particle is no longer
+  ///                 recombied into the jet
+  /// \param jet_recombination_scheme  the recombination scheme used to 
+  ///                                  sum the 4-vecors inside the jet
+  /// \param track_recombination_scheme  the recombination scheme used to 
+  ///                                    sum the 4-vecors when accumulating
+  ///                                    track into a the jet
+  /// Both recombiners are defaulted to pt_scheme recomb as for the Rivet
+  /// implementation.
+  TrackJetPlugin (double radius, 
+		  RecombinationScheme jet_recombination_scheme=pt_scheme, 
+		  RecombinationScheme track_recombination_scheme=pt_scheme){
+    _radius  = radius;
+    _radius2 = radius*radius;
+    _jet_recombiner = JetDefinition::DefaultRecombiner(jet_recombination_scheme);
+    _track_recombiner = JetDefinition::DefaultRecombiner(track_recombination_scheme);
+  }
+
+  /// copy constructor
+  TrackJetPlugin (const TrackJetPlugin & plugin) {
+    *this = plugin;
+  }
+
+  // the things that are required by base class
+  virtual std::string description () const;
+  virtual void run_clustering(ClusterSequence &) const;
+
+  /// the plugin mechanism's standard way of accessing the jet radius
+  /// here we return the R of the last alg in the list
+  virtual double R() const {return _radius;}
+
+private:
+  double _radius, _radius2;
+
+  JetDefinition::DefaultRecombiner _jet_recombiner;
+  JetDefinition::DefaultRecombiner _track_recombiner;
+
+  static bool _first_time;
+
+  /// print a banner for reference to the 3rd-party code
+  void _print_banner(std::ostream *ostr) const;
+};
+
+FASTJET_END_NAMESPACE        // defined in fastjet/internal/base.hh
+
+#endif // __TRACKJETPLUGIN_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/BackgroundEstimatorBase.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/BackgroundEstimatorBase.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/BackgroundEstimatorBase.cc	(revision 5)
@@ -0,0 +1,141 @@
+//STARTHEADER
+// $Id: BackgroundEstimatorBase.cc 999 2013-03-04 11:48:06Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#include "fastjet/tools/BackgroundEstimatorBase.hh"
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+LimitedWarning BackgroundEstimatorBase::_warnings_empty_area;
+
+//----------------------------------------------------------------------
+// given a quantity in a vector (e.g. pt_over_area) and knowledge
+// about the number of empty jets, calculate the median and
+// stand_dev_if_gaussian (roughly from the 16th percentile)
+//
+// If do_fj2_calculation is set to true then this performs FastJet
+// 2.X estimation of the standard deviation, which has a spurious
+// offset in the limit of a small number of jets.
+void BackgroundEstimatorBase::_median_and_stddev(const vector<double> & quantity_vector, 
+                                                 double n_empty_jets, 
+                                                 double & median, 
+                                                 double & stand_dev_if_gaussian,
+                                                 bool do_fj2_calculation) const {
+
+  // this check is redundant (the code below behaves sensibly even
+  // with a zero size), but serves as a reminder of what happens if
+  // the quantity vector is zero-sized
+  if (quantity_vector.size() == 0) {
+    median = 0;
+    stand_dev_if_gaussian = 0;
+    return;
+  }
+
+  vector<double> sorted_quantity_vector = quantity_vector;
+  sort(sorted_quantity_vector.begin(), sorted_quantity_vector.end());
+
+  // empty area can sometimes be negative; with small ranges this can
+  // become pathological, so warn the user
+  int n_jets_used = sorted_quantity_vector.size();
+  if (n_empty_jets < -n_jets_used/4.0)
+    _warnings_empty_area.warn("BackgroundEstimatorBase::_median_and_stddev(...): the estimated empty area is suspiciously large and negative and may lead to an over-estimation of rho. This may be due to (i) a rare statistical fluctuation or (ii) too small a range used to estimate the background properties.");
+
+  // now get the median & error, accounting for empty jets;
+  // define the fractions of distribution at median, median-1sigma
+  double posn[2] = {0.5, (1.0-0.6827)/2.0};
+  double res[2];
+  for (int i = 0; i < 2; i++) {
+    res[i] = _percentile(sorted_quantity_vector, posn[i], n_empty_jets, 
+                         do_fj2_calculation);
+  }
+  
+  median = res[0];
+  stand_dev_if_gaussian = res[0] - res[1];
+}
+
+
+//----------------------------------------------------------------------
+// computes a percentile of a given _sorted_ vector of quantities
+//  - sorted_quantities        the (sorted) vector contains the data sample
+//  - percentile               the percentile (defined between 0 and 1) to compute
+//  - nempty                   an additional number of 0's
+//                             (considered at the beginning of 
+//                             the quantity vector)
+//  - do_fj2_calculation       carry out the calculation as it
+//                             was done in fj2 (suffers from "edge effects")
+double BackgroundEstimatorBase::_percentile(const vector<double> & sorted_quantities, 
+                                            const double percentile, 
+                                            const double nempty,
+                                            const bool do_fj2_calculation
+                                            ) const {
+  assert(percentile >= 0.0 && percentile <= 1.0);
+
+  int quantities_size = sorted_quantities.size();
+  if (quantities_size == 0) return 0;
+
+  double total_njets = quantities_size + nempty;
+  double percentile_pos;
+  if (do_fj2_calculation) {
+    percentile_pos = (total_njets-1)*percentile - nempty;
+  } else {
+    percentile_pos = (total_njets)*percentile - nempty - 0.5;
+  }
+
+  double result;
+  if (percentile_pos >= 0 && quantities_size > 1) {
+    int int_percentile_pos = int(percentile_pos);
+
+    // avoid potential overflow issues
+    if (int_percentile_pos+1 > quantities_size-1){
+      int_percentile_pos = quantities_size-2;
+      percentile_pos = quantities_size-1;
+    }
+
+    result =
+      sorted_quantities[int_percentile_pos] * (int_percentile_pos+1-percentile_pos)
+      + sorted_quantities[int_percentile_pos+1] * (percentile_pos - int_percentile_pos);
+    
+
+  } else if (percentile_pos > -0.5 && quantities_size >= 1 
+             && !do_fj2_calculation) {
+    // in the LHS of this "bin", just keep a constant value (we could have
+    // interpolated to zero, but this might misbehave in cases where all jets
+    // are active, because it would go to zero too fast)
+    result = sorted_quantities[0];
+  } else {
+    result = 0.0;
+  }
+  return result;
+
+
+}
+
+
+FASTJET_END_NAMESPACE        // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/BackgroundEstimatorBase.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/BackgroundEstimatorBase.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/BackgroundEstimatorBase.hh	(revision 5)
@@ -0,0 +1,215 @@
+#ifndef __FASTJET_BACKGROUND_ESTIMATOR_BASE_HH__
+#define __FASTJET_BACKGROUND_ESTIMATOR_BASE_HH__
+
+//STARTHEADER
+// $Id: BackgroundEstimatorBase.hh 2689 2011-11-14 14:51:06Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include <fastjet/ClusterSequenceAreaBase.hh>
+#include <fastjet/FunctionOfPseudoJet.hh>
+#include <fastjet/Selector.hh>
+#include <fastjet/Error.hh>
+#include <iostream>
+
+FASTJET_BEGIN_NAMESPACE     // defined in fastjet/internal/base.hh
+
+
+/// @ingroup tools_background
+/// \class BackgroundEstimatorBase
+///
+/// Abstract base class that provides the basic interface for classes
+/// that estimate levels of background radiation in hadrion and
+/// heavy-ion collider events.
+///
+///
+class BackgroundEstimatorBase {
+public:
+  /// @name  constructors and destructors
+  //\{
+  //----------------------------------------------------------------
+  BackgroundEstimatorBase() : _rescaling_class(0) {}
+  //\}
+
+  /// a default virtual destructor that does nothing
+  virtual ~BackgroundEstimatorBase() {}
+
+
+  /// @name setting a new event
+  //\{
+  //----------------------------------------------------------------
+
+  /// tell the background estimator that it has a new event, composed
+  /// of the specified particles.
+  virtual void set_particles(const std::vector<PseudoJet> & particles) = 0;
+
+  //\}
+
+  /// @name  retrieving fundamental information
+  //\{
+  //----------------------------------------------------------------
+
+  /// get rho, the background density per unit area
+  virtual double rho() const = 0;
+
+  /// get sigma, the background fluctuations per unit area; must be
+  /// multipled by sqrt(area) to get fluctuations for a region of a
+  /// given area.
+  virtual double sigma() const { 
+    throw Error("sigma() not supported for this Background Estimator");
+  }
+
+  /// get rho, the background density per unit area, locally at the
+  /// position of a given jet. Note that this is not const, because a
+  /// user may then wish to query other aspects of the background that
+  /// could depend on the position of the jet last used for a rho(jet)
+  /// determination.
+  virtual double rho(const PseudoJet & jet) = 0;
+
+  /// get sigma, the background fluctuations per unit area, locally at
+  /// the position of a given jet. As for rho(jet), it is non-const.
+  virtual double sigma(const PseudoJet & /*jet*/) { 
+    throw Error("sigma(jet) not supported for this Background Estimator");
+  }
+
+  /// returns true if this background estimator has support for
+  /// determination of sigma
+  virtual bool has_sigma() {return false;}
+  //\}
+  
+
+  /// @name configuring the behaviour
+  //\{
+  //----------------------------------------------------------------
+
+  /// Set a pointer to a class that calculates the rescaling factor as
+  /// a function of the jet (position). Note that the rescaling factor
+  /// is used both in the determination of the "global" rho (the pt/A
+  /// of each jet is divided by this factor) and when asking for a
+  /// local rho (the result is multiplied by this factor).
+  ///
+  /// The BackgroundRescalingYPolynomial class can be used to get a
+  /// rescaling that depends just on rapidity.
+  virtual void set_rescaling_class(const FunctionOfPseudoJet<double> * rescaling_class_in) { _rescaling_class = rescaling_class_in; }
+
+  /// return the pointer to the jet density class
+  const FunctionOfPseudoJet<double> *  rescaling_class() const{
+    return _rescaling_class;
+  }
+
+  //\}
+
+  /// @name description
+  //\{
+  //----------------------------------------------------------------
+
+  /// returns a textual description of the background estimator
+  virtual std::string description() const = 0;
+
+  //\}
+
+protected:
+  /// @name helpers for derived classes
+  ///
+  /// Note that these helpers are related to median-based estimation
+  /// of the background, so there is no guarantee that they will
+  /// remain in this base class in the long term
+  //\{
+  //----------------------------------------------------------------
+
+  /// given a quantity in a vector (e.g. pt_over_area) and knowledge
+  /// about the number of empty jets, calculate the median and
+  /// stand_dev_if_gaussian (roughly from the 16th percentile)
+  ///
+  /// If do_fj2_calculation is set to true then this performs FastJet
+  /// 2.X estimation of the standard deviation, which has a spurious
+  /// offset in the limit of a small number of jets.
+  void _median_and_stddev(const std::vector<double> & quantity_vector, 
+                          double n_empty_jets, 
+                          double & median, 
+                          double & stand_dev_if_gaussian,
+                          bool do_fj2_calculation = false
+                          ) const;
+
+  /// computes a percentile of a given _sorted_ vector
+  ///  \param sorted_quantity_vector   the vector contains the data sample
+  ///  \param percentile               the percentile (defined between 0 and 1) to compute
+  ///  \param nempty                   an additional number of 0's
+  ///                                  (considered at the beginning of 
+  ///                                  the quantity vector)
+  ///  \param do_fj2_calculation       carry out the calculation as it
+  ///                                  was done in fj2 (suffers from "edge effects")
+  double _percentile(const std::vector<double> & sorted_quantity_vector, 
+                     const double percentile, 
+                     const double nempty=0.0,
+                     const bool do_fj2_calculation = false) const;
+
+  //\}
+
+  const FunctionOfPseudoJet<double> * _rescaling_class;
+  static LimitedWarning _warnings_empty_area;
+};
+
+
+
+//----------------------------------------------------------------------
+/// @ingroup tools_background
+/// A background rescaling that is a simple polynomial in y
+class BackgroundRescalingYPolynomial : public FunctionOfPseudoJet<double> {
+public:
+  /// construct a background rescaling polynomial of the form
+  /// a0 + a1*y + a2*y^2 + a3*y^3 + a4*y^4
+  ///
+  /// The following values give a reasonable reproduction of the
+  /// Pythia8 tune 4C background shape for pp collisions at
+  /// sqrt(s)=7TeV:
+  ///
+  /// - a0 =  1.157
+  /// - a1 =  0
+  /// - a2 = -0.0266
+  /// - a3 =  0
+  /// - a4 =  0.000048
+  ///
+  BackgroundRescalingYPolynomial(double a0=1, 
+                                 double a1=0, 
+                                 double a2=0, 
+                                 double a3=0, 
+                                 double a4=0) : _a0(a0), _a1(a1), _a2(a2), _a3(a3), _a4(a4) {}
+
+  /// return the rescaling factor associated with this jet
+  virtual double result(const PseudoJet & jet) const;
+private:
+  double _a0, _a1, _a2, _a3, _a4;
+};
+
+
+
+
+
+FASTJET_END_NAMESPACE
+
+#endif  // __BACKGROUND_ESTIMATOR_BASE_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Boost.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Boost.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Boost.hh	(revision 5)
@@ -0,0 +1,86 @@
+//STARTHEADER
+// $Id: Boost.hh 2689 2011-11-14 14:51:06Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_TOOL_BOOST_HH__
+#define __FASTJET_TOOL_BOOST_HH__
+
+#include <fastjet/PseudoJet.hh>
+#include <fastjet/FunctionOfPseudoJet.hh>
+#include <fastjet/PseudoJetStructureBase.hh>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+/// @ingroup tools_generic
+/// \class Boost
+/// Class to boost a PseudoJet
+///
+/// This is a FunctionOfPseudoJet with return type PseudoJet. Its
+/// action if to boost the PseudoJet by a boost vector passed to its
+/// constructor
+class Boost : public FunctionOfPseudoJet<PseudoJet>{
+public:
+  /// default ctor
+  Boost(const PseudoJet & jet_rest) : _jet_rest(jet_rest){}
+
+  /// the action of the function: boost the PseudoJet by a boost
+  /// vector _jet_rest
+  PseudoJet result(const PseudoJet & original) const{
+    PseudoJet res = original;
+    return res.boost(_jet_rest);
+  }
+
+protected:
+  PseudoJet _jet_rest;  ///< the boost vector
+};
+
+/// @ingroup tools_generic
+/// \class Unboost
+/// Class to un-boost a PseudoJet
+///
+/// This is a FunctionOfPseudoJet with return type PseudoJet. Its
+/// action if to un-boost the PseudoJet back in the restframe of the
+/// PseudoJet passed to its constructor
+class Unboost : public FunctionOfPseudoJet<PseudoJet>{
+public:
+  /// default ctor
+  Unboost(const PseudoJet & jet_rest) : _jet_rest(jet_rest){}
+
+  /// the action of the function: boost the PseudoJet to the rest
+  /// frame of _jet_rest
+  PseudoJet result(const PseudoJet & original) const{
+    PseudoJet res = original;
+    return res.unboost(_jet_rest);
+  }
+
+protected:
+  PseudoJet _jet_rest;  ///< the boost vector
+};
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
+
+#endif // __FASTJET_TRANSFORMER_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/CASubJetTagger.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/CASubJetTagger.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/CASubJetTagger.cc	(revision 5)
@@ -0,0 +1,173 @@
+//STARTHEADER
+// $Id: CASubJetTagger.cc 999 2013-03-04 11:48:06Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include <fastjet/tools/CASubJetTagger.hh>
+#include <fastjet/ClusterSequence.hh>
+
+#include <algorithm>
+#include <cmath>
+#include <sstream>
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE
+
+
+LimitedWarning CASubJetTagger::_non_ca_warnings;
+
+// the tagger's description
+//----------------------------------------------------------------------
+string CASubJetTagger::description() const{
+  ostringstream oss;
+  oss << "CASubJetTagger with z_threshold=" << _z_threshold ;
+  if (_absolute_z_cut) oss << " (defined wrt original jet)";
+  oss << " and scale choice ";
+  switch (_scale_choice) {
+  case kt2_distance:         oss << "kt2_distance";         break;
+  case jade_distance:        oss << "jade_distance";        break;
+  case jade2_distance:       oss << "jade2_distance";       break;
+  case plain_distance:       oss << "plain_distance";       break;
+  case mass_drop_distance:   oss << "mass_drop_distance";   break;
+  case dot_product_distance: oss << "dot_product_distance"; break;
+  default:
+    throw Error("unrecognized scale choice");
+  }
+
+  return oss.str();
+}
+
+// run the tagger on the given cs/jet
+// returns the tagged PseudoJet if successful, 0 otherwise
+//----------------------------------------------------------------------
+PseudoJet CASubJetTagger::result(const PseudoJet & jet) const{
+  // make sure that the jet results from a Cambridge/Aachen clustering
+  if (jet.validated_cs()->jet_def().jet_algorithm() != cambridge_algorithm)
+    _non_ca_warnings.warn("CASubJetTagger should only be applied on jets from a Cambridge/Aachen clustering; use it with other algorithms at your own risk");
+
+  // recurse in the jet to find the max distance
+  JetAux aux;
+  aux.jet          = PseudoJet();
+  aux.aux_distance = -numeric_limits<double>::max();
+  aux.delta_r      = 0.0;
+  aux.z            = 1.0;
+  _recurse_through_jet(jet, aux, jet); // last arg remains original jet
+
+  // create the result and its associated structure
+  PseudoJet result_local = aux.jet;
+
+  // the tagger is considered to have failed if aux has never been set
+  // (in which case it will not have parents).
+  if (result_local == PseudoJet()) return result_local;
+
+  // otherwise sort out the structure
+  CASubJetTaggerStructure * s = new CASubJetTaggerStructure(result_local);
+//  s->_original_jet = jet;
+  s->_scale_choice = _scale_choice;
+  s->_distance     = aux.aux_distance;
+  s->_absolute_z   = _absolute_z_cut;
+  s->_z            = aux.z;
+
+  result_local.set_structure_shared_ptr(SharedPtr<PseudoJetStructureBase>(s));
+
+  return result_local;
+}
+
+
+///----------------------------------------------------------------------
+/// work through the jet, establishing a distance at each branching
+inline void CASubJetTagger::_recurse_through_jet(const PseudoJet & jet, JetAux &aux, const PseudoJet & original_jet) const {
+
+  PseudoJet parent1, parent2;
+  if (! jet.has_parents(parent1, parent2)) return;
+
+  /// make sure the objects are not _too_ close together
+  if (parent1.squared_distance(parent2) < _dr2_min) return;
+
+  // distance
+  double dist=0.0;
+  switch (_scale_choice) {
+  case kt2_distance:
+    // a standard (LI) kt distance
+    dist = parent1.kt_distance(parent2);
+    break;
+  case jade_distance:
+    // something a bit like a mass: pti ptj Delta R_ij^2
+    dist = parent1.perp()*parent2.perp()*parent1.squared_distance(parent2);
+    break;
+  case jade2_distance:
+    // something a bit like a mass*deltaR^2: pti ptj Delta R_ij^4
+    dist = parent1.perp()*parent2.perp()*pow(parent1.squared_distance(parent2),2);
+    break;
+  case plain_distance:
+    // Delta R_ij^2
+    dist = parent1.squared_distance(parent2);
+    break;
+  case mass_drop_distance:
+    // Delta R_ij^2
+    dist = jet.m() - std::max(parent1.m(),parent2.m());
+    break;
+  case dot_product_distance:
+    // parent1 . parent2 
+    // ( = jet.m2() - parent1.m2() - parent2.m() in a 
+    // 4-vector recombination scheme) 
+    dist = dot_product(parent1, parent2);
+    break;
+  default:
+    throw Error("unrecognized scale choice");
+  }
+
+  // check the z cut
+  bool zcut1 = true;
+  bool zcut2 = true;
+  double z2 = 0.0;
+
+  // not very efficient -- sort out later
+  if (parent1.perp2() < parent2.perp2()) std::swap(parent1,parent2);
+
+  if (_absolute_z_cut) {
+    z2    = parent2.perp() / original_jet.perp();
+    zcut1 = parent1.perp() / original_jet.perp() >= _z_threshold;
+  } else {
+    z2    = parent2.perp()/(parent1.perp()+parent2.perp());
+  }
+  zcut2 = z2 >= _z_threshold;
+
+  if (zcut1 && zcut2){
+    if (dist > aux.aux_distance){
+      aux.jet          = jet;
+      aux.aux_distance = dist;
+      aux.delta_r      = sqrt(parent1.squared_distance(parent2));
+      aux.z            = z2; // the softest
+    }
+  }    
+
+  if (zcut1) _recurse_through_jet(parent1, aux, original_jet);
+  if (zcut2) _recurse_through_jet(parent2, aux, original_jet);
+}
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/CASubJetTagger.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/CASubJetTagger.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/CASubJetTagger.hh	(revision 5)
@@ -0,0 +1,224 @@
+//STARTHEADER
+// $Id: CASubJetTagger.hh 2616 2011-09-30 18:03:40Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __CASUBJET_TAGGER_HH__
+#define __CASUBJET_TAGGER_HH__
+
+#include <fastjet/PseudoJet.hh>
+#include <fastjet/WrappedStructure.hh>
+#include <fastjet/tools/Transformer.hh>
+#include "fastjet/LimitedWarning.hh"
+
+FASTJET_BEGIN_NAMESPACE
+
+class CASubJetTagger;
+class CASubJetTaggerStructure;
+
+//----------------------------------------------------------------------
+/// @ingroup tools_taggers
+/// \class CASubJetTagger
+/// clean (almost parameter-free) tagger searching for the element in
+/// the clustering history that maximises a chosen distance
+///
+/// class to help us get a clean (almost parameter-free) handle on
+/// substructure inside a C/A jet. It follows the logic described in
+/// arXiv:0906.0728 (and is inspired by the original Cambridge
+/// algorithm paper in its use of separate angular and dimensionful
+/// distances), but provides some extra flexibility.
+///
+/// It searches for all splittings that pass a symmetry cut (zcut) and
+/// then selects the one with the largest auxiliary scale choice
+/// (e.g. jade distance of the splitting, kt distance of the
+/// splitting, etc.)
+///
+/// By default, the zcut is calculated from the fraction of the child
+/// pt carried by the parent jet. If one calls set_absolute_z_cut the
+/// fraction of transverse momentum will be computed wrt the original
+/// jet.
+///
+/// original code copyright (C) 2009 by Gavin Salam, released under
+/// the GPL.
+///
+/// \section desc Options
+/// 
+///  - the distance choice: options are
+///        kt2_distance        : usual min(kti^2,ktj^2)DeltaR_{ij}^2
+///        jade_distance       : kti . ktj DeltaR_{ij}^2 (LI version of jade)
+///        jade2_distance      : kti . ktj DeltaR_{ij}^4 (LI version of jade * DR^2)
+///        plain_distance      :           DeltaR_{ij}^2
+///        mass_drop_distance  : m_jet - max(m_parent1,m_parent2)
+///        dot_product_distance: parent1.parent2
+///    (kt2_distance by default)
+///
+///  - the z cut (0 by default)
+///
+///  - by calling set_absolute_z_cut(), one can ask that the pt
+///    fraction if calculated wrt the original jet
+///
+///  - by calling set_dr_min(drmin), one can ask that only the
+///    recombinations where the 2 objects are (geometrically) distant
+///    by at least drmin are kept in the maximisation.
+///
+/// \section input Input conditions
+/// 
+///  - the jet must have been obtained from a Cambridge/Aachen cluster
+///    sequence
+///
+/// \section output Output/structure
+/// 
+///  - the element of the cluster sequence maximising the requested
+///    distance (and satisfying the zcut) is returned.
+///
+///  - if the original jet has no parents, it will be returned
+///
+///  - the value of the "z" and distance corresponding to that history
+///    element are stored and accessible through
+///      result.structure_of<CASubJetTagger>().z();
+///      result.structure_of<CASubJetTagger>().distance();
+///
+class CASubJetTagger : public Transformer {
+public:
+
+  /// the available choices of auxiliary scale with respect to which
+  /// to order the splittings
+  enum ScaleChoice {
+    kt2_distance,        //< usual min(kti^2,ktj^2)DeltaR_{ij}^2
+    jade_distance,       //< kti . ktj DeltaR_{ij}^2 (LI version of jade)
+    jade2_distance,      //< kti . ktj DeltaR_{ij}^4 (LI version of jade * DR^2)
+    plain_distance,      //<           DeltaR_{ij}^2
+    mass_drop_distance,  //<    m_jet - max(m_parent1,m_parent2)
+    dot_product_distance //<  parent1.parent2
+  };
+
+  /// just constructs
+  CASubJetTagger(ScaleChoice scale_choice = jade_distance,
+                 double      z_threshold  = 0.1)
+    : _scale_choice(scale_choice), _z_threshold(z_threshold),
+      _dr2_min(0.0), _absolute_z_cut(false){};
+
+  /// sets a minimum delta R below which spliting will be ignored
+  /// (only relevant if set prior to calling run())
+  void set_dr_min(double drmin) {_dr2_min = drmin*drmin;}
+
+  /// returns a textual description of the tagger
+  virtual std::string description() const;
+
+  /// If (abs_z_cut) is set to false (the default) then for a
+  /// splitting to be considered, each subjet must satisfy 
+  /// 
+  ///        p_{t,sub} > z_threshold * p_{t,parent}
+  ///
+  /// whereas if it is set to true, then each subject must satisfy
+  ///
+  ///        p_{t,sub} > z_threshold * p_{t,original-jet}
+  ///
+  /// where parent is the immediate parent of the splitting, and
+  /// original jet is the one supplied to the run() function.
+  ///
+  /// Only relevant is called prior to run().
+  void set_absolute_z_cut(bool abs_z_cut=true) {_absolute_z_cut = abs_z_cut;}
+  
+  /// runs the tagger on the given jet and
+  /// returns the tagged PseudoJet if successful, or a PseudoJet==0 otherwise
+  /// (standard access is through operator()).
+  virtual PseudoJet result(const PseudoJet & jet) const;
+
+  /// the type of Structure returned
+  typedef CASubJetTaggerStructure StructureType;
+
+protected:
+  /// class that contains the result internally
+  class JetAux {
+  public:
+    PseudoJet jet;          //< the subjet (immediate parent of splitting)
+    double    aux_distance; //< the auxiliary distance between its two subjets
+    double    delta_r;      //< the angular distance between its two subjets
+    double    z;            //< the transverse momentum fraction
+  };
+
+
+  void _recurse_through_jet(const PseudoJet & current_jet, 
+                            JetAux &aux_max,
+                            const PseudoJet & original_jet) const;
+
+  ScaleChoice _scale_choice;
+  double      _z_threshold;
+  double      _dr2_min;
+  bool        _absolute_z_cut;
+
+  static  LimitedWarning _non_ca_warnings;
+};
+
+
+//------------------------------------------------------------------------
+/// @ingroup tools_taggers
+/// the structure returned by a CASubJetTagger
+///
+/// Since this is directly an element of the ClusterSequence, we keep
+/// basically the original ClusterSequenceStructure (wrapped for
+/// memory-management reasons) and add information about the pt
+/// fraction and distance of the subjet structure
+class CASubJetTaggerStructure : public WrappedStructure{
+public:
+  /// default ctor
+  ///  \param result_jet   the jet for which we have to keep the
+  ///                      structure
+  CASubJetTaggerStructure(const PseudoJet & result_jet)
+    : WrappedStructure(result_jet.structure_shared_ptr()){}
+
+  /// returns the scale choice asked for the maximisation
+  CASubJetTagger::ScaleChoice scale_choice() const {return _scale_choice;}
+
+  /// returns the value of the distance measure (corresponding to
+  /// ScaleChoice) for this jet's splitting
+  double distance() const {return _distance;}
+
+  /// returns the pt fraction contained by the softer of the two component
+  /// pieces of this jet (normalised relative to this jet)
+  double z() const {return _z;}
+
+  /// returns the pt fraction contained by the softer of the two component
+  /// pieces of this jet (normalised relative to the original jet)
+  bool absolute_z() const {return _absolute_z;}
+
+//  /// returns the original jet (before tagging)
+//  const PseudoJet & original() const {return _original_jet;}
+
+protected:
+  CASubJetTagger::ScaleChoice _scale_choice; ///< the user scale choice 
+  double _distance;  ///< the maximal distance associated with the result
+  bool _absolute_z;  ///< whether z is computed wrt to the original jet or not
+  double _z;         ///< the transverse momentum fraction
+//  PseudoJet _original_jet;  ///< the original jet (before tagging)
+
+  friend class CASubJetTagger; ///< to allow setting the internal information
+};
+
+FASTJET_END_NAMESPACE
+
+#endif // __CASUBJET_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Filter.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Filter.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Filter.cc	(revision 5)
@@ -0,0 +1,412 @@
+//STARTHEADER
+// $Id: Filter.cc 999 2013-03-04 11:48:06Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/tools/Filter.hh"
+#include <fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh>
+#include <cassert>
+#include <algorithm>
+#include <sstream>
+#include <typeinfo>
+
+using namespace std;
+
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+// Filter class implementation
+//----------------------------------------------------------------------
+
+// class description
+string Filter::description() const {
+  ostringstream ostr;
+  ostr << "Filter with subjet_def = ";
+  if (_Rfiltfunc) {
+    ostr << "Cambridge/Aachen algorithm with dynamic Rfilt"
+         << " (recomb. scheme deduced from jet, or E-scheme if not unique)";
+  } else if (_Rfilt > 0) {
+    ostr << "Cambridge/Aachen algorithm with Rfilt = " 
+         << _Rfilt 
+         << " (recomb. scheme deduced from jet, or E-scheme if not unique)";
+  } else {
+    ostr << _subjet_def.description();
+  }
+  ostr<< ", selection " << _selector.description();
+  if (_subtractor) {
+    ostr << ", subtractor: " << _subtractor->description();
+  } else if (_rho != 0) {
+    ostr << ", subtracting with rho = " << _rho;
+  }
+  return ostr.str();
+}
+
+
+// core functions
+//----------------------------------------------------------------------
+
+// return a vector of subjets, which are the ones that would be kept
+// by the filtering
+PseudoJet Filter::result(const PseudoJet &jet) const {
+  // start by getting the list of subjets (including a list of sanity
+  // checks)
+  // NB: subjets is empty to begin with (see the comment for
+  //     _set_filtered_elements_cafilt)
+  vector<PseudoJet> subjets; 
+  JetDefinition subjet_def;
+  bool discard_area;
+  // NB: on return, subjet_def is set to the jet definition actually
+  //     used (so that we can make use of its recombination scheme 
+  //     when joining the jets to be kept).
+  _set_filtered_elements(jet, subjets, subjet_def, discard_area);
+
+  // now build the vector of kept and rejected subjets
+  vector<PseudoJet> kept, rejected;
+  // Note that in the following line we make a copy of the _selector
+  // to avoid issues with needing a mutable _selector
+  Selector selector_copy = _selector;
+  if (selector_copy.takes_reference()) selector_copy.set_reference(jet);
+  selector_copy.sift(subjets, kept, rejected);
+
+  // gather the info under the form of a PseudoJet
+  return _finalise(jet, kept, rejected, subjet_def, discard_area);
+}
+
+
+// sets filtered_elements to be all the subjets on which filtering will work
+void Filter::_set_filtered_elements(const PseudoJet & jet,
+                                    vector<PseudoJet> & filtered_elements,
+                                    JetDefinition & subjet_def,
+                                    bool & discard_area) const {
+  // sanity checks
+  //-------------------------------------------------------------------
+  // make sure that the jet has constituents
+  if (! jet.has_constituents())
+    throw Error("Filter can only be applied on jets having constituents");
+
+  // for a whole variety of checks, we shall need the "recursive"
+  // pieces of the jet (the jet itself or recursing down to its most
+  // fundamental pieces).
+  // So we do compute these once and for all
+  vector<PseudoJet> all_pieces; //.clear();
+  if ((!_get_all_pieces(jet, all_pieces)) || (all_pieces.size()==0))
+    throw Error("Attempt to filter a jet that has no associated ClusterSequence or is not a superposition of jets associated with a ClusterSequence");
+  
+  // if the filter uses subtraction, make sure we have a CS that supports area and has
+  // explicit ghosts 
+  if (_uses_subtraction()) {
+    if (!jet.has_area())   
+      throw Error("Attempt to filter and subtract (non-zero rho or subtractor) without area info for the original jet");
+
+    if (!_check_explicit_ghosts(all_pieces))
+      throw Error("Attempt to filter and subtract (non-zero rho or subtractor) without explicit ghosts");
+  }
+
+  // if we're dealing with a dynamic determination of the filtering
+  // radius, do it now
+  if ((_Rfilt>=0) || (_Rfiltfunc)){
+    double Rfilt = (_Rfiltfunc) ? (*_Rfiltfunc)(jet) : _Rfilt;
+    const JetDefinition::Recombiner * common_recombiner = _get_common_recombiner(all_pieces);
+    if (common_recombiner) {
+      if (typeid(*common_recombiner) == typeid(JetDefinition::DefaultRecombiner)) {
+        RecombinationScheme scheme = 
+          static_cast<const JetDefinition::DefaultRecombiner *>(common_recombiner)->scheme();
+        subjet_def = JetDefinition(cambridge_algorithm, Rfilt, scheme);
+      } else {
+        subjet_def = JetDefinition(cambridge_algorithm, Rfilt, common_recombiner);
+      }
+    } else {
+      subjet_def = JetDefinition(cambridge_algorithm, Rfilt);
+    }
+  } else {
+    subjet_def = _subjet_def;
+  }
+
+  // get the jet definition to be use and whether we can apply our
+  // simplified C/A+C/A filter
+  //
+  // we apply C/A clustering iff
+  //  - the request subjet_def is C/A
+  //  - the jet is either directly coming from C/A or if it is a
+  //    superposition of C/A jets
+  //  - the pieces agree with the recombination scheme of subjet_def
+  //------------------------------------------------------------------
+  bool simple_cafilt = _check_ca(all_pieces);
+
+  // extract the subjets
+  //-------------------------------------------------------------------
+  discard_area = false;
+  if (simple_cafilt){
+    // first make sure that 'filtered_elements' is empty
+    filtered_elements.clear();
+    _set_filtered_elements_cafilt(jet, filtered_elements, subjet_def.R());
+    // in the following case, areas can be erroneous and will be discarded
+    discard_area = (!_uses_subtraction()) && (jet.has_area()) && (!_check_explicit_ghosts(all_pieces));
+  } else {
+    // here we'll simply recluster the jets.
+    //
+    // To include an area support we need
+    //  - the jet to have an area
+    //  - subtraction requested or explicit ghosts
+    bool do_areas = (jet.has_area()) && ((_uses_subtraction()) || (_check_explicit_ghosts(all_pieces))); 
+    _set_filtered_elements_generic(jet, filtered_elements, subjet_def, do_areas);
+  }
+
+  // order the filtered elements in pt
+  filtered_elements = sorted_by_pt(filtered_elements);
+}
+
+// set the filtered elements in the simple case of C/A+C/A
+//
+// WATCH OUT: this could be recursively called, so filtered elements
+//            of 'jet' are APPENDED to 'filtered_elements'
+void Filter::_set_filtered_elements_cafilt(const PseudoJet & jet, 
+                                           vector<PseudoJet> & filtered_elements, 
+                                           double Rfilt) const{
+  // we know that the jet is either a C/A jet or a superposition of
+  // such pieces
+  if (jet.has_associated_cluster_sequence()){
+    // just extract the exclusive subjets of 'jet'
+    const ClusterSequence *cs = jet.associated_cluster_sequence(); 
+    vector<PseudoJet> local_fe;
+
+    double dcut = Rfilt / cs->jet_def().R();
+    if (dcut>=1.0){
+      local_fe.push_back(jet);
+    } else {
+      dcut *= dcut;
+      local_fe = jet.exclusive_subjets(dcut);
+    }
+
+    // subtract the jets if needed
+    // Note that this one would work on pieces!!
+    //-----------------------------------------------------------------
+    if (_uses_subtraction()){
+      const ClusterSequenceAreaBase * csab = jet.validated_csab();
+      for (unsigned int i=0;i<local_fe.size();i++) {
+        if (_subtractor) {
+          local_fe[i] = (*_subtractor)(local_fe[i]);
+        } else {
+          local_fe[i] = csab->subtracted_jet(local_fe[i], _rho);
+        }
+      }
+    }
+
+    copy(local_fe.begin(), local_fe.end(), back_inserter(filtered_elements));
+    return;
+  }
+
+  // just recurse into the pieces
+  const vector<PseudoJet> & pieces = jet.pieces();
+  for (vector<PseudoJet>::const_iterator it = pieces.begin(); 
+       it!=pieces.end(); it++)
+    _set_filtered_elements_cafilt(*it, filtered_elements, Rfilt);
+}
+
+
+// set the filtered elements in the generic re-clustering case (wo
+// subtraction)
+void Filter::_set_filtered_elements_generic(const PseudoJet & jet, 
+                                            vector<PseudoJet> & filtered_elements,
+                                            const JetDefinition & subjet_def,
+					    bool do_areas) const{
+  // create a new, internal, ClusterSequence from the jet constituents
+  // get the subjets directly from there
+  //
+  // If the jet has area support then we separate the ghosts from the
+  // "regular" particles so the subjets will also have area
+  // support. Note that we do this regardless of whether rho is zero
+  // or not.
+  //
+  // Note that to be able to separate the ghosts, one needs explicit
+  // ghosts!!
+  // ---------------------------------------------------------------
+  if (do_areas){
+    vector<PseudoJet> all_constituents = jet.constituents();
+    vector<PseudoJet> regular_constituents, ghosts;  
+
+    for (vector<PseudoJet>::iterator it = all_constituents.begin(); 
+         it != all_constituents.end(); it++){
+      if (it->is_pure_ghost())
+        ghosts.push_back(*it);
+      else
+        regular_constituents.push_back(*it);
+    }
+
+    // figure out the ghost area from the 1st ghost (if none, any value
+    // would probably do as the area will be 0 and subtraction will have
+    // no effect!)
+    double ghost_area = (ghosts.size()) ? ghosts[0].area() : 0.01;
+    ClusterSequenceActiveAreaExplicitGhosts * csa
+      = new ClusterSequenceActiveAreaExplicitGhosts(regular_constituents, 
+                                                    subjet_def, 
+                                                    ghosts, ghost_area);
+
+    // get the subjets: we use the subtracted or unsubtracted ones
+    // depending on rho or _subtractor being non-zero
+    if (_uses_subtraction()) {
+      if (_subtractor) {
+        filtered_elements = (*_subtractor)(csa->inclusive_jets());
+      } else {
+        filtered_elements = csa->subtracted_jets(_rho);
+      }
+    } else {
+      filtered_elements = csa->inclusive_jets();
+    }
+
+    // allow the cs to be deleted when it's no longer used
+    csa->delete_self_when_unused();
+  } else {
+    ClusterSequence * cs = new ClusterSequence(jet.constituents(), subjet_def);
+    filtered_elements = cs->inclusive_jets();
+    // allow the cs to be deleted when it's no longer used
+    cs->delete_self_when_unused();
+  }
+}
+
+
+// gather the information about what is kept and rejected under the
+// form of a PseudoJet with a special ClusterSequenceInfo
+PseudoJet Filter::_finalise(const PseudoJet & /*jet*/, 
+                            vector<PseudoJet> & kept, 
+                            vector<PseudoJet> & rejected,
+                            const JetDefinition & subjet_def,
+                            const bool discard_area) const {
+  // figure out which recombiner to use
+  const JetDefinition::Recombiner &rec = *(subjet_def.recombiner());
+
+  // create an appropriate structure and transfer the info to it
+  PseudoJet filtered_jet = join<StructureType>(kept, rec);
+  StructureType *fs = (StructureType*) filtered_jet.structure_non_const_ptr();
+//  fs->_original_jet = jet;
+  fs->_rejected = rejected;
+
+  if (discard_area){
+    // safety check: make sure there is an area to discard!!!
+    assert(fs->_area_4vector_ptr);
+    delete fs->_area_4vector_ptr;
+    fs->_area_4vector_ptr=0;
+  }
+  
+  return filtered_jet;
+}
+
+// various checks
+//----------------------------------------------------------------------
+
+// get the pieces down to the fundamental pieces
+// 
+// Note that this just checks that there is an associated CS to the
+// fundamental pieces, not that it is still valid
+bool Filter::_get_all_pieces(const PseudoJet &jet, vector<PseudoJet> &all_pieces) const{
+  if (jet.has_associated_cluster_sequence()){
+    all_pieces.push_back(jet);
+    return true;
+  }
+
+  if (jet.has_pieces()){
+    const vector<PseudoJet> pieces = jet.pieces();
+    for (vector<PseudoJet>::const_iterator it=pieces.begin(); it!=pieces.end(); it++)
+      if (!_get_all_pieces(*it, all_pieces)) return false;
+    return true;
+  }
+
+  return false;
+}
+
+// get the common recombiner to all pieces (NULL if none)
+//
+// Note that if the jet has an associated cluster sequence that is no
+// longer valid, an error will be thrown (needed since it could be the
+// 1st check called after the enumeration of the pieces)
+const JetDefinition::Recombiner* Filter::_get_common_recombiner(const vector<PseudoJet> &all_pieces) const{
+  const JetDefinition & jd_ref = all_pieces[0].validated_cs()->jet_def();
+  for (unsigned int i=1; i<all_pieces.size(); i++)
+    if (!all_pieces[i].validated_cs()->jet_def().has_same_recombiner(jd_ref)) return NULL;
+
+  return jd_ref.recombiner();
+}
+
+// check if the jet (or all its pieces) have explicit ghosts
+// (assuming the jet has area support
+//
+// Note that if the jet has an associated cluster sequence that is no
+// longer valid, an error will be thrown (needed since it could be the
+// 1st check called after the enumeration of the pieces)
+bool Filter::_check_explicit_ghosts(const vector<PseudoJet> &all_pieces) const{
+  for (vector<PseudoJet>::const_iterator it=all_pieces.begin(); it!=all_pieces.end(); it++)
+    if (! it->validated_csab()->has_explicit_ghosts()) return false;
+  return true;
+}
+
+// check if one can apply the simplification for C/A subjets
+//
+// This includes:
+//  - the subjet definition asks for C/A subjets
+//  - all the pieces share the same CS
+//  - that CS is C/A with the same recombiner as the subjet def
+//  - the filtering radius is not larger than any of the pairwise
+//    distance between the pieces
+//
+// Note that if the jet has an associated cluster sequence that is no
+// longer valid, an error will be thrown (needed since it could be the
+// 1st check called after the enumeration of the pieces)
+bool Filter::_check_ca(const vector<PseudoJet> &all_pieces) const{
+  if (_subjet_def.jet_algorithm() != cambridge_algorithm) return false;
+
+  // check that the 1st of all the pieces (we're sure there is at
+  // least one) is coming from a C/A clustering. Then check that all
+  // the following pieces share the same ClusterSequence
+  const ClusterSequence * cs_ref = all_pieces[0].validated_cs();
+  if (cs_ref->jet_def().jet_algorithm() != cambridge_algorithm) return false;
+  for (unsigned int i=1; i<all_pieces.size(); i++)
+    if (all_pieces[i].validated_cs() != cs_ref) return false;
+
+  // check that the 1st peice has the same recombiner as the one used
+  // for the subjet clustering
+  // Note that since they share the same CS, checking the 2st one is enough
+  if (!cs_ref->jet_def().has_same_recombiner(_subjet_def)) return false;
+
+  // we also have to make sure that the filtering radius is not larger
+  // than any of the inter-pieces distance
+  double Rfilt2 = _subjet_def.R();
+  Rfilt2 *= Rfilt2;
+  for (unsigned int i=0; i<all_pieces.size()-1; i++){
+    for (unsigned int j=i+1; j<all_pieces.size(); j++){
+      if (all_pieces[i].squared_distance(all_pieces[j]) <  Rfilt2) return false;
+    }
+  }
+
+  return true;
+}
+
+//----------------------------------------------------------------------
+// FilterInterface implementation 
+//----------------------------------------------------------------------
+
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Filter.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Filter.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Filter.hh	(revision 5)
@@ -0,0 +1,257 @@
+#ifndef __FASTJET_TOOLS_FILTER_HH__
+#define __FASTJET_TOOLS_FILTER_HH__
+
+//STARTHEADER
+// $Id: Filter.hh 2694 2011-11-14 22:27:51Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include <fastjet/ClusterSequence.hh>
+#include <fastjet/Selector.hh>
+#include <fastjet/CompositeJetStructure.hh> // to derive the FilterStructure from CompositeJetStructure
+#include <fastjet/tools/Transformer.hh>     // to derive Filter from Transformer
+#include <iostream>
+#include <string>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+// fwd declarations
+class Filter;
+class FilterStructure;
+
+//----------------------------------------------------------------------
+/// @ingroup tools_generic
+/// \class Filter
+/// Class that helps perform filtering (Butterworth, Davison, Rubin
+/// and Salam, arXiv:0802.2470) and trimming (Krohn, Thaler and Wang,
+/// arXiv:0912.1342) on jets, optionally in conjunction with
+/// subtraction (Cacciari and Salam, arXiv:0707.1378).
+///
+/// For example, to apply filtering that reclusters a jet's
+/// constituents with the Cambridge/Aachen jet algorithm with R=0.3
+/// and then selects the 3 hardest subjets, one can use the following
+/// code:
+/// \code
+///    Filter filter(JetDefinition(cambridge_algorithm, 0.3), SelectorNHardest(3));
+///    PseudoJet filtered_jet = filter(original_jet);
+/// \endcode
+///
+/// To obtain trimming, involving for example the selection of all
+/// subjets carrying at least 3% of the original jet's pt, the
+/// selector would be replaced by SelectorPtFractionMin(0.03).
+///
+/// To additionally perform subtraction on the subjets prior to
+/// selection, either include a 3rd argument specifying the background
+/// density rho, or call the set_subtractor(...) member function.  If
+/// subtraction is requested, the original jet must be the result of a
+/// clustering with active area with explicit ghosts support or a
+/// merging of such pieces.
+///
+/// The information on the subjets that were kept and rejected can be
+/// obtained using:
+/// \code
+///    vector<PseudoJet> kept_subjets = filtered_jet.pieces();
+///    vector<PseudoJet> rejected_subjets = filtered_jet.structure_of<Filter>().rejected();
+/// \endcode
+///
+/// \section impl Implementation Note
+/// 
+/// If the original jet was defined with the Cambridge/Aachen
+/// algorithm (or is made of pieces each of which comes from the C/A
+/// alg) and the filtering definition is C/A, then the filter does not
+/// rerun the C/A algorithm on the constituents, but instead makes use
+/// of the existent C/A cluster sequence in the original jet. This
+/// increases the speed of the filter. 
+///
+/// See also \subpage Example11 for a further usage example.
+///
+/// Support for areas, reuse of C/A cluster sequences, etc.,
+/// considerably complicates the implementation of Filter. For an
+/// explanation of how a simpler filter might be coded, see the
+/// "User-defined transformers" appendix of the manual.
+class Filter : public Transformer{
+public:
+  /// trivial ctor
+  /// Note: this is just for derived classes
+  ///       a Filter initialised through this constructor will not work!
+  Filter() : _Rfiltfunc(0){};
+
+  /// define a filter that decomposes a jet into subjets using a
+  /// generic JetDefinition and then keeps only a subset of these
+  /// subjets according to a Selector. Optionally, each subjet may be
+  /// internally bakground-subtracted prior to selection.
+  ///
+  ///  \param subjet_def   the jet definition applied to obtain the subjets
+  ///  \param selector     the Selector applied to compute the kept subjets
+  ///  \param rho          if non-zero, backgruond-subtract each subjet befor selection
+  ///
+  /// Note: internal subtraction only applies on jets that are
+  /// obtained with a cluster sequence with area support and explicit
+  /// ghosts
+  Filter(JetDefinition subjet_def, Selector selector, double rho = 0.0) : 
+    _subjet_def(subjet_def), _Rfiltfunc(0), _Rfilt(-1), _selector(selector), _rho(rho), _subtractor(0) {}
+
+  /// Same as the full constructor (see above) but just specifying the radius
+  /// By default, Cambridge-Aachen is used
+  /// If the jet (or all its pieces) is obtained with a non-default
+  /// recombiner, that one will be used
+  ///  \param Rfilt   the filtering radius
+  Filter(double Rfilt, Selector selector, double rho = 0.0) : 
+    _Rfiltfunc(0), _Rfilt(Rfilt), _selector(selector), _rho(rho), _subtractor(0) { 
+    if (_Rfilt<0)
+      throw Error("Attempt to create a Filter with a negative filtering radius");
+  }
+
+  /// Same as the full constructor (see above) but just specifying a
+  /// filtering radius that will depend on the jet being filtered
+  /// As for the previous case, Cambridge-Aachen is used
+  /// If the jet (or all its pieces) is obtained with a non-default
+  /// recombiner, that one will be used
+  ///  \param Rfilt_func   the filtering radius function of a PseudoJet
+  Filter(FunctionOfPseudoJet<double> *Rfilt_func, Selector selector, double rho = 0.0) : 
+    _Rfiltfunc(Rfilt_func), _Rfilt(-1), _selector(selector), _rho(rho), _subtractor(0) {}
+
+  /// default dtor
+  virtual ~Filter(){};
+
+  /// Set a subtractor that is applied to all individual subjets before
+  /// deciding which ones to keep. It takes precedence over a non-zero rho.
+  void set_subtractor(const Transformer * subtractor) {_subtractor = subtractor;}
+
+  /// runs the filtering and sets kept and rejected to be the jets of interest
+  /// (with non-zero rho, they will have been subtracted).
+  ///
+  /// \param jet    the jet that gets filtered
+  /// \return the filtered jet
+  virtual PseudoJet result(const PseudoJet & jet) const;
+
+  /// class description
+  virtual std::string description() const;
+
+  // the type of the associated structure
+  typedef FilterStructure StructureType;
+
+private:
+  /// Sets filtered_elements to be all the subjets on which filtering will work.
+  /// It also sets the subjet_def to be used in joining things (the bit of
+  /// subjet def that is of interest for later is the recombiner).
+  void _set_filtered_elements(const PseudoJet & jet,
+                              std::vector<PseudoJet> & filtered_elements,
+                              JetDefinition & subjet_def,
+                              bool & discard_area) const;
+  
+  /// set the filtered elements in the simple case of C/A+C/A
+  void _set_filtered_elements_cafilt(const PseudoJet & jet,
+                                     std::vector<PseudoJet> & filtered_elements,
+                                     double Rfilt) const;
+
+  /// set the filtered elements in the generic re-clustering case
+  void _set_filtered_elements_generic(const PseudoJet & jet, 
+                                      std::vector<PseudoJet> & filtered_elements,
+                                      const JetDefinition & subjet_def,
+				      bool do_areas) const;
+
+  /// gather the information about what is kept and rejected under the
+  /// form of a PseudoJet with a special ClusterSequenceInfo
+  PseudoJet _finalise(const PseudoJet & jet, 
+                      std::vector<PseudoJet> & kept, 
+                      std::vector<PseudoJet> & rejected,
+                      const JetDefinition & subjet_def,
+                      const bool discard_area) const;
+
+  // a series of checks
+  //--------------------------------------------------------------------
+  /// get the pieces down to the fundamental pieces
+  bool _get_all_pieces(const PseudoJet &jet, std::vector<PseudoJet> &all_pieces) const;
+
+  /// get the common recombiner to all pieces (NULL if none)
+  const JetDefinition::Recombiner* _get_common_recombiner(const std::vector<PseudoJet> &all_pieces) const;
+
+  /// check if one can apply the simplified trick for C/A subjets
+  bool _check_ca(const std::vector<PseudoJet> &all_pieces) const;
+
+  /// check if the jet (or all its pieces) have explicit ghosts
+  /// (assuming the jet has area support
+  ///
+  /// Note that if the jet has an associated cluster sequence that is no
+  /// longer valid, an error will be thrown
+  bool _check_explicit_ghosts(const std::vector<PseudoJet> &all_pieces) const;
+
+  bool _uses_subtraction() const {return (_subtractor || _rho != 0);}
+
+  JetDefinition _subjet_def;   ///< the jet definition to use to extract the subjets
+  FunctionOfPseudoJet<double> *_Rfiltfunc; 
+                               ///< a dynamic filtering radius function of the jet being filtered
+  double _Rfilt;               ///< a constant specifying the subjet radius (with C/A)
+  Selector _selector;  ///< the subjet selection criterium
+  double _rho;                 ///< the background density (used for subtraction when possible)
+  const Transformer * _subtractor; ///< for subtracting bkgd density from subjets
+};
+
+
+
+//----------------------------------------------------------------------
+/// @ingroup tools_generic
+/// \class FilterStructure
+/// Class to contain structure information for a filtered jet.
+class FilterStructure : public CompositeJetStructure {
+public:
+  /// constructor from an original ClusterSequenceInfo
+  /// We just share the original ClusterSequenceWrapper and initialise
+  /// the rest
+  FilterStructure(const std::vector<PseudoJet> & pieces_in, 
+                  const JetDefinition::Recombiner *rec = 0)
+    : CompositeJetStructure(pieces_in, rec){}
+
+  /// virtual dtor to allow further overloading  
+  virtual ~FilterStructure(){}
+
+  /// description
+  virtual std::string description() const { return "Filtered PseudoJet"; }
+
+  //------------------------------------------------------------------
+  /// @name The filter-specific information
+  //------------------------------------------------------------------
+
+//  /// returns the original jet (the first of the original jets
+//  /// if you filtered a collection of jets)
+//  const PseudoJet & original() const {return _original_jet;}
+
+  /// returns the subjets that were not kept during the filtering procedure
+  /// (subtracted if the filter requests it, and valid in the original cs)
+  const std::vector<PseudoJet> & rejected() const {return _rejected;}
+
+  friend class Filter;  // allow the filter to change the protected/private members
+
+protected:
+//  PseudoJet _original_jet;           ///< the original jet
+  std::vector<PseudoJet> _rejected;  ///< the subjets rejected by the filter
+};
+
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
+
+#endif   // __FASTJET_TOOLS_FILTER_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/GridMedianBackgroundEstimator.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/GridMedianBackgroundEstimator.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/GridMedianBackgroundEstimator.cc	(revision 5)
@@ -0,0 +1,201 @@
+//STARTHEADER
+// $Id: GridMedianBackgroundEstimator.cc 999 2013-03-04 11:48:06Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#include "fastjet/tools/GridMedianBackgroundEstimator.hh"
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+// setting a new event
+//----------------------------------------------------------------------
+// tell the background estimator that it has a new event, composed
+// of the specified particles.
+void GridMedianBackgroundEstimator::set_particles(const vector<PseudoJet> & particles) {
+  fill(_scalar_pt.begin(), _scalar_pt.end(), 0.0);
+  for (unsigned i = 0; i < particles.size(); i++) {
+    int j = igrid(particles[i]);
+    if (j >= 0){
+      if (_rescaling_class == 0)
+        _scalar_pt[j] += particles[i].perp();
+      else
+        _scalar_pt[j] += particles[i].perp()/(*_rescaling_class)(particles[i]);
+    }
+  }
+  sort(_scalar_pt.begin(), _scalar_pt.end());
+
+  _has_particles = true;
+}
+
+
+//----------------------------------------------------------------------
+// retrieving fundamental information
+//----------------------------------------------------------------------
+// get rho, the median background density per unit area
+double GridMedianBackgroundEstimator::rho() const {
+  verify_particles_set();
+  return _percentile(_scalar_pt, 0.5) / _cell_area;
+}
+
+
+//----------------------------------------------------------------------
+// get sigma, the background fluctuations per unit area; must be
+// multipled by sqrt(area) to get fluctuations for a region of a
+// given area.
+double GridMedianBackgroundEstimator::sigma() const{
+  verify_particles_set();
+  // watch out: by definition, our sigma is the standard deviation of
+  // the pt density multiplied by the square root of the cell area
+  return (_percentile(_scalar_pt, 0.5) -
+          _percentile(_scalar_pt, (1.0-0.6827)/2.0)
+          )/sqrt(_cell_area);
+}
+
+//----------------------------------------------------------------------
+// get rho, the background density per unit area, locally at the
+// position of a given jet. Note that this is not const, because a
+// user may then wish to query other aspects of the background that
+// could depend on the position of the jet last used for a rho(jet)
+// determination.
+double GridMedianBackgroundEstimator::rho(const PseudoJet & jet)  {
+  verify_particles_set();
+  double rescaling = (_rescaling_class == 0) ? 1.0 : (*_rescaling_class)(jet);
+  return rescaling*rho();
+}
+
+
+//----------------------------------------------------------------------
+// get sigma, the background fluctuations per unit area, locally at
+// the position of a given jet. As for rho(jet), it is non-const.
+double GridMedianBackgroundEstimator::sigma(const PseudoJet & jet){
+  verify_particles_set();
+  double rescaling = (_rescaling_class == 0) ? 1.0 : (*_rescaling_class)(jet);
+  return rescaling*sigma();
+}
+
+//----------------------------------------------------------------------
+// verify that particles have been set and throw an error if not
+void GridMedianBackgroundEstimator::verify_particles_set() const {
+  if (!_has_particles) throw Error("GridMedianBackgroundEstimator::rho() or sigma() called without particles having been set");
+}
+
+
+//----------------------------------------------------------------------
+// description
+//----------------------------------------------------------------------
+string GridMedianBackgroundEstimator::description() const { 
+  ostringstream desc;
+  desc << "GridMedianBackgroundEstimator, with grid extension |y| < " << _ymax 
+       << " and requested grid spacing = " << _requested_grid_spacing;
+  return desc.str();
+}       
+
+
+//----------------------------------------------------------------------
+// configuring the behaviour
+//----------------------------------------------------------------------
+// Set a pointer to a class that calculates the rescaling factor as
+// a function of the jet (position). Note that the rescaling factor
+// is used both in the determination of the "global" rho (the pt/A
+// of each jet is divided by this factor) and when asking for a
+// local rho (the result is multiplied by this factor).
+//
+// The BackgroundRescalingYPolynomial class can be used to get a
+// rescaling that depends just on rapidity.
+//
+// Note that this has to be called BEFORE any attempt to do an
+// actual computation
+void GridMedianBackgroundEstimator::set_rescaling_class(const FunctionOfPseudoJet<double> * rescaling_class_in) {
+  // The rescaling is taken into account when particles are set. So
+  // you need to call set_particles again if you set the rescaling
+  // class. We thus warn if there are already some available
+  // particles
+  if (_has_particles)
+    _warning_rescaling.warn("GridMedianBackgroundEstimator::set_rescaling_class(): trying to set the rescaling class when there are already particles that have been set is dangerous: the rescaling will not affect the already existing particles resulting in mis-estimation of rho. You need to call set_particles() again before proceeding with any background estimation.");
+  
+  BackgroundEstimatorBase::set_rescaling_class(rescaling_class_in);
+}
+
+
+//----------------------------------------------------------------------
+// protected material
+//----------------------------------------------------------------------
+// configure the grid
+void GridMedianBackgroundEstimator::setup_grid() {
+
+  // since we've exchanged the arguments of the grid constructor,
+  // there's a danger of calls with exchanged ymax,spacing arguments -- 
+  // the following check should catch most such situations.
+  assert(_ymax>0 && _ymax - _ymin >= _requested_grid_spacing);
+
+  // this grid-definition code is becoming repetitive -- it should
+  // probably be moved somewhere central...
+  double ny_double = (_ymax-_ymin) / _requested_grid_spacing;
+  _ny = int(ny_double+0.5);
+  _dy = (_ymax-_ymin) / _ny;
+  
+  _nphi = int (twopi / _requested_grid_spacing + 0.5);
+  _dphi = twopi / _nphi;
+
+  // some sanity checking (could throw a fastjet::Error)
+  assert(_ny >= 1 && _nphi >= 1);
+
+  _ntotal = _nphi * _ny;
+  _scalar_pt.resize(_ntotal);
+  _cell_area = _dy * _dphi;
+}
+
+
+//----------------------------------------------------------------------
+// retrieve the grid cell index for a given PseudoJet
+int GridMedianBackgroundEstimator::igrid(const PseudoJet & p) const {
+  // directly taking int does not work for values between -1 and 0
+  // so use floor instead
+  // double iy_double = (p.rap() - _ymin) / _dy;
+  // if (iy_double < 0.0) return -1;
+  // int iy = int(iy_double);
+  // if (iy >= _ny) return -1;
+
+  // writing it as below gives a huge speed gain (factor two!). Even
+  // though answers are identical and the routine here is not the
+  // speed-critical step. It's not at all clear why.
+  int iy = int(floor( (p.rap() - _ymin) / _dy ));
+  if (iy < 0 || iy >= _ny) return -1;
+
+  int iphi = int( p.phi()/_dphi );
+  assert(iphi >= 0 && iphi <= _nphi);
+  if (iphi == _nphi) iphi = 0; // just in case of rounding errors
+
+  int igrid_res = iy*_nphi + iphi;
+  assert (igrid_res >= 0 && igrid_res < _ny*_nphi);
+  return igrid_res;
+}
+
+
+FASTJET_END_NAMESPACE        // defined in fastjet/internal/base.hh
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/GridMedianBackgroundEstimator.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/GridMedianBackgroundEstimator.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/GridMedianBackgroundEstimator.hh	(revision 5)
@@ -0,0 +1,175 @@
+#ifndef __GRID_MEDIAN_BACKGROUND_ESTIMATOR_HH__
+#define __GRID_MEDIAN_BACKGROUND_ESTIMATOR_HH__
+
+//STARTHEADER
+// $Id: GridMedianBackgroundEstimator.hh 2580 2011-09-13 17:25:43Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#include "fastjet/tools/BackgroundEstimatorBase.hh"
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+/// @ingroup tools_background
+/// \class GridMedianBackgroundEstimator
+/// 
+/// Background Estimator based on the median pt/area of a set of grid
+/// cells. 
+///
+/// Description of the method:
+///   This background estimator works by projecting the event onto a
+///   grid in rapidity and azimuth. In each grid cell, the scalar pt
+///   sum of the particles in the cell is computed. The background
+///   density is then estimated by the median of (scalar pt sum/cell
+///   area) for all cells.
+///
+/// Parameters:
+///   The class takes 2 arguments: the absolute rapidity extent of the 
+///   cells and the size of the grid cells. Note that the size of the cell
+///   will be adjusted in azimuth to satisfy the 2pi periodicity and
+///   in rapidity to match the requested rapidity extent.
+///
+/// Rescaling:
+///   It is possible to use a rescaling profile. In this case, the
+///   profile needs to be set before setting the particles and it will
+///   be applied to each particle (i.e. not to each cell). 
+///   Note also that in this case one needs to call rho(jet) instead of
+///   rho() [Without rescaling, they are identical]
+///
+class GridMedianBackgroundEstimator : public BackgroundEstimatorBase {
+public:
+  /// @name  constructors and destructors
+  //\{
+  //----------------------------------------------------------------
+  ///   \param ymax   maximal absolute rapidity extent of the grid
+  ///   \param requested_grid_spacing   size of the grid cell. The
+  ///            "real" cell size could differ due e.g. to the 2pi
+  ///             periodicity in azimuthal angle (size, not area)
+  GridMedianBackgroundEstimator(double ymax, double requested_grid_spacing) :
+    _ymin(-ymax), _ymax(ymax), 
+    _requested_grid_spacing(requested_grid_spacing),
+    _has_particles(false){setup_grid();}
+  //\}
+
+
+  /// @name setting a new event
+  //\{
+  //----------------------------------------------------------------
+
+  /// tell the background estimator that it has a new event, composed
+  /// of the specified particles.
+  void set_particles(const std::vector<PseudoJet> & particles);
+
+  //\}
+
+  /// @name  retrieving fundamental information
+  //\{
+  //----------------------------------------------------------------
+
+  /// returns rho, the median background density per unit area
+  double rho() const;
+
+  /// returns sigma, the background fluctuations per unit area; must be
+  /// multipled by sqrt(area) to get fluctuations for a region of a
+  /// given area.
+  double sigma() const;
+
+  /// returns rho, the background density per unit area, locally at the
+  /// position of a given jet. Note that this is not const, because a
+  /// user may then wish to query other aspects of the background that
+  /// could depend on the position of the jet last used for a rho(jet)
+  /// determination.
+  double rho(const PseudoJet & jet);
+
+  /// returns sigma, the background fluctuations per unit area, locally at
+  /// the position of a given jet. As for rho(jet), it is non-const.
+  double sigma(const PseudoJet & jet);
+
+  /// returns true if this background estimator has support for
+  /// determination of sigma
+  bool has_sigma() {return true;}
+
+  /// returns the area of the grid cells (all identical, but
+  /// referred to as "mean" area for uniformity with JetMedianBGE).
+  double mean_area() const {return _cell_area;}
+  //\}
+
+  /// @name configuring the behaviour
+  //\{
+  //----------------------------------------------------------------
+
+  /// Set a pointer to a class that calculates the rescaling factor as
+  /// a function of the jet (position). Note that the rescaling factor
+  /// is used both in the determination of the "global" rho (the pt/A
+  /// of each jet is divided by this factor) and when asking for a
+  /// local rho (the result is multiplied by this factor).
+  ///
+  /// The BackgroundRescalingYPolynomial class can be used to get a
+  /// rescaling that depends just on rapidity.
+  ///
+  /// Note that this has to be called BEFORE any attempt to do an
+  /// actual computation
+  virtual void set_rescaling_class(const FunctionOfPseudoJet<double> * rescaling_class);
+
+  //\}
+
+  /// @name description
+  //\{
+  //----------------------------------------------------------------
+
+  /// returns a textual description of the background estimator
+  std::string description() const;
+
+  //\}
+
+
+private:
+  /// configure the grid
+  void setup_grid();
+
+  /// retrieve the grid cell index for a given PseudoJet
+  int igrid(const PseudoJet & p) const;
+
+  /// verify that particles have been set and throw an error if not
+  void verify_particles_set() const;
+
+  // information about the grid
+  double _ymin, _ymax, _dy, _dphi, _requested_grid_spacing, _cell_area;
+  int _ny, _nphi, _ntotal;
+
+  // information abotu the event
+  std::vector<double> _scalar_pt;
+  bool _has_particles;
+
+  // various warnings to let people aware of potential dangers
+  LimitedWarning _warning_rho_of_jet;
+  LimitedWarning _warning_rescaling;
+};
+
+FASTJET_END_NAMESPACE        // defined in fastjet/internal/base.hh
+
+#endif // __GRID_MEDIAN_BACKGROUND_ESTIMATOR_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/JHTopTagger.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/JHTopTagger.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/JHTopTagger.cc	(revision 5)
@@ -0,0 +1,194 @@
+//STARTHEADER
+// $Id: JHTopTagger.cc 999 2013-03-04 11:48:06Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include <fastjet/tools/JHTopTagger.hh>
+#include <fastjet/Error.hh>
+#include <fastjet/JetDefinition.hh>
+#include <fastjet/ClusterSequence.hh>
+#include <sstream>
+#include <limits>
+
+FASTJET_BEGIN_NAMESPACE
+
+using namespace std;
+
+//----------------------------------------------------------------------
+// JHTopTagger class implementation
+//----------------------------------------------------------------------
+
+LimitedWarning JHTopTagger::_warnings_nonca;
+
+//------------------------------------------------------------------------
+// description of the tagger
+string JHTopTagger::description() const{ 
+  ostringstream oss;
+  oss << "JHTopTagger with delta_p=" << _delta_p << ", delta_r=" << _delta_r
+      << ", cos_theta_W_max=" << _cos_theta_W_max
+      << " and mW = " << _mW;
+  oss << description_of_selectors();
+  return oss.str();
+}
+
+//------------------------------------------------------------------------
+// returns the tagged PseudoJet if successful, 0 otherwise
+//  - jet   the PseudoJet to tag
+PseudoJet JHTopTagger::result(const PseudoJet & jet) const{
+  // make sure that there is a "regular" cluster sequence associated
+  // with the jet. Note that we also check it is valid (to avoid a
+  // more criptic error later on)
+  if (!jet.has_valid_cluster_sequence()){
+    throw Error("JHTopTagger can only be applied on jets having an associated (and valid) ClusterSequence");
+  }
+
+  // warn if the jet has not been clustered with a Cambridge/Aachen
+  // algorithm
+  if (! jet.validated_cs()->jet_def().jet_algorithm() == cambridge_algorithm)
+    _warnings_nonca.warn("JHTopTagger should only be applied on jets from a Cambridge/Aachen clustering; use it with other algorithms at your own risk.");
+
+
+  // do the first splitting
+  vector<PseudoJet> split0 = _split_once(jet, jet);
+  if (split0.size() == 0) return PseudoJet();
+
+  // now try a second splitting on each of the resulting objects
+  vector<PseudoJet> subjets;
+  for (unsigned i = 0; i < 2; i++) {
+    vector<PseudoJet> split1 = _split_once(split0[i], jet);
+    if (split1.size() > 0) {
+      subjets.push_back(split1[0]);
+      subjets.push_back(split1[1]);
+    } else {
+      subjets.push_back(split0[i]);
+    }
+  }
+
+  // make sure things make sense
+  if (subjets.size() < 3) return PseudoJet();
+
+  // now find the pair of objects closest in mass to the W
+  double dmW_min = numeric_limits<double>::max();
+  int ii=-1, jj=-1;
+  for (unsigned i = 0 ; i < subjets.size()-1; i++) {
+    for (unsigned j = i+1 ; j < subjets.size(); j++) {
+      double dmW = abs(_mW - (subjets[i]+subjets[j]).m());
+      if (dmW < dmW_min) {
+        dmW_min = dmW; ii = i; jj = j;
+      }
+    }
+  }
+
+  // order the subjets in the following order:
+  //  - hardest of the W subjets
+  //  - softest of the W subjets
+  //  - hardest of the remaining subjets
+  //  - softest of the remaining subjets (if any)
+  if (ii>0) std::swap(subjets[ii], subjets[0]);
+  if (jj>1) std::swap(subjets[jj], subjets[1]);
+  if (subjets[0].perp2() < subjets[1].perp2()) std::swap(subjets[0], subjets[1]);
+  if ((subjets.size()>3) && (subjets[2].perp2() < subjets[3].perp2())) 
+    std::swap(subjets[2], subjets[3]);
+  
+  // create the result and its structure
+  const JetDefinition::Recombiner *rec
+    = jet.associated_cluster_sequence()->jet_def().recombiner();
+
+  PseudoJet W = join(subjets[0], subjets[1], *rec);
+  PseudoJet non_W;
+  if (subjets.size()>3) {
+    non_W = join(subjets[2], subjets[3], *rec);
+  } else {
+    non_W = join(subjets[2], *rec);
+  }
+  PseudoJet result_local = join<JHTopTaggerStructure>(W, non_W, *rec);
+  JHTopTaggerStructure *s = (JHTopTaggerStructure*) result_local.structure_non_const_ptr();
+  s->_cos_theta_w = _cos_theta_W(result_local);
+
+  // if the polarisation angle does not pass the cut, consider that
+  // the tagging has failed
+  //
+  // Note that we could perhaps ensure this cut before constructing
+  // the result structure but this has the advantage that the top
+  // 4-vector is already available and does not have to de re-computed
+  if (s->_cos_theta_w >= _cos_theta_W_max ||
+      ! _top_selector.pass(result_local) || ! _W_selector.pass(W)
+      ) {
+    result_local *= 0.0;
+  }
+
+  return result_local;
+
+  // // old version
+  // PseudoJet result = join<JHTopTaggerStructure>(subjets, *rec);
+  // JHTopTaggerStructure *s = (JHTopTaggerStructure*) result.structure_non_const_ptr();
+  // //  s->_original_jet = jet;
+  // s->_W = join(subjets[0], subjets[1], *rec);
+  // if (subjets.size()>3)
+  //   s->_non_W = join(subjets[2], subjets[3], *rec);
+  // else
+  //   s->_non_W = join(subjets[2], *rec);
+  // s->_cos_theta_w = _cos_theta_W(result);
+  // 
+  // // if the polarisation angle does not pass the cut, consider that
+  // // the tagging has failed
+  // //
+  // // Note that we could perhaps ensure this cut before constructing
+  // // the result structure but this has the advantage that the top
+  // // 4-vector is already available and does not have to de re-computed
+  // if (s->_cos_theta_w >= _cos_theta_W_max)
+  //   return PseudoJet();
+  // 
+  // return result;
+}
+
+// runs the Johns Hopkins decomposition procedure
+vector<PseudoJet> JHTopTagger::_split_once(const PseudoJet & jet_to_split,
+                                           const PseudoJet & reference_jet) const{
+  PseudoJet this_jet = jet_to_split;
+  PseudoJet p1, p2;
+  vector<PseudoJet> result_local;
+  while (this_jet.has_parents(p1, p2)) {
+    if (p2.perp2() > p1.perp2()) std::swap(p1,p2); // order with hardness
+    if (p1.perp() < _delta_p * reference_jet.perp()) break; // harder is too soft wrt original jet
+    if ( (abs(p2.rap()-p1.rap()) + abs(p2.delta_phi_to(p1))) < _delta_r) break; // distance is too small
+    if (p2.perp() < _delta_p * reference_jet.perp()) {
+      this_jet = p1; // softer is too soft wrt original, so ignore it
+      continue; 
+    }
+    //result.push_back(this_jet);
+    result_local.push_back(p1);
+    result_local.push_back(p2);
+    break;
+  }
+  return result_local;
+}
+
+
+
+
+FASTJET_END_NAMESPACE
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/JHTopTagger.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/JHTopTagger.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/JHTopTagger.hh	(revision 5)
@@ -0,0 +1,220 @@
+#ifndef __FASTJET_JH_TOP_TAGGER_HH__
+#define __FASTJET_JH_TOP_TAGGER_HH__
+
+//STARTHEADER
+// $Id: JHTopTagger.hh 2689 2011-11-14 14:51:06Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#include <fastjet/tools/TopTaggerBase.hh>
+#include <fastjet/CompositeJetStructure.hh>
+#include <fastjet/LimitedWarning.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+class JHTopTagger;
+class JHTopTaggerStructure;
+
+//----------------------------------------------------------------------
+/// @ingroup tools_taggers
+/// \class JHTopTagger
+/// Class that helps perform boosted top tagging using the "Johns Hopkins"
+/// method from arXiv:0806.0848 (Kaplan, Rehermann, Schwartz
+/// and Tweedie)
+///
+///The tagger proceeds as follows:
+///  - start from a jet J obtained with the Cambridge/Aachen algorithm
+///  - undo the last iteration j -> j_1,j_2 (with pt_1>pt_2) until the
+///    two subjets satisfy pt_1 > delta_p pt_J (with pt_J the pt of
+///    the original jet) and |y_1 - y_2| + |phi_1 - phi_2| > delta_r.
+///  - if one of these criteria is not satisfied, carry on the
+///    procedure with j_1 (discarding j_2)
+///  - for each of the subjets found, repeat the procedure. If some
+///    new substructure is found, keep these 2 new subjets, otherwise
+///    keep the original subjet (found during the first iteration)
+///  - at this stage, one has at most 4 subjets. If one has less than
+///    3, the tagger has failed.
+///  - reconstruct the W from the 2 subjets with a mass closest to the
+///    W mass
+///  - impose that the W helicity angle be less than a threshold
+///    cos_theta_W_max.
+///
+/// \section input Input conditions
+/// 
+///  - the original jet must have an associated (and valid)
+///    ClusterSequence
+///  - the tagger is designed to work with jets formed by the
+///    Cambridge/Aachen (C/A) algorithm; if a non-C/A jet is passed to
+///    the tagger, a warning will be issued
+///
+/// \section Example
+///
+/// A  JHTopTagger can be used as follows:
+///
+/// \code
+///    double delta_p = 0.10; // subjets must carry at least this fraction of the original jet's p_t
+///    double delta_r = 0.19; // subjets must be separated by at least this Manhattan distance
+///    double cos_theta_W_max = 0.7; // the maximal allowed value of the W helicity angle
+///    JHTopTagger top_tagger(delta_p, delta_r, cos_theta_W_max);
+///    // indicate the acceptable range of top, W masses (default: no limits)
+///    top_tagger.set_top_selector(SelectorMassRange(150,200));
+///    top_tagger.set_W_selector  (SelectorMassRange( 65, 95));
+///    // now try and tag a jet
+///    PseudoJet top_candidate = top_tagger(jet);  // jet should come from a Cambridge/Aachen clustering
+///    if (top_candidate != 0) { // successful tagging
+///      double top_mass = top_candidate.m();
+///      double W_mass   = top_candidate.structure_of<JHTopTagger>().W().m();
+///    }
+/// \endcode
+///
+/// The full set of information available from the structure_of<JHTopTagger>() 
+/// call is
+///
+/// - PseudoJet W()    : the W subjet of the top candidate
+/// - PseudoJet non_W(): non-W subjet(s) of the top candidate (i.e. the b)
+/// - double cos_theta_W(): the W helicity angle
+/// - PseudoJet W1(): the harder of the two prongs of the W
+/// - PseudoJet W2(): the softer of the two prongs of the W
+///
+/// The structure of the top_candidate can also be accessed through its
+/// pieces() function:
+///
+/// - top_candidate.pieces()[0]: W
+/// - top_candidate.pieces()[1]: non_W
+///
+/// The W itself has two pieces (corresponding to W1, W2). 
+///
+/// The existence of the first two of the structural calls (W(),
+/// non_W()) and the fact that the top is made of two pieces (W,
+/// non_W) are features that should be common to all taggers derived
+/// from TopTaggerBase.
+///
+/// See also \subpage Example13 for a full usage example.
+///
+class JHTopTagger : public TopTaggerBase {
+public:
+  /// default ctor
+  /// The parameters are the following:
+  ///  \param delta_p          fractional pt cut imposed on the subjets
+  ///                          (computed as a fraction of the original jet)
+  ///  \param delta_r          minimal distance between 2 subjets
+  ///                          (computed as |y1-y2|+|phi1-phi2|)
+  ///  \param cos_theta_W_max  the maximal value for the polarisation 
+  ///                          angle of the W
+  ///  \param mW               the W mass
+  ///
+  /// The default values of all these parameters are taken from
+  /// arXiv:0806:0848
+  JHTopTagger(const double delta_p=0.10, const double delta_r=0.19, 
+              double cos_theta_W_max=0.7, double mW=80.4)
+    : _delta_p(delta_p), _delta_r(delta_r),
+      _cos_theta_W_max(cos_theta_W_max), _mW(mW){};
+
+  /// returns a textual description of the tagger
+  virtual std::string description() const;
+
+  /// runs the tagger on the given jet and
+  /// returns the tagged PseudoJet if successful, or a PseudoJet==0 otherwise
+  /// (standard access is through operator()).
+  ///  \param jet   the PseudoJet to tag
+  virtual PseudoJet result(const PseudoJet & jet) const;
+
+  // the type of the associated structure
+  typedef JHTopTaggerStructure StructureType;
+
+protected:
+  /// runs the Johns Hopkins decomposition procedure
+  std::vector<PseudoJet> _split_once(const PseudoJet & jet_to_split,
+                                     const PseudoJet & reference_jet) const;
+
+  double _delta_p, _delta_r, _cos_theta_W_max, _mW;
+  static LimitedWarning _warnings_nonca;
+};
+
+
+//------------------------------------------------------------------------
+/// @ingroup tools_taggers
+/// \class JHTopTaggerStructure
+/// the structure returned by the JHTopTagger transformer.
+///
+/// See the JHTopTagger class description for the details of what
+/// is inside this structure
+///
+class JHTopTaggerStructure : public CompositeJetStructure, public TopTaggerBaseStructure {
+public:
+  /// ctor with pieces initialisation
+  JHTopTaggerStructure(std::vector<PseudoJet> pieces_in,
+                 const JetDefinition::Recombiner *recombiner = 0) :
+    CompositeJetStructure(pieces_in, recombiner), _cos_theta_w(0.0){}
+
+  /// returns the W subjet
+  inline const PseudoJet & W() const{ 
+    return _pieces[0];
+  }
+
+  /// returns the first W subjet (the harder)
+  inline PseudoJet W1() const{
+    assert(W().pieces().size()>0);
+    return W().pieces()[0];
+  }
+  
+  /// returns the second W subjet
+  inline PseudoJet W2() const{
+    assert(W().pieces().size()>1);
+    return W().pieces()[1];
+  }
+
+  /// returns the non-W subjet
+  /// It will have 1 or 2 pieces depending on whether the tagger has
+  /// found 3 or 4 pieces
+  inline const PseudoJet & non_W() const{ 
+    return _pieces[1];
+  }
+
+  /// returns the W helicity angle
+  inline double cos_theta_W() const {return _cos_theta_w;}
+
+//  /// returns the original jet (before tagging)
+//  const PseudoJet & original() const {return _original_jet;}
+
+
+protected:
+  double _cos_theta_w;      ///< the W helicity angle
+  //PseudoJet _W;             ///< the tagged W
+  //PseudoJet _non_W;         ///< the remaining pieces
+//  PseudoJet _original_jet;  ///< the original jet (before tagging)
+
+  // allow the tagger to set these
+  friend class JHTopTagger;
+};
+
+
+
+FASTJET_END_NAMESPACE
+
+#endif  //  __FASTJET_JH_TOP_TAGGER_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/JetMedianBackgroundEstimator.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/JetMedianBackgroundEstimator.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/JetMedianBackgroundEstimator.cc	(revision 5)
@@ -0,0 +1,444 @@
+//STARTHEADER
+// $Id: JetMedianBackgroundEstimator.cc 999 2013-03-04 11:48:06Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/tools/JetMedianBackgroundEstimator.hh"
+#include <fastjet/ClusterSequenceArea.hh>
+#include <fastjet/ClusterSequenceStructure.hh>
+#include <iostream>
+
+FASTJET_BEGIN_NAMESPACE     // defined in fastjet/internal/base.hh
+
+using namespace std;
+
+double BackgroundJetScalarPtDensity::result(const PseudoJet & jet) const {
+  std::vector<PseudoJet> constituents = jet.constituents();
+  double scalar_pt = 0;
+  for (unsigned i = 0; i < constituents.size(); i++) {
+    scalar_pt += pow(constituents[i].perp(), _pt_power);
+  }
+  return scalar_pt / jet.area();
+}
+
+
+//----------------------------------------------------------------------
+double BackgroundRescalingYPolynomial::result(const PseudoJet & jet) const {
+  double y = jet.rap();
+  double y2 = y*y;
+  double rescaling = _a0 + _a1*y + _a2*y2 + _a3*y2*y + _a4*y2*y2;
+  return rescaling;
+}
+
+/// allow for warnings
+LimitedWarning JetMedianBackgroundEstimator::_warnings;
+LimitedWarning JetMedianBackgroundEstimator::_warnings_zero_area;
+LimitedWarning JetMedianBackgroundEstimator::_warnings_preliminary;
+
+
+//---------------------------------------------------------------------
+// class JetMedianBackgroundEstimator
+// Class to estimate the density of the background per unit area
+//---------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+// ctors and dtors
+//----------------------------------------------------------------------
+// ctor that allows to set only the particles later on
+JetMedianBackgroundEstimator::JetMedianBackgroundEstimator(const Selector &rho_range,
+                                         const JetDefinition &jet_def,
+                                         const AreaDefinition &area_def)
+  : _rho_range(rho_range), _jet_def(jet_def), _area_def(area_def) {
+
+  // initialise things decently
+  reset();
+
+  // make a few checks
+  _check_jet_alg_good_for_median();
+}
+
+
+//----------------------------------------------------------------------
+// ctor from a cluster sequence
+//  - csa        the ClusterSequenceArea to use
+//  - rho_range  the Selector specifying which jets will be considered
+JetMedianBackgroundEstimator::JetMedianBackgroundEstimator( const Selector &rho_range, const ClusterSequenceAreaBase &csa)
+  : _rho_range(rho_range), _jet_def(JetDefinition()){
+
+  // initialise things properly
+  reset();
+
+  // tell the BGE about the cluster sequence
+  set_cluster_sequence(csa);
+}
+
+
+//----------------------------------------------------------------------
+// setting a new event
+//----------------------------------------------------------------------
+// tell the background estimator that it has a new event, composed
+// of the specified particles.
+void JetMedianBackgroundEstimator::set_particles(const vector<PseudoJet> & particles) {
+  // make sure that we have been provided a genuine jet definition 
+  if (_jet_def.jet_algorithm() == undefined_jet_algorithm)
+    throw Error("JetMedianBackgroundEstimator::set_particles can only be called if you set the jet (and area) definition explicitly through the class constructor");
+
+  // initialise things decently (including setting uptodate to false!)
+  //reset();
+  _uptodate=false;
+
+  // cluster the particles
+  // 
+  // One may argue that it is better to cache the particles and only
+  // do the clustering later but clustering the particles now has 2
+  // practical advantages:
+  //  - it allows to une only '_included_jets' in all that follows
+  //  - it avoids adding another flag to ensure particles are 
+  //    clustered only once
+  ClusterSequenceArea *csa = new ClusterSequenceArea(particles, _jet_def, _area_def);
+  _included_jets = csa->inclusive_jets();
+
+  // store the CS for later on
+  _csi = csa->structure_shared_ptr();
+  csa->delete_self_when_unused();
+}
+
+//----------------------------------------------------------------------
+// (re)set the cluster sequence (with area support) to be used by
+// future calls to rho() etc. 
+//
+// \param csa  the cluster sequence area
+//
+// Pre-conditions: 
+//  - one should be able to estimate the "empty area" (i.e. the area
+//    not occupied by jets). This is feasible if at least one of the following
+//    conditions is satisfied:
+//     ( i) the ClusterSequence has explicit ghosts
+//     (ii) the range selected has a computable area.
+//  - the jet algorithm must be suited for median computation
+//    (otherwise a warning will be issues)
+//
+// Note that selectors with e.g. hardest-jets exclusion do not have
+// a well-defined area. For this reasons, it is STRONGLY advised to
+// use an area with explicit ghosts.
+void JetMedianBackgroundEstimator::set_cluster_sequence(const ClusterSequenceAreaBase & csa) {
+  _csi = csa.structure_shared_ptr();
+
+  // sanity checks
+  //---------------
+  //  (i) check the alg is appropriate
+  _check_jet_alg_good_for_median();
+
+  //  (ii) check that, if there are no explicit ghosts, the selector has a finite area
+  if ((!csa.has_explicit_ghosts()) && (!_rho_range.has_finite_area())){
+    throw Error("JetMedianBackgroundEstimator: either an area with explicit ghosts (recommended) or a Selector with finite area is needed (to allow for the computation of the empty area)");
+  }
+
+  // get the initial list of jets
+  _included_jets = csa.inclusive_jets();
+
+  _uptodate = false;
+}
+
+
+//----------------------------------------------------------------------
+// (re)set the jets (which must have area support) to be used by future
+// calls to rho() etc.; for the conditions that must be satisfied
+// by the jets, see the Constructor that takes jets.
+void JetMedianBackgroundEstimator::set_jets(const vector<PseudoJet> &jets) {
+  
+  if (! jets.size())
+    throw Error("JetMedianBackgroundEstimator::JetMedianBackgroundEstimator: At least one jet is needed to compute the background properties");
+
+  // sanity checks
+  //---------------
+  //  (o) check that there is an underlying CS shared by all the jets
+  if (! (jets[0].has_associated_cluster_sequence()) && (jets[0].has_area()))
+    throw Error("JetMedianBackgroundEstimator::JetMedianBackgroundEstimator: the jets used to estimate the background properties must be associated with a valid ClusterSequenceAreaBase");
+
+  _csi = jets[0].structure_shared_ptr();
+  ClusterSequenceStructure * csi = dynamic_cast<ClusterSequenceStructure*>(_csi());
+  const ClusterSequenceAreaBase * csab = csi->validated_csab();
+
+  for (unsigned int i=1;i<jets.size(); i++){
+    if (! jets[i].has_associated_cluster_sequence()) // area automatic if the next test succeeds
+      throw Error("JetMedianBackgroundEstimator::set_jets(...): the jets used to estimate the background properties must be associated with a valid ClusterSequenceAreaBase");
+
+    if (jets[i].structure_shared_ptr().get() != _csi.get())
+      throw Error("JetMedianBackgroundEstimator::set_jets(...): all the jets used to estimate the background properties must share the same ClusterSequence");
+  }
+
+  //  (i) check the alg is appropriate
+  _check_jet_alg_good_for_median();
+
+  //  (ii) check that, if there are no explicit ghosts, the selector has a finite area
+  if ((!csab->has_explicit_ghosts()) && (!_rho_range.has_finite_area())){
+    throw Error("JetMedianBackgroundEstimator: either an area with explicit ghosts (recommended) or a Selector with finite area is needed (to allow for the computation of the empty area)");
+  }
+
+
+  // get the initial list of jets
+  _included_jets = jets;
+
+  // ensure recalculation of quantities that need it
+  _uptodate = false;
+}
+
+
+//----------------------------------------------------------------------
+// retrieving fundamental information
+//----------------------------------------------------------------
+
+// get rho, the median background density per unit area
+double JetMedianBackgroundEstimator::rho() const {
+  if (_rho_range.takes_reference())
+    throw Error("The background estimation is obtained from a selector that takes a reference jet. rho(PseudoJet) should be used in that case");
+  _recompute_if_needed();
+  return _rho;
+}
+
+// get sigma, the background fluctuations per unit area
+double JetMedianBackgroundEstimator::sigma() const {
+  if (_rho_range.takes_reference())
+    throw Error("The background estimation is obtained from a selector that takes a reference jet. rho(PseudoJet) should be used in that case");
+  _recompute_if_needed();
+  return _sigma;
+}
+
+// get rho, the median background density per unit area, locally at
+// the position of a given jet.
+//
+// If the Selector associated with the range takes a reference jet
+// (i.e. is relocatable), then for subsequent operations the
+// Selector has that jet set as its reference.
+double JetMedianBackgroundEstimator::rho(const PseudoJet & jet) {
+  _recompute_if_needed(jet);
+  double our_rho = _rho;
+  if (_rescaling_class != 0) { 
+    our_rho *= (*_rescaling_class)(jet);
+  }
+  return our_rho;
+}
+
+// get sigma, the background fluctuations per unit area,
+// locally at the position of a given jet.
+//
+// If the Selector associated with the range takes a reference jet
+// (i.e. is relocatable), then for subsequent operations the
+// Selector has that jet set as its reference.
+double JetMedianBackgroundEstimator::sigma(const PseudoJet &jet) {
+  _recompute_if_needed(jet);
+  double our_sigma = _sigma;
+  if (_rescaling_class != 0) { 
+    our_sigma *= (*_rescaling_class)(jet);
+  }
+  return our_sigma;
+}
+
+
+//----------------------------------------------------------------------
+// configuring behaviour
+//----------------------------------------------------------------------
+// reset to default values
+// 
+// set the variou options to their default values
+void JetMedianBackgroundEstimator::reset(){
+  // set the remaining default parameters
+  set_use_area_4vector();  // true by default
+  set_provide_fj2_sigma(false);
+
+  // reset the computed values
+  _rho = _sigma = 0.0;
+  _n_jets_used = _n_empty_jets = 0;
+  _empty_area = _mean_area = 0.0;
+
+  _included_jets.clear();
+
+  _jet_density_class = 0; // null pointer
+  _rescaling_class = 0;   // null pointer
+
+  _uptodate = false;
+}
+
+
+// Set a pointer to a class that calculates the quantity whose
+// median will be calculated; if the pointer is null then pt/area
+// is used (as occurs also if this function is not called).
+void JetMedianBackgroundEstimator::set_jet_density_class(const FunctionOfPseudoJet<double> * jet_density_class_in) {
+  _warnings_preliminary.warn("JetMedianBackgroundEstimator::set_jet_density_class: density classes are still preliminary in FastJet 3.0. Their interface may differ in future releases (without guaranteeing backward compatibility).");
+  _jet_density_class = jet_density_class_in;
+  _uptodate = false;
+}
+
+
+
+//----------------------------------------------------------------------
+// description
+//----------------------------------------------------------------------
+string JetMedianBackgroundEstimator::description() const { 
+  ostringstream desc;
+  desc << "JetMedianBackgroundEstimator, using " << _jet_def.description() 
+       << " with " << _area_def.description() 
+       << " and selecting jets with " << _rho_range.description();
+  return desc.str();
+}       
+
+
+
+//----------------------------------------------------------------------
+// computation of the background properties
+//----------------------------------------------------------------------
+// for estimation using a relocatable selector (i.e. local range)
+// this allows to set its position. Note that this HAS to be called
+// before any attempt to compute the background properties
+void JetMedianBackgroundEstimator::_recompute_if_needed(const PseudoJet &jet){
+  // if the range is relocatable, handles its relocation
+  if (_rho_range.takes_reference()){
+    // check that the reference is not the same as the previous one
+    // (would avoid an unnecessary recomputation)
+    if (jet == _current_reference) return;
+
+    // relocate the range and make sure things get recomputed the next
+    // time one tries to get some information
+    _rho_range.set_reference(jet);
+    _uptodate=false;
+  }
+
+  _recompute_if_needed();
+}
+
+// do the actual job
+void JetMedianBackgroundEstimator::_compute() const {
+  // check if the clustersequence is still valid
+  _check_csa_alive();
+
+  // fill the vector of pt/area (or the quantity from the jet density class) 
+  //  - in the range
+  vector<double> vector_for_median;
+  double total_area  = 0.0;
+  _n_jets_used = 0;
+
+  // apply the selector to the included jets
+  vector<PseudoJet> selected_jets = _rho_range(_included_jets);
+
+  // compute the pt/area for the selected jets
+  for (unsigned i = 0; i < selected_jets.size(); i++) {
+    const PseudoJet & current_jet = selected_jets[i];
+
+    double this_area = (_use_area_4vector) ? current_jet.area_4vector().perp() : current_jet.area(); 
+
+    if (this_area>0){
+      double median_input;
+      if (_jet_density_class == 0) {
+        median_input = current_jet.perp()/this_area;
+      } else {
+        median_input = (*_jet_density_class)(current_jet);
+      }
+      if (_rescaling_class != 0) {
+        median_input /= (*_rescaling_class)(current_jet);
+      }
+      vector_for_median.push_back(median_input);
+      total_area  += this_area;
+      _n_jets_used++;
+    } else {
+      _warnings_zero_area.warn("JetMedianBackgroundEstimator::_compute(...): discarded jet with zero area. Zero-area jets may be due to (i) too large a ghost area (ii) a jet being outside the ghost range (iii) the computation not being done using an appropriate algorithm (kt;C/A).");
+    }
+      
+  }
+  
+  // there is nothing inside our region, so answer will always be zero
+  if (vector_for_median.size() == 0) {
+    _rho        = 0.0;
+    _sigma      = 0.0;
+    _mean_area  = 0.0;
+    return;
+  }
+
+  // determine the number of empty jets
+  const ClusterSequenceAreaBase * csab = (dynamic_cast<ClusterSequenceStructure*>(_csi()))->validated_csab();
+  if (csab->has_explicit_ghosts()) {
+    _empty_area = 0.0;
+    _n_empty_jets = 0;
+  } else {
+    _empty_area = csab->empty_area(_rho_range);
+    _n_empty_jets = csab->n_empty_jets(_rho_range);
+  }
+
+  double total_njets = _n_jets_used + _n_empty_jets;
+  total_area  += _empty_area;
+
+  double stand_dev;
+  _median_and_stddev(vector_for_median, _n_empty_jets, _rho, stand_dev, 
+                     _provide_fj2_sigma);
+
+  // process and store the results (_rho was already stored above)
+  _mean_area  = total_area / total_njets;
+  _sigma      = stand_dev * sqrt(_mean_area);
+
+  // record that the computation has been performed  
+  _uptodate = true;
+}
+
+
+
+// check that the underlying structure is still alive;
+// throw an error otherwise
+void JetMedianBackgroundEstimator::_check_csa_alive() const{
+  ClusterSequenceStructure* csa = dynamic_cast<ClusterSequenceStructure*>(_csi());
+  if (csa == 0) {
+    throw Error("JetMedianBackgroundEstimator: there is no cluster sequence associated with the JetMedianBackgroundEstimator");
+  }
+  if (! dynamic_cast<ClusterSequenceStructure*>(_csi())->has_associated_cluster_sequence())
+    throw Error("JetMedianBackgroundEstimator: modifications are no longer possible as the underlying ClusterSequence has gone out of scope");
+}
+
+
+// check that the algorithm used for the clustering is suitable for
+// background estimation (i.e. either kt or C/A).
+// Issue a warning otherwise
+void JetMedianBackgroundEstimator::_check_jet_alg_good_for_median() const{
+  const JetDefinition * jet_def = &_jet_def;
+
+  // if no explicit jet def has been provided, fall back on the
+  // cluster sequence
+  if (_jet_def.jet_algorithm() == undefined_jet_algorithm){
+    const ClusterSequence * cs = dynamic_cast<ClusterSequenceStructure*>(_csi())->validated_cs();
+    jet_def = &(cs->jet_def());
+  }
+
+  if (jet_def->jet_algorithm() != kt_algorithm
+      && jet_def->jet_algorithm() != cambridge_algorithm
+      && jet_def->jet_algorithm() != cambridge_for_passive_algorithm) {
+    _warnings.warn("JetMedianBackgroundEstimator: jet_def being used may not be suitable for estimating diffuse backgrounds (good alternatives are kt, cam)");
+  }
+}
+
+
+
+
+FASTJET_END_NAMESPACE
+
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/JetMedianBackgroundEstimator.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/JetMedianBackgroundEstimator.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/JetMedianBackgroundEstimator.hh	(revision 5)
@@ -0,0 +1,466 @@
+#ifndef __FASTJET_BACKGROUND_ESTIMATOR_HH__
+#define __FASTJET_BACKGROUND_ESTIMATOR_HH__
+
+//STARTHEADER
+// $Id: JetMedianBackgroundEstimator.hh 2689 2011-11-14 14:51:06Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include <fastjet/ClusterSequenceAreaBase.hh>
+#include <fastjet/AreaDefinition.hh>
+#include <fastjet/FunctionOfPseudoJet.hh>
+#include <fastjet/Selector.hh>
+#include <fastjet/tools/BackgroundEstimatorBase.hh>
+#include <iostream>
+
+FASTJET_BEGIN_NAMESPACE     // defined in fastjet/internal/base.hh
+
+
+/// @ingroup tools_background
+/// \class JetMedianBackgroundEstimator
+///
+/// Class to estimate the pt density of the background per unit area,
+/// using the median of the distribution of pt/area from jets that
+/// pass some selection criterion.
+///
+/// Events are passed either in the form of the event particles (in
+/// which they're clustered by the class), a ClusterSequenceArea (in
+/// which case the jets used are those returned by "inclusive_jets()")
+/// or directly as a set of jets.
+///
+/// The selection criterion is typically a geometrical one (e.g. all
+/// jets with |y|<2) sometimes supplemented with some kinematical
+/// restriction (e.g. exclusion of the two hardest jets). It is passed
+/// to the class through a Selector.
+///
+/// Beware: 
+///   by default, to correctly handle partially empty events, the
+///   class attempts to calculate an "empty area", based
+///   (schematically) on
+///
+///          range.total_area() - sum_{jets_in_range} jets.area()
+///  
+///   For ranges with small areas, this can be inaccurate (particularly 
+///   relevant in dense events where empty_area should be zero and ends
+///   up not being zero).
+///
+///   This calculation of empty area can be avoided if a
+///   ClusterSequenceArea class with explicit ghosts
+///   (ActiveAreaExplicitGhosts) is used.  This is _recommended_
+///   unless speed requirements cause you to use Voronoi areas. For
+///   speedy background estimation you could also consider using
+///   GridMedianBackgroundEstimator.
+///
+///
+class JetMedianBackgroundEstimator : public BackgroundEstimatorBase {
+public:
+  /// @name constructors and destructors
+  //\{
+  //----------------------------------------------------------------
+  /// Constructor that sets the rho range as well as the jet
+  /// definition and area definition to be used to cluster the
+  /// particles. Prior to the estimation of rho, one has to provide
+  /// the particles to cluster using set_particles(...)
+  ///
+  /// \param rho_range  the Selector specifying which jets will be considered
+  /// \param jet_def    the jet definition to use for the clustering
+  /// \param area_def   the area definition to use for the clustering
+  JetMedianBackgroundEstimator(const Selector &rho_range,
+                               const JetDefinition &jet_def,
+                               const AreaDefinition &area_def);
+
+  /// ctor from a ClusterSequenceAreaBase with area
+  ///
+  /// \param rho_range   the Selector specifying which jets will be considered
+  /// \param csa         the ClusterSequenceArea to use
+  ///
+  /// Pre-conditions: 
+  ///  - one should be able to estimate the "empty area" (i.e. the area
+  ///    not occupied by jets). This is feasible if at least one of the following
+  ///    conditions is satisfied:
+  ///     ( i) the ClusterSequence has explicit ghosts
+  ///     (ii) the range has a computable area.
+  ///  - the jet algorithm must be suited for median computation
+  ///    (otherwise a warning will be issues)
+  ///
+  /// Note that selectors with e.g. hardest-jets exclusion do not have
+  /// a well-defined area. For this reasons, it is STRONGLY advised to
+  /// use an area with explicit ghosts.
+  JetMedianBackgroundEstimator(const Selector &rho_range,
+                               const ClusterSequenceAreaBase &csa);
+
+
+  /// Default constructor that optionally sets the rho range. The
+  /// configuration must be done later calling
+  /// set_cluster_sequence(...) or set_jets(...).
+  ///
+  /// \param rho_range   the Selector specifying which jets will be considered
+  ///
+  JetMedianBackgroundEstimator(const Selector &rho_range = SelectorIdentity())
+    : _rho_range(rho_range), _jet_def(JetDefinition()) { reset(); }
+  
+
+  /// default dtor
+  ~JetMedianBackgroundEstimator(){}
+
+  //\}
+
+
+  /// @name setting a new event
+  //\{
+  //----------------------------------------------------------------
+
+  /// tell the background estimator that it has a new event, composed
+  /// of the specified particles.
+  virtual void set_particles(const std::vector<PseudoJet> & particles);
+
+  /// (re)set the cluster sequence (with area support) to be used by
+  /// future calls to rho() etc. 
+  ///
+  /// \param csa  the cluster sequence area
+  ///
+  /// Pre-conditions: 
+  ///  - one should be able to estimate the "empty area" (i.e. the area
+  ///    not occupied by jets). This is feasible if at least one of the following
+  ///    conditions is satisfied:
+  ///     ( i) the ClusterSequence has explicit ghosts
+  ///     (ii) the range selected has a computable area.
+  ///  - the jet algorithm must be suited for median computation
+  ///    (otherwise a warning will be issues)
+  ///
+  /// Note that selectors with e.g. hardest-jets exclusion do not have
+  /// a well-defined area. For this reasons, it is STRONGLY advised to
+  /// use an area with explicit ghosts.
+  void set_cluster_sequence(const ClusterSequenceAreaBase & csa);
+
+  /// (re)set the jets (which must have area support) to be used by future
+  /// calls to rho() etc.; for the conditions that must be satisfied
+  /// by the jets, see the Constructor that takes jets.
+  void set_jets(const std::vector<PseudoJet> &jets);
+
+  /// (re)set the selector to be used for future calls to rho() etc.
+  void set_selector(const Selector & rho_range_selector) {
+    _rho_range = rho_range_selector;
+    _uptodate = false;
+  }
+
+  //\}
+
+
+  /// @name  retrieving fundamental information
+  //\{
+  //----------------------------------------------------------------
+
+  /// get rho, the median background density per unit area
+  double rho() const;
+
+  /// get sigma, the background fluctuations per unit area
+  double sigma() const;
+
+  /// get rho, the median background density per unit area, locally at
+  /// the position of a given jet.
+  ///
+  /// If the Selector associated with the range takes a reference jet
+  /// (i.e. is relocatable), then for subsequent operations the
+  /// Selector has that jet set as its reference.
+  double rho(const PseudoJet & jet);
+
+  /// get sigma, the background fluctuations per unit area,
+  /// locally at the position of a given jet.
+  ///
+  /// If the Selector associated with the range takes a reference jet
+  /// (i.e. is relocatable), then for subsequent operations the
+  /// Selector has that jet set as its reference.
+  double sigma(const PseudoJet &jet);
+
+  /// returns true if this background estimator has support for
+  /// determination of sigma
+  virtual bool has_sigma() {return true;}
+
+  //\}
+  
+  /// @name  retrieving additional useful information
+  //\{
+  //----------------------------------------------------------------
+  /// Returns the mean area of the jets used to actually compute the
+  /// background properties in the last call of rho() or sigma()
+  double mean_area() const{
+    _recompute_if_needed();
+    return _mean_area;
+  }
+  
+  /// returns the number of jets used to actually compute the
+  /// background properties in the last call of rho() or sigma()
+  unsigned int n_jets_used() const{
+    _recompute_if_needed();
+    return _n_jets_used;
+  }
+
+  /// Returns the estimate of the area (within the range defined by
+  /// the selector) that is not occupied by jets. The value is that
+  /// for the last call of rho() or sigma()
+  ///
+  /// The answer is defined to be zero if the area calculation
+  /// involved explicit ghosts; if the area calculation was an active
+  /// area, then use is made of the active area's internal list of
+  /// pure ghost jets (taking those that pass the selector); otherwise
+  /// it is based on the difference between the selector's total area
+  /// and the area of the jets that pass the selector.
+  ///
+  /// The result here is just the cached result of the corresponding
+  /// call to the ClusterSequenceAreaBase function.
+  double empty_area() const{
+    _recompute_if_needed();
+    return _empty_area;
+  }
+
+  /// Returns the number of empty jets used when computing the
+  /// background properties. The value is that for the last call of
+  /// rho() or sigma().
+  ///
+  /// If the area has explicit ghosts the result is zero; for active
+  /// areas it is the number of internal pure ghost jets that pass the
+  /// selector; otherwise it is deduced from the empty area, divided by 
+  /// \f$ 0.55 \pi R^2 \f$ (the average pure-ghost-jet area).
+  ///
+  /// The result here is just the cached result of the corresponding
+  /// call to the ClusterSequenceAreaBase function.
+  double n_empty_jets() const{
+    _recompute_if_needed();
+    return _n_empty_jets;
+  }
+
+  //}
+
+
+  /// @name configuring behaviour
+  //\{
+  //----------------------------------------------------------------
+
+  /// Resets the class to its default state, including the choice to
+  /// use 4-vector areas.
+  ///
+  void reset();
+
+  /// By default when calculating pt/Area for a jet, it is the
+  /// transverse component of the 4-vector area that is used in the ratiof \f$p_t/A\f$. 
+  /// Calling this function with a "false" argument causes the scalar area to
+  /// be used instead. 
+  ///
+  /// While the difference between the two choices is usually small,
+  /// for high-precision work it is usually the 4-vector area that is
+  /// to be preferred.
+  ///
+  ///  \param use_it             whether one uses the 4-vector area or not (true by default)
+  void set_use_area_4vector(bool use_it = true){
+    _use_area_4vector = use_it;
+    _uptodate = false;
+  }  
+
+  /// check if the estimator uses the 4-vector area or the scalar area
+  bool use_area_4vector() const{ return _use_area_4vector;}
+
+  /// The FastJet v2.X sigma calculation had a small spurious offset
+  /// in the limit of a small number of jets. This is fixed by default
+  /// in versions 3 upwards. The old behaviour can be obtained with a
+  /// call to this function.
+  void set_provide_fj2_sigma(bool provide_fj2_sigma = true) {
+    _provide_fj2_sigma = provide_fj2_sigma;
+    _uptodate = false;
+  }
+
+  /// Set a pointer to a class that calculates the quantity whose
+  /// median will be calculated; if the pointer is null then pt/area
+  /// is used (as occurs also if this function is not called).
+  ///
+  /// Note that this is still <i>preliminary</i> in FastJet 3.0 and
+  /// that backward compatibility is not guaranteed in future releases
+  /// of FastJet
+  void set_jet_density_class(const FunctionOfPseudoJet<double> * jet_density_class);
+
+  /// return the pointer to the jet density class
+  const FunctionOfPseudoJet<double> *  jet_density_class() const{
+    return _jet_density_class;
+  }
+
+  /// Set a pointer to a class that calculates the rescaling factor as
+  /// a function of the jet (position). Note that the rescaling factor
+  /// is used both in the determination of the "global" rho (the pt/A
+  /// of each jet is divided by this factor) and when asking for a
+  /// local rho (the result is multiplied by this factor).
+  ///
+  /// The BackgroundRescalingYPolynomial class can be used to get a
+  /// rescaling that depends just on rapidity.
+  virtual void set_rescaling_class(const FunctionOfPseudoJet<double> * rescaling_class_in) {
+    BackgroundEstimatorBase::set_rescaling_class(rescaling_class_in);
+    _uptodate = false;
+  }
+
+  //\}
+
+  /// @name description
+  //\{
+  //----------------------------------------------------------------
+
+  /// returns a textual description of the background estimator
+  std::string description() const;
+
+  //\}
+
+
+private:
+
+  /// do the actual job
+  void _compute() const;
+   
+  /// check if the properties need to be recomputed 
+  /// and do so if needed
+  void _recompute_if_needed() const {
+    if (!_uptodate) _compute();
+    _uptodate = true;
+  }
+
+  /// for estimation using a selector that takes a reference jet
+  /// (i.e. a selector that can be relocated) this function allows one
+  /// to set its position.
+  ///
+  /// Note that this HAS to be called before any attempt to compute
+  /// the background properties. The call is, however, performed
+  /// automatically by the functions rho(jet) and sigma(jet).
+  void _recompute_if_needed(const PseudoJet &jet);
+
+  /// check that the underlying structure is still alive
+  /// throw an error otherwise
+  void _check_csa_alive() const;
+
+  /// check that the algorithm used for the clustering is adapted for
+  /// background estimation (i.e. either kt or C/A)
+  /// Issue a warning otherwise
+  void _check_jet_alg_good_for_median() const;
+  
+  // the basic parameters of this class (passed through the variou ctors)
+  Selector _rho_range;                   ///< range to compute the background in
+  JetDefinition _jet_def;                ///< the jet def to use for teh clustering
+  AreaDefinition _area_def;              ///< the area def to use for teh clustering
+  std::vector<PseudoJet> _included_jets; ///< jets to be used
+  
+  // the tunable aprameters of the class
+  bool _use_area_4vector;
+  bool _provide_fj2_sigma;
+  const FunctionOfPseudoJet<double> * _jet_density_class;
+  //SharedPtr<BackgroundRescalingBase> _rescaling_class_sharedptr;
+  
+  // the actual results of the computation
+  mutable double _rho;               ///< background estimated density per unit area
+  mutable double _sigma;             ///< background estimated fluctuations
+  mutable double _mean_area;         ///< mean area of the jets used to estimate the background
+  mutable unsigned int _n_jets_used; ///< number of jets used to estimate the background
+  mutable double _n_empty_jets;      ///< number of empty (pure-ghost) jets
+  mutable double _empty_area;        ///< the empty (pure-ghost/unclustered) area!
+
+  // internal variables
+  SharedPtr<PseudoJetStructureBase> _csi; ///< allows to check if _csa is still valid
+  PseudoJet _current_reference;           ///< current reference jet
+  mutable bool _uptodate;                 ///< true when the background computation is up-to-date
+
+  /// handle warning messages
+  static LimitedWarning _warnings;
+  static LimitedWarning _warnings_zero_area;
+  static LimitedWarning _warnings_preliminary;
+};
+
+
+
+
+//----------------------------------------------------------------------
+/// @ingroup tools_background
+/// \class BackgroundJetPtDensity
+/// Class that implements pt/area_4vector.perp() for background estimation
+/// <i>(this is a preliminary class)</i>.
+class BackgroundJetPtDensity : public FunctionOfPseudoJet<double> {
+public:
+  virtual double result(const PseudoJet & jet) const {
+    return jet.perp() / jet.area_4vector().perp();
+  }
+  virtual std::string description() const {return "BackgroundJetPtDensity";}
+};
+
+
+//----------------------------------------------------------------------
+/// @ingroup tools_background
+/// \class BackgroundJetScalarPtDensity
+/// Class that implements (scalar pt sum of jet)/(scalar area of jet)
+/// for background estimation <i>(this is a preliminary class)</i>.
+///
+/// Optionally it can return a quantity based on the sum of pt^n,
+/// e.g. for use in subtracting fragementation function moments.
+class BackgroundJetScalarPtDensity : public FunctionOfPseudoJet<double> {
+public:
+  /// Default constructor provides background estimation with scalar pt sum
+  BackgroundJetScalarPtDensity() : _pt_power(1) {}
+
+  /// Constructor to provide background estimation based on 
+  /// \f$ sum_{i\in jet} p_{ti}^{n} \f$
+  BackgroundJetScalarPtDensity(double n) : _pt_power(n) {}
+
+  virtual double result(const PseudoJet & jet) const;
+
+  virtual std::string description() const {return "BackgroundScalarJetPtDensity";}
+
+private:
+  double _pt_power;
+};
+
+//----------------------------------------------------------------------
+/// @ingroup tools_background
+/// \class BackgroundJetPtMDensity
+/// Class that implements
+/// \f$  \frac{1}{A} \sum_{i \in jet} (\sqrt{p_{ti}^2+m^2} - p_{ti}) \f$
+/// for background estimation <i>(this is a preliminary class)</i>.
+/// 
+///
+/// This is useful for correcting jet masses in cases where the event
+/// involves massive particles.
+class BackgroundJetPtMDensity : public FunctionOfPseudoJet<double> {
+public:
+  virtual double result(const PseudoJet & jet) const {
+    std::vector<PseudoJet> constituents = jet.constituents();
+    double scalar_ptm = 0;
+    for (unsigned i = 0; i < constituents.size(); i++) {
+      scalar_ptm += constituents[i].mperp() - constituents[i].perp();
+    }
+    return scalar_ptm / jet.area();
+  }
+
+  virtual std::string description() const {return "BackgroundPtMDensity";}
+};
+
+
+
+FASTJET_END_NAMESPACE
+
+#endif  // __BACKGROUND_ESTIMATOR_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/MassDropTagger.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/MassDropTagger.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/MassDropTagger.cc	(revision 5)
@@ -0,0 +1,101 @@
+//STARTHEADER
+// $Id: MassDropTagger.cc 999 2013-03-04 11:48:06Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include <fastjet/tools/MassDropTagger.hh>
+#include <fastjet/ClusterSequence.hh>
+#include <sstream>
+
+FASTJET_BEGIN_NAMESPACE
+
+LimitedWarning MassDropTagger::_warnings_nonca;
+
+using namespace std;
+
+//----------------------------------------------------------------------
+// MassDropTagger class implementation
+//----------------------------------------------------------------------
+
+//------------------------------------------------------------------------
+// description of the tagger
+string MassDropTagger::description() const{ 
+  ostringstream oss;
+  oss << "MassDropTagger with mu=" << _mu << " and ycut=" << _ycut;
+  return oss.str();
+}
+
+//------------------------------------------------------------------------
+// returns the tagged PseudoJet if successful, 0 otherwise
+//  - jet   the PseudoJet to tag
+PseudoJet MassDropTagger::result(const PseudoJet & jet) const{
+  PseudoJet j = jet;
+
+  // issue a warning if the jet is not obtained through a C/A
+  // clustering
+  if ((! j.has_associated_cluster_sequence()) ||
+      (! j.validated_cs()->jet_def().jet_algorithm() == cambridge_algorithm))
+    _warnings_nonca.warn("MassDropTagger should only be applied on jets from a Cambridge/Aachen clustering; use it with other algorithms at your own risk.");
+
+
+  PseudoJet j1, j2;
+  bool had_parents;
+
+  // we just ask that we can "walk" in the cluster sequence.
+  // appropriate errors will be thrown automatically if this is not
+  // the case
+  while ((had_parents = j.has_parents(j1,j2))) {
+    // make parent1 the more massive jet
+    if (j1.m2() < j2.m2()) std::swap(j1,j2);
+
+    // if we pass the conditions on the mass drop and its degree of
+    // asymmetry (kt_dist/m^2 > rtycut [where kt_dist/m^2 \sim
+    // z/(1-z)), then we've found something interesting, so exit the
+    // loop
+    if ( (j1.m2() < _mu*_mu*j.m2()) && (j1.kt_distance(j2) > _ycut*j.m2()) )
+      break;
+    else
+      j = j1;
+  }
+    
+  if (!had_parents)
+    // no Higgs found, return an empty PseudoJet
+    return PseudoJet();
+
+  // create the result and its structure
+  PseudoJet result_local = j;
+  MassDropTaggerStructure * s = new MassDropTaggerStructure(result_local);
+//  s->_original_jet = jet;
+  s->_mu = (j.m2()!=0.0) ? sqrt(j1.m2()/j.m2()) : 0.0;
+  s->_y  = (j.m2()!=0.0) ? j1.kt_distance(j2)/j.m2() : 0.0;
+
+  result_local.set_structure_shared_ptr(SharedPtr<PseudoJetStructureBase>(s));
+
+  return result_local;
+}
+
+FASTJET_END_NAMESPACE
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/MassDropTagger.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/MassDropTagger.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/MassDropTagger.hh	(revision 5)
@@ -0,0 +1,154 @@
+//STARTHEADER
+// $Id: MassDropTagger.hh 2731 2011-11-21 12:15:21Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_MASS_DROP_TAGGER_HH__
+#define __FASTJET_MASS_DROP_TAGGER_HH__
+
+#include <fastjet/tools/Transformer.hh>
+#include <fastjet/LimitedWarning.hh>
+#include <fastjet/WrappedStructure.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+class MassDropTagger;
+class MassDropTaggerStructure;
+
+//----------------------------------------------------------------------
+/// @ingroup tools_taggers
+/// \class MassDropTagger
+/// Class that helps perform 2-pronged boosted tagging using
+/// the "mass-drop" technique (with asymmetry cut) introduced by Jonathan
+/// Butterworth, Adam Davison, Mathieu Rubin and Gavin Salam in
+/// arXiv:0802.2470 in the context of a boosted Higgs search.
+///
+/// The tagger proceeds as follows:
+///
+///  0. start from a jet obtained from with the Cambridge/Aachen
+///     algorithm
+///
+///  1. undo the last step of the clustering step j -> j1 + j2 (label
+///     them such as j1 is the most massive).
+///  
+///  2. if there is a mass drop, i.e. m_j1/m_j < mu_cut, and the
+///     splitting is sufficiently symmetric, \f${\rm
+///     min}(p_{tj1}^2,p_{tj2}^2)\Delta R_{j1,j2}^2 > y_{\rm cut}
+///     m_j^2\f$, keep j as the result of the tagger (with j1 and j2
+///     its 2 subjets)
+///
+///  3. otherwise, redefine j to be equal to j1 and return to step 1.
+///
+/// Note that in the original proposal, j1 and j2 are both required
+/// to be b-tagged and a filter (with Rfilt=min(0.3,Rbb/2) and
+/// n_filt=3) is also applied to j to obtain the final "Higgs candidate".
+/// See the example \subpage Example12 for details.
+///
+/// \section desc Options
+/// 
+/// The constructor has the following arguments:
+///  - The first argument is the minimal mass drop that is required (mu_cut) [0.67
+///    by default]
+///  - The second argument is the asymmetry cut (y_cut) [0.09 by default]
+///
+/// \section input Input conditions
+/// 
+///  - one must be able to successively "uncluster" the original jet
+///    using "has_parents"
+///
+/// \section output Output/structure
+/// 
+///  - the 2 subjets are kept as pieces if some substructure is found,
+///    otherwise a single 0-momentum piece is returned
+///  - the 'mu' and 'y' values corresponding to the unclustering step
+///    that passed the tagger's cuts
+///
+/// See also \subpage Example12  for a usage example.
+class MassDropTagger : public Transformer{
+public:
+  /// default ctor
+  MassDropTagger(const double mu=0.67, const double ycut=0.09) : _mu(mu), _ycut(ycut){};
+
+  /// returns a textual description of the tagger
+  virtual std::string description() const;
+
+  /// runs the tagger on the given jet and
+  /// returns the tagged PseudoJet if successful, a PseudoJet==0 otherwise
+  /// (standard access is through operator()).
+  ///  \param jet   the PseudoJet to tag
+  virtual PseudoJet result(const PseudoJet & jet) const;
+
+  /// the type of the associated structure
+  typedef MassDropTaggerStructure StructureType;
+
+protected:
+  double _mu, _ycut;
+  static LimitedWarning _warnings_nonca;
+};
+
+
+//------------------------------------------------------------------------
+/// @ingroup tools_taggers
+/// \class MassDropTaggerStructure
+/// the structure returned by the MassDropTagger transformer.
+///
+/// See the MassDropTagger class description for the details of what
+/// is inside this structure
+///
+class MassDropTaggerStructure : public WrappedStructure{
+public:
+  /// ctor with initialisation
+  ///  \param pieces  the pieces of the created jet
+  ///  \param rec     the recombiner from the underlying cluster sequence
+  MassDropTaggerStructure(const PseudoJet & result_jet) :
+    WrappedStructure(result_jet.structure_shared_ptr()), _mu(0.0), _y(0.0){}
+
+  /// returns the mass-drop ratio, pieces[0].m()/jet.m(), for the splitting
+  /// that triggered the mass-drop condition
+  inline double mu() const{return _mu;}
+
+  /// returns the value of y = (squared kt distance) / (squared mass) for the
+  /// splitting that triggered the mass-drop condition
+  inline double y() const {return _y;}
+
+//  /// returns the original jet (before tagging)
+//  const PseudoJet & original() const {return _original_jet;}
+
+protected:
+  double _mu;              ///< the value of the mass-drop parameter
+  double _y;               ///< the value of the asymmetry parameter
+//  PseudoJet _original_jet; ///< the original jet (before tagging)
+
+  // allow the tagger to set these
+  friend class MassDropTagger;
+};
+
+
+
+FASTJET_END_NAMESPACE
+
+#endif  //  __FASTJET_MASS_DROP_TAGGER_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Pruner.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Pruner.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Pruner.cc	(revision 5)
@@ -0,0 +1,342 @@
+//STARTHEADER
+// $Id: Pruner.cc 999 2013-03-04 11:48:06Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/tools/Pruner.hh"
+#include "fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh"
+#include "fastjet/Selector.hh"
+#include <cassert>
+#include <algorithm>
+#include <sstream>
+#include <typeinfo>
+
+using namespace std;
+
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+
+//----------------------------------------------------------------------
+// class Pruner
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+// alternative (dynamic) ctor
+//  \param jet_def the jet definition for the internal clustering
+//  \param zcut_dyn    dynamic pt-fraction cut in the pruning
+//  \param Rcut_dyn    dynamic angular distance cut in the pruning
+Pruner::Pruner(const JetDefinition &jet_def, 
+         FunctionOfPseudoJet<double> *zcut_dyn,
+         FunctionOfPseudoJet<double> *Rcut_dyn)
+  : _jet_def(jet_def), _zcut(0), _Rcut_factor(0),
+    _zcut_dyn(zcut_dyn), _Rcut_dyn(Rcut_dyn), _get_recombiner_from_jet(false)  {
+  assert(_zcut_dyn != 0 && _Rcut_dyn != 0);
+}
+
+//----------------------------------------------------------------------
+// action on a single jet
+PseudoJet Pruner::result(const PseudoJet &jet) const{
+  // pruning can only be applied to jets that have constituents
+  if (!jet.has_constituents()){
+    throw Error("Pruner: trying to apply the Pruner transformer to a jet that has no constituents");
+  }
+
+  // if the jet has area support and there are explicit ghosts, we can
+  // transfer that support to the internal re-clustering
+  bool do_areas = jet.has_area() && _check_explicit_ghosts(jet);
+
+  // build the pruning plugin
+  double Rcut = (_Rcut_dyn) ? (*_Rcut_dyn)(jet) : _Rcut_factor * 2.0*jet.m()/jet.perp();
+  double zcut = (_zcut_dyn) ? (*_zcut_dyn)(jet) : _zcut;
+  PruningPlugin * pruning_plugin;
+  // for some constructors, we get the recombiner from the 
+  // input jet -- some acrobatics are needed (see plans for FJ3.1
+  // for a hopefully better solution).
+  if (_get_recombiner_from_jet) {
+    const JetDefinition::Recombiner * common_recombiner = 
+                                              _get_common_recombiner(jet);
+    if (common_recombiner) {
+      JetDefinition jet_def = _jet_def;
+      if (typeid(*common_recombiner) == typeid(JetDefinition::DefaultRecombiner)) {
+        RecombinationScheme scheme = 
+          static_cast<const JetDefinition::DefaultRecombiner *>(common_recombiner)->scheme();
+        jet_def.set_recombination_scheme(scheme);
+      } else {
+        jet_def.set_recombiner(common_recombiner);
+      }
+      pruning_plugin = new PruningPlugin(jet_def, zcut, Rcut);
+    } else {
+      // if there wasn't a common recombiner, we just use the default
+      // recombiner that was in _jet_def
+      pruning_plugin = new PruningPlugin(_jet_def, zcut, Rcut);
+    }
+  } else {
+    pruning_plugin = new PruningPlugin(_jet_def, zcut, Rcut);
+  }
+
+  // now recluster the constituents of the jet with that plugin
+  JetDefinition internal_jet_def(pruning_plugin);
+  // flag the plugin for automatic deletion _before_ we make
+  // copies (so that as long as the copies are also present
+  // it doesn't get deleted).
+  internal_jet_def.delete_plugin_when_unused();
+
+  ClusterSequence * cs;
+  if (do_areas){
+    vector<PseudoJet> particles, ghosts;
+    SelectorIsPureGhost().sift(jet.constituents(), ghosts, particles);
+    // determine the ghost area from the 1st ghost (if none, any value
+    // will do, as the area will be 0 and subtraction will have
+    // no effect!)
+    double ghost_area = (ghosts.size()) ? ghosts[0].area() : 0.01;
+    cs = new ClusterSequenceActiveAreaExplicitGhosts(particles, internal_jet_def, 
+                                                     ghosts, ghost_area);
+  } else {
+    cs = new ClusterSequence(jet.constituents(), internal_jet_def);
+  }
+  
+  PseudoJet result_local = SelectorNHardest(1)(cs->inclusive_jets())[0];
+  PrunerStructure * s = new PrunerStructure(result_local);
+  result_local.set_structure_shared_ptr(SharedPtr<PseudoJetStructureBase>(s));
+  
+  // make sure things remain persistent -- i.e. tell the jet definition
+  // and the cluster sequence that it is their responsibility to clean 
+  // up memory once the "result" reaches the end of its life in the user's
+  // code. (The CS deletes itself when the result goes out of scope and
+  // that also triggers deletion of the plugin)
+  cs->delete_self_when_unused();
+
+  return result_local;  
+}
+
+// check if the jet has explicit_ghosts (knowing that there is an
+// area support)
+bool Pruner::_check_explicit_ghosts(const PseudoJet &jet) const{
+  // if the jet comes from a Clustering check explicit ghosts in that
+  // clustering
+  if (jet.has_associated_cluster_sequence())
+    return jet.validated_csab()->has_explicit_ghosts();
+
+  // if the jet has pieces, recurse in the pieces
+  if (jet.has_pieces()){
+    vector<PseudoJet> pieces = jet.pieces();
+    for (unsigned int i=0;i<pieces.size(); i++)
+      if (!_check_explicit_ghosts(pieces[i])) return false;
+    // never returned false, so we're OK.
+    return true;
+  }
+
+  // return false for any other (unknown) structure
+  return false;
+}
+
+// see if there is a common recombiner among the pieces; if there
+// is return a pointer to it; otherwise, return NULL.
+// 
+// NB: this way of doing things is not ideal, because quite some work
+//     is needed to get a correct handling of the final recombiner
+//     (e.g. default v. non-default). In future add
+//     set_recombiner(jet_def) to JetDefinition, maybe also add
+//     an invalid_scheme to the default recombiner and then 
+//     do all the work below directly with a JetDefinition directly
+//     together with JD::has_same_recombiner(...)
+const JetDefinition::Recombiner * Pruner::_get_common_recombiner(const PseudoJet &jet) const{
+  if (jet.has_associated_cluster_sequence())
+    return jet.validated_cs()->jet_def().recombiner();
+
+  // if the jet has pieces, recurse in the pieces
+  if (jet.has_pieces()){
+    vector<PseudoJet> pieces = jet.pieces();
+    if (pieces.size() == 0) return 0;
+    const JetDefinition::Recombiner * reco = _get_common_recombiner(pieces[0]);
+    for (unsigned int i=1;i<pieces.size(); i++)
+      if (_get_common_recombiner(pieces[i]) != reco) return 0;
+    // never returned false, so we're OK.
+    return reco;
+  }
+
+  // return false for any other (unknown) structure
+  return 0;
+}
+
+
+// transformer description
+std::string Pruner::description() const{
+  ostringstream oss;
+  oss << "Pruner with jet_definition = (" << _jet_def.description() << ")";
+  if (_zcut_dyn) {
+    oss << ", dynamic zcut (" << _zcut_dyn->description() << ")"
+        << ", dynamic Rcut (" << _Rcut_dyn->description() << ")";
+  } else {
+    oss << ", zcut = " << _zcut
+        << ", Rcut_factor = " << _Rcut_factor;
+  }
+  return oss.str();
+}
+
+
+
+//----------------------------------------------------------------------
+// class PrunerStructure
+//----------------------------------------------------------------------
+
+// return the other jets that may have been found along with the
+// result of the pruning
+// The resulting vector is sorted in pt
+vector<PseudoJet> PrunerStructure::extra_jets() const{ 
+  return sorted_by_pt((!SelectorNHardest(1))(validated_cs()->inclusive_jets()));;
+}
+
+
+//----------------------------------------------------------------------
+// class PruningRecombiner
+//----------------------------------------------------------------------
+
+// decide whether to recombine things or not
+void PruningRecombiner::recombine(const PseudoJet &pa, 
+                                  const PseudoJet &pb,
+                                  PseudoJet &pab) const{
+  PseudoJet p;
+  _recombiner->recombine(pa, pb, p);
+
+  // if the 2 particles are close enough, do the recombination
+  if (pa.squared_distance(pb)<=_Rcut2){
+    pab=p; return;
+  }
+
+  double pt2a = pa.perp2();
+  double pt2b = pb.perp2();
+
+  // check which is the softest
+  if (pt2a < pt2b){
+    if (pt2a<_zcut2*p.perp2()){
+      pab = pb; _rejected.push_back(pa.cluster_hist_index());
+    } else {
+      pab = p;
+    }
+  } else {
+    if (pt2b<_zcut2*p.perp2()) {
+      pab = pa; _rejected.push_back(pb.cluster_hist_index());
+    } else {
+      pab = p;
+    }
+  }
+}
+
+// description
+string PruningRecombiner::description() const{
+  ostringstream oss;
+  oss << "Pruning recombiner with zcut = " << sqrt(_zcut2)
+      << ", Rcut = " << sqrt(_Rcut2)
+      << ", and underlying recombiner = " << _recombiner->description();
+  return oss.str();
+}
+
+
+
+
+//----------------------------------------------------------------------
+// class PruningPlugin
+//----------------------------------------------------------------------
+// the actual clustering work for the plugin
+void PruningPlugin::run_clustering(ClusterSequence &input_cs) const{
+  // declare a pruning recombiner
+  PruningRecombiner pruning_recombiner(_zcut, _Rcut, _jet_def.recombiner());
+  JetDefinition jet_def = _jet_def;
+  jet_def.set_recombiner(&pruning_recombiner);
+
+  // cluster the particles using that recombiner
+  ClusterSequence internal_cs(input_cs.jets(), jet_def);
+  const vector<ClusterSequence::history_element> & internal_hist = internal_cs.history();
+
+  // transfer the list of "childless" elements into a bool vector
+  vector<bool> kept(internal_hist.size(), true);
+  const vector<unsigned int> &pr_rej = pruning_recombiner.rejected();
+  for (unsigned int i=0;i<pr_rej.size(); i++) kept[pr_rej[i]]=false;
+
+  // browse the history, keeping only the elements that have not been
+  // vetoed.
+  //
+  // In the process we build a map for the history indices
+  vector<unsigned int> internal2input(internal_hist.size());
+  for (unsigned int i=0; i<input_cs.jets().size(); i++)
+    internal2input[i] = i;
+
+  for (unsigned int i=input_cs.jets().size(); i<internal_hist.size(); i++){
+    const ClusterSequence::history_element &he = internal_hist[i];
+
+    // deal with recombinations with the beam
+    if (he.parent2 == ClusterSequence::BeamJet){
+      int internal_jetp_index = internal_hist[he.parent1].jetp_index;
+      int internal_hist_index = internal_cs.jets()[internal_jetp_index].cluster_hist_index();
+
+      int input_jetp_index = input_cs.history()[internal2input[internal_hist_index]].jetp_index;
+
+      // cout << "Beam recomb for internal " << internal_hist_index
+      //            << " (input jet index=" << input_jetp_index << endl;
+
+      input_cs.plugin_record_iB_recombination(input_jetp_index, he.dij);
+      continue;
+    }
+
+    // now, deal with two-body recombinations
+    if (!kept[he.parent1]){ // 1 is rejected, we keep only 2
+      internal2input[i]=internal2input[he.parent2];
+      // cout << "rejecting internal " << he.parent1
+      //            << ", mapping internal " << i 
+      //            << " to internal " << he.parent2
+      //            << " i.e. " << internal2input[i] << endl;
+    } else if (!kept[he.parent2]){ // 2 is rejected, we keep only 1
+      internal2input[i]=internal2input[he.parent1];
+      // cout << "rejecting internal " << he.parent2 
+      //            << ", mapping internal " << i 
+      //            << " to internal " << he.parent1
+      //            << " i.e. " << internal2input[i] << endl;
+    } else { // do the recombination
+      int new_index;
+      input_cs.plugin_record_ij_recombination(input_cs.history()[internal2input[he.parent1]].jetp_index,
+                                              input_cs.history()[internal2input[he.parent2]].jetp_index,
+                                              he.dij, internal_cs.jets()[he.jetp_index], new_index);
+      internal2input[i]=input_cs.jets()[new_index].cluster_hist_index();
+      // cout << "merging " << internal2input[he.parent1] << " (int: " << he.parent1 << ")"
+      //      << " and "    << internal2input[he.parent2] << " (int: " << he.parent2 << ")"
+      //      << " into "   << internal2input[i] << " (int: " << i << ")" << endl;
+    }
+  }
+}
+
+// returns the plugin description
+string PruningPlugin::description() const{
+  ostringstream oss;
+  oss << "Pruning plugin with jet_definition = (" << _jet_def.description()
+      <<"), zcut = " << _zcut
+      << ", Rcut = " << _Rcut;
+  return oss.str();
+}
+
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Pruner.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Pruner.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Pruner.hh	(revision 5)
@@ -0,0 +1,302 @@
+#ifndef __FASTJET_TOOLS_PRUNER_HH__
+#define __FASTJET_TOOLS_PRUNER_HH__
+
+//STARTHEADER
+// $Id: Pruner.hh 2616 2011-09-30 18:03:40Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/WrappedStructure.hh"
+#include "fastjet/tools/Transformer.hh"
+#include <iostream>
+#include <string>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+// fwd declarations
+class Pruner;
+class PrunerStructure;
+class PruningRecombiner;
+class PruningPlugin;
+
+//----------------------------------------------------------------------
+/// @ingroup tools_generic
+/// \class Pruner
+/// Transformer that prunes a jet
+///
+/// This transformer prunes a jet according to the ideas presented in 
+/// arXiv:0903.5081 (S.D. Ellis, C.K. Vermilion and J.R. Walsh). 
+/// 
+/// The jet's constituents are reclustered with a user-specified jet
+/// definition, with the modification that objects i and j are only
+/// recombined if at least one of the following two criteria is
+/// satisfied:
+///
+///  - the geometric distance between i and j is smaller than 'Rcut'
+///    with Rcut = Rcut_factor*2m/pt (Rcut_factor is a parameter of
+///    the Pruner and m and pt obtained from the jet being pruned)
+///  - the transverse momenta of i and j are at least 'zcut' p_t(i+j)
+///
+/// If both these criteria fail, i and j are not recombined, the 
+/// harder of i and j is kept, and the softer is rejected. 
+///
+/// Usage: 
+/// \code
+///    Pruner pruner(jet_def, zcut, Rcut_factor);
+///    PseudoJet pruned_jet = pruner(jet);
+/// \endcode
+///
+/// The pruned_jet has a valid associated cluster sequence. In addition
+/// the subjets of the original jet that have been vetoed by pruning
+/// (i.e. have been 'pruned away') can be accessed using
+///
+/// \code
+///   vector<PseudoJet> rejected_subjets = pruned_jet.structure_of<Pruner>().rejected();
+/// \endcode
+///
+/// If the re-clustering happens to find more than a single inclusive
+/// jet (this should normally not happen if the radius of the jet
+/// definition used for the reclustering was set large enough),
+/// the hardest of these jets is retured as the result of the
+/// Pruner. The other jets can be accessed through
+///
+/// \code
+///   vector<PseudoJet> extra_jets = pruned_jet.structure_of<Pruner>().extra_jets();
+/// \endcode
+///
+/// Instead of using Rcut_factor and zcut, one can alternatively
+/// construct a Pruner by passing two (pointers to) functions of 
+/// PseudoJet that dynamically compute the Rcut and zcut to 
+/// be used for the jet being pruned.
+///
+/// When the jet being pruned has area support and explicit ghosts,
+/// the resulting pruned jet will likewise have area.
+///
+//----------------------------------------------------------------------
+class Pruner : public Transformer{
+public:
+  /// minimal constructor, which takes a jet algorithm, sets the radius
+  /// to JetDefinition::max_allowable_R (practically equivalent to
+  /// infinity) and also tries to use a recombiner based on the one in
+  /// the jet definition of the particular jet being pruned.
+  ///
+  ///  \param jet_alg     the jet algorithm for the internal clustering
+  ///  \param zcut        pt-fraction cut in the pruning
+  ///  \param Rcut_factor the angular distance cut in the pruning will be
+  ///                     Rcut_factor * 2m/pt
+  Pruner(const JetAlgorithm jet_alg, double zcut, double Rcut_factor) 
+    : _jet_def(jet_alg, JetDefinition::max_allowable_R),
+      _zcut(zcut), _Rcut_factor(Rcut_factor),
+      _zcut_dyn(0), _Rcut_dyn(0), _get_recombiner_from_jet(true) {}
+
+
+  /// alternative ctor in which the full reclustering jet definition can
+  /// be specified.
+  ///
+  ///  \param jet_def     the jet definition for the internal clustering
+  ///  \param zcut        pt-fraction cut in the pruning
+  ///  \param Rcut_factor the angular distance cut in the pruning will be
+  ///                     Rcut_factor * 2m/pt
+  Pruner(const JetDefinition &jet_def, double zcut, double Rcut_factor)
+    : _jet_def(jet_def),
+      _zcut(zcut), _Rcut_factor(Rcut_factor),
+      _zcut_dyn(0), _Rcut_dyn(0), _get_recombiner_from_jet(false) {}
+
+
+  /// alternative ctor in which the pt-fraction cut and angular distance
+  /// cut are functions of the jet being pruned.
+  ///
+  ///  \param jet_def the jet definition for the internal clustering
+  ///  \param zcut_dyn    dynamic pt-fraction cut in the pruning
+  ///  \param Rcut_dyn    dynamic angular distance cut in the pruning
+  Pruner(const JetDefinition &jet_def, 
+         FunctionOfPseudoJet<double> *zcut_dyn,
+         FunctionOfPseudoJet<double> *Rcut_dyn);
+
+  /// action on a single jet
+  virtual PseudoJet result(const PseudoJet &jet) const;
+
+  /// description
+  virtual std::string description() const;
+  
+  // the type of the associated structure
+  typedef PrunerStructure StructureType;
+
+private:
+  /// check if the jet has explicit_ghosts (knowing that there is an
+  /// area support)
+  bool _check_explicit_ghosts(const PseudoJet &jet) const;
+
+  /// return a pointer to a "common" recombiner if there is one,
+  /// alternatively a null pointer.
+  const JetDefinition::Recombiner * _get_common_recombiner(const PseudoJet &jet) const;
+
+  JetDefinition _jet_def; ///< the internal jet definition
+  double _zcut;        	  ///< the pt-fraction cut
+  double _Rcut_factor;    ///< the angular separation cut factor
+  FunctionOfPseudoJet<double> *_zcut_dyn; ///< dynamic zcut
+  FunctionOfPseudoJet<double> *_Rcut_dyn; ///< dynamic Rcut
+  bool   _get_recombiner_from_jet; ///< true for minimal constructor,
+                                   ///< causes recombiner to be set equal 
+                                   ///< to that already used in the jet 
+                                   ///< (if it can be deduced)
+};
+
+
+//----------------------------------------------------------------------
+/// @ingroup tools_generic
+/// \class PrunerStructure
+/// The structure associated with a PseudoJet thas has gone through a
+/// Pruner transformer
+//----------------------------------------------------------------------
+class PrunerStructure : public WrappedStructure{
+public:
+  /// default ctor
+  ///  \param result_jet  the jet for which we have to keep the structure
+  PrunerStructure(const PseudoJet & result_jet)
+    : WrappedStructure(result_jet.structure_shared_ptr()){}
+
+  /// description
+  virtual std::string description() const{ return "Pruned PseudoJet";}
+
+  /// return the constituents that have been rejected
+  std::vector<PseudoJet> rejected() const{ 
+    return validated_cs()->childless_pseudojets();
+  }
+
+  /// return the other jets that may have been found along with the
+  /// result of the pruning
+  /// The resulting vector is sorted in pt
+  std::vector<PseudoJet> extra_jets() const;
+
+protected:
+  friend class Pruner; ///< to allow setting the internal information
+};
+
+//----------------------------------------------------------------------
+/// \if internal_doc
+/// @ingroup internal
+/// \class PruningRecombiner
+/// recombines the objects that are not vetoed by pruning
+///
+/// This recombiner only recombines, using the provided 'recombiner',
+/// objects (i and j) that pass at least one of the following two criteria:
+///
+///  - the geometric distance between i and j is smaller than 'Rcut'
+///  - the transverse momenta of i and j are at least 'zcut' p_t(i+j)
+///
+/// If both these criteria fail, the hardest of i and j is kept and
+/// the softest is rejected.
+///
+/// Note that this in not meant for standalone use [in particular
+/// because it could lead to memory issues due to the rejected indices
+/// stored internally].
+///
+/// \endif
+class PruningRecombiner : public JetDefinition::Recombiner{
+public:
+  /// ctor
+  ///  \param zcut   transverse momentum fraction cut
+  ///  \param Rcut   angular separation cut
+  ///  \param recomb pointer to a recombiner to use to cluster pairs
+  PruningRecombiner(double zcut, double Rcut, 
+		    const JetDefinition::Recombiner *recombiner)
+    : _zcut2(zcut*zcut), _Rcut2(Rcut*Rcut), 
+      _recombiner(recombiner){}
+
+  /// perform a recombination taking into account the pruning
+  /// conditions
+  virtual void recombine(const PseudoJet &pa, 
+			 const PseudoJet &pb,
+			 PseudoJet &pab) const;
+
+  /// returns the description of the recombiner
+  virtual std::string description() const;
+
+  /// return the history indices that have been pruned away
+  const std::vector<unsigned int> & rejected() const{ return _rejected;}
+
+  /// clears the list of rejected indices
+  ///
+  /// If one decides to use this recombiner standalone, one has to
+  /// call this after each clustering in order for the rejected() vector
+  /// to remain sensible and not grow to infinite size.
+  void clear_rejected(){ _rejected.clear();}
+
+private:
+  double _zcut2;  ///< transverse momentum fraction cut (squared)
+  double _Rcut2;  ///< angular separation cut (squared)
+  const JetDefinition::Recombiner *_recombiner; ///< the underlying recombiner to use
+  mutable std::vector<unsigned int> _rejected;  ///< list of rejected history indices
+};
+
+
+//----------------------------------------------------------------------
+/// \if internal_doc
+/// @ingroup internal
+/// \class PruningPlugin
+/// FastJet internal plugin that clusters the particles using the
+/// PruningRecombiner. 
+///
+/// See PruningRecombiner for a description of what pruning does.
+///
+/// Note that this is an internal FastJet class used by the Pruner
+/// transformer and it is not meant to be used as a standalone clustering
+/// tool.
+///
+/// \endif
+//----------------------------------------------------------------------
+class PruningPlugin : public JetDefinition::Plugin{
+public:
+  /// ctor
+  ///  \param jet_def the jet definition to be used for the 
+  ///                 internal clustering
+  ///  \param zcut    transverse momentum fraction cut
+  ///  \param Rcut    angular separation cut
+  PruningPlugin(const JetDefinition &jet_def, double zcut, double Rcut)
+    : _jet_def(jet_def), _zcut(zcut), _Rcut(Rcut){}
+
+  /// the actual clustering work for the plugin
+  virtual void run_clustering(ClusterSequence &input_cs) const;
+
+  /// description of the plugin
+  virtual std::string description() const;
+
+  /// returns the radius
+  virtual double R() const {return _jet_def.R();}
+
+private:
+  JetDefinition _jet_def; ///< the internal jet definition
+  double _zcut;           ///< transverse momentum fraction cut 
+  double _Rcut;           ///< angular separation cut
+};
+
+
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
+
+#endif   // __FASTJET_TOOLS_PRUNER_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/RestFrameNSubjettinessTagger.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/RestFrameNSubjettinessTagger.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/RestFrameNSubjettinessTagger.cc	(revision 5)
@@ -0,0 +1,120 @@
+//STARTHEADER
+// $Id: RestFrameNSubjettinessTagger.cc 999 2013-03-04 11:48:06Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include <fastjet/tools/RestFrameNSubjettinessTagger.hh>
+#include <fastjet/tools/Boost.hh>
+#include <fastjet/ClusterSequence.hh>
+#include <sstream>
+
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+//------------------------------------------------------------------------
+// RestFrameNSubjettinessTagger class implementation
+//------------------------------------------------------------------------
+
+//------------------------------------------------------------------------
+// tagger description
+string RestFrameNSubjettinessTagger::description() const{ 
+  ostringstream oss;
+  oss << "RestFrameNSubjettiness tagger that performs clustering in the jet rest frame with " 
+      << _subjet_def.description() 
+      << ", supplemented with cuts tau_2 < " << _t2cut 
+      << " and cos(theta_s) < " << _costscut;
+  return oss.str();
+}
+
+
+//------------------------------------------------------------------------
+// action on a single jet
+// returns the tagged PseudoJet if successful, 0 otherwise
+PseudoJet RestFrameNSubjettinessTagger::result(const PseudoJet & jet) const{
+  // make sure that the jet has constituents
+  if (!jet.has_constituents())
+    throw("The jet you try to tag needs to have accessible constituents");
+   
+  // get the constituents and boost them into the rest frame of the jet
+  vector<PseudoJet> rest_input = jet.constituents();
+  for (unsigned int i=0; i<rest_input.size(); i++)
+    rest_input[i].unboost(jet);
+
+  ClusterSequence cs_rest(rest_input, _subjet_def);
+  vector<PseudoJet> subjets = (_use_exclusive)
+    ? cs_rest.exclusive_jets(2)
+    : sorted_by_E(cs_rest.inclusive_jets());
+
+  // impose the cuts in the rest-frame
+  if (subjets.size()<2) return PseudoJet();
+
+  const PseudoJet &j0 = subjets[0];
+  const PseudoJet &j1 = subjets[1];
+
+  /// impose the cut on cos(theta_s)
+  double ct0 = (j0.px()*jet.px() + j0.py()*jet.py() + j0.pz()*jet.pz())
+    /sqrt(j0.modp2()*jet.modp2());
+  double ct1 = (j1.px()*jet.px() + j1.py()*jet.py() + j1.pz()*jet.pz())
+    /sqrt(j1.modp2()*jet.modp2());
+  if ((ct0 > _costscut) || (ct1 > _costscut)) return PseudoJet();
+  
+  // ccompute the 2-subjettiness and impose the coresponding cut
+  double tau2 = 0.0;
+  for (unsigned int i=0; i<rest_input.size(); i++)
+    tau2 += min(dot_product(rest_input[i], j0), 
+                dot_product(rest_input[i], j1));
+
+  tau2 *= (2.0/jet.m2());
+
+  if (tau2 > _t2cut) return PseudoJet();
+
+  // We have a positive tag, 
+  //  - boost everything back into the lab frame
+  //  - record the info in the interface
+  // Note that in order to point to the correct Clustersequence, the
+  // subjets must be taken from the boosted one. We extract that
+  // through the history index of the rest-frame subjets
+  ClusterSequence * cs_structure = new ClusterSequence();
+  Boost boost(jet);
+  cs_structure->transfer_from_sequence(cs_rest, &boost);
+  PseudoJet subjet_lab1 = cs_structure->jets()[cs_rest.history()[subjets[0].cluster_hist_index()].jetp_index];
+  PseudoJet subjet_lab2 = cs_structure->jets()[cs_rest.history()[subjets[0].cluster_hist_index()].jetp_index];
+    
+  PseudoJet result_local = join<StructureType>(subjet_lab1,subjet_lab2);
+  StructureType * s = (StructureType *) result_local.structure_non_const_ptr();
+//  s->_original_jet = jet;
+  s->_tau2 = tau2;
+  s->_costhetas = max(ct0, ct1);
+
+  // keep the rest-frame CS alive
+  cs_structure->delete_self_when_unused();
+
+  return result_local;
+}
+
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/RestFrameNSubjettinessTagger.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/RestFrameNSubjettinessTagger.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/RestFrameNSubjettinessTagger.hh	(revision 5)
@@ -0,0 +1,162 @@
+#ifndef __FASTJET_RESTFRAMENSUBJETTINESS_TAGGER_HH__
+#define __FASTJET_RESTFRAMENSUBJETTINESS_TAGGER_HH__
+
+//STARTHEADER
+// $Id: RestFrameNSubjettinessTagger.hh 2689 2011-11-14 14:51:06Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include <fastjet/PseudoJet.hh>
+#include <fastjet/JetDefinition.hh>
+#include <fastjet/CompositeJetStructure.hh>
+#include <fastjet/tools/Transformer.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+class RestFrameNSubjettinessTagger;
+class RestFrameNSubjettinessTaggerStructure;
+
+//----------------------------------------------------------------------
+/// @ingroup tools_taggers
+/// \class RestFrameNSubjettinessTagger
+/// Class that helps perform 2-pronged boosted tagging using
+/// a reclustering in the jet's rest frame, supplemented with a cut on N-subjettiness
+/// (and a decay angle), as discussed by Ji-Hun Kim in arXiv:1011.1493.
+///
+/// To tag a fat jet, the tagger proceeds as follows:
+///
+///  - boost its constituents into the rest frame of the jet
+///
+///  - recluster them using another jet definition (the original
+///    choice was SISCone in spherical coordinates with R=0.6 and
+///    f=0.75.
+///
+///  - keep the 2 most energetic subjets (\f$q_{1,2}\f$) and compute
+///    the 2-subjettiness
+///    \f[ 
+///      \tau_2^j = \frac{2}{m_{\rm jet}^2}\,
+///                 \sum_{k\in {\rm jet}} {\rm min}(q_1.p_k,q_2.p_k)
+///    \f]
+///    where the sum runs over the constituents of the jet. 
+///
+///  - require \f$\tau_2^j < \tau_2^{\rm cut}\f$ [0.08 by default]
+///
+///  - impose that (in the rest frame of the fat jet), the angles
+///    between the 2 most energetic subjets and the boost axis are
+///    both large enough: \f$\cos(\theta_s)<c_\theta^{\rm cut}\f$ 
+///    [0.8 by default]
+///
+/// Note that in the original version, the jets to be tagged were reconstructed
+/// using SISCone with R=0.8 and f=0.75. Also, b-tagging was imposed
+/// on the 2 subjets found in the rest-frame tagging procedure.
+///
+/// \section desc Options
+/// 
+/// The constructor has the following arguments:
+///  - The first argument is the jet definition to be used to
+///    recluster the constituents of the jet to be filtered (in the
+///    rest frame of the tagged jet).
+///  - The second argument is the cut on tau_2 [0.08 by default]
+///  - The 3rd argument is the cut on cos(theta_s) [0.8 by default]
+///  - If the 4th argument is true, 2 exclusive rest-frame jets will
+///    be considered in place of the 2 most energetic inclusive jets
+///
+/// \section input Input conditions
+/// 
+///  - the original jet must have constituents
+///
+/// \section output Output/structure
+/// 
+///  - the 2 subjets are kept as pieces if some substructure is found,
+///    otherwise a single 0-momentum piece
+///  - the tau2 and maximal cos(theta_s) values computed during the
+///    tagging can be obtained via the resulting jet's structure_of<...>() 
+///    function
+///
+class RestFrameNSubjettinessTagger : public Transformer{
+public:
+  /// ctor with arguments (see the class description above)
+  RestFrameNSubjettinessTagger(const JetDefinition subjet_def, 
+                      const double tau2cut=0.08, 
+                      const double costhetascut=0.8,
+                      const bool use_exclusive = false)
+    : _subjet_def(subjet_def), _t2cut(tau2cut), _costscut(costhetascut),
+      _use_exclusive(use_exclusive){};
+
+  /// returns a textual description of the tagger 
+  virtual std::string description() const;
+
+  /// runs the tagger on the given jet and
+  /// returns the tagged PseudoJet if successful, a PseudoJet==0 otherwise
+  /// (standard access is through operator()).
+  virtual PseudoJet result(const PseudoJet & jet) const;
+
+  /// the type of Structure returned
+  typedef RestFrameNSubjettinessTaggerStructure StructureType;
+
+protected:
+  JetDefinition _subjet_def;
+  double _t2cut, _costscut;
+  bool _use_exclusive;
+};
+
+
+//------------------------------------------------------------------------
+/// @ingroup tools_taggers
+/// \class RestFrameNSubjettinessTaggerStructure
+/// the structure returned by the RestFrameNSubjettinessTagger transformer.
+///
+/// See the RestFrameNSubjettinessTagger class description for the details of
+/// what is inside this structure
+///
+class RestFrameNSubjettinessTaggerStructure : public CompositeJetStructure{
+public:
+  /// ctor with pieces initialisation
+  RestFrameNSubjettinessTaggerStructure(const std::vector<PseudoJet> & pieces_in) :
+    CompositeJetStructure(pieces_in), _tau2(0.0), _costhetas(1.0){}
+
+  /// returns the associated N-subjettiness
+  inline double tau2() const{return _tau2;}
+
+  /// returns the associated angle with the boosted axis
+  inline double costhetas() const {return _costhetas;}
+
+//  /// returns the original jet (before tagging)
+//  const PseudoJet & original() const {return _original_jet;}
+
+protected:
+  double _tau2;      ///< the value of the N-subjettiness
+  double _costhetas; ///< the minimal angle between the dijets
+                     ///< and the boost axis
+//  PseudoJet _original_jet;  ///< the original jet (before tagging)
+
+  // allow the tagger to set these
+  friend class RestFrameNSubjettinessTagger;
+};
+
+FASTJET_END_NAMESPACE
+#endif  //  __FASTJET_RESTFRAMENSUBJETTINESS_TAGGER_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Subtractor.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Subtractor.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Subtractor.cc	(revision 5)
@@ -0,0 +1,86 @@
+//STARTHEADER
+// $Id: Subtractor.cc 999 2013-03-04 11:48:06Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/tools/Subtractor.hh"
+#include <cassert>
+#include <sstream>
+#include <limits>
+using namespace std;
+
+FASTJET_BEGIN_NAMESPACE     // defined in fastjet/internal/base.hh
+
+const double Subtractor::_invalid_rho = -numeric_limits<double>::infinity();
+
+
+Subtractor::Subtractor(double rho) : _bge(0), _rho(rho) {
+  assert(_rho>0.0);
+}
+
+PseudoJet Subtractor::result(const PseudoJet & jet) const {
+  if (!jet.has_area()){
+    throw Error("Trying to subtract a jet without area support");
+  }
+  
+  double rho;
+  if (_bge != 0) {
+    rho = _bge->rho(jet);
+  } else if (_rho != _invalid_rho) {
+    rho = _rho;
+  } else {
+    throw Error("default Subtractor does not have any information about the background, which is needed to perform the subtraction");
+  }
+
+  PseudoJet subtracted_jet = jet;
+  PseudoJet area4vect = jet.area_4vector();
+  // sanity check
+  if (rho*area4vect.perp() < jet.perp() ) { 
+    // this subtraction should retain the jet's structural
+    // information
+    subtracted_jet -= rho*area4vect;
+  } else { 
+    // this sets the jet's momentum to zero while
+    // maintaining all of the jet's structural information
+    subtracted_jet *= 0;
+  }
+  return subtracted_jet;
+}
+
+//----------------------------------------------------------------------
+std::string Subtractor::description() const{
+  if (_bge != 0) {
+    return "Subtractor that uses the following background estimator to determine rho: "+_bge->description();
+  } else if (_rho != _invalid_rho) {
+    ostringstream ostr;
+    ostr << "Subtractor that uses a fixed value of rho = " << _rho;
+    return ostr.str();
+  } else {
+    return "Uninitialised subtractor";
+  }
+}
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Subtractor.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Subtractor.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Subtractor.hh	(revision 5)
@@ -0,0 +1,105 @@
+//STARTHEADER
+// $Id: Subtractor.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_TOOLS_SUBTRACTOR_HH__
+#define __FASTJET_TOOLS_SUBTRACTOR_HH__
+
+#include "fastjet/tools/Transformer.hh" // to derive Subtractor from Transformer
+#include "fastjet/tools/BackgroundEstimatorBase.hh" // used as a ctor argument
+
+FASTJET_BEGIN_NAMESPACE     // defined in fastjet/internal/base.hh
+
+
+//----------------------------------------------------------------------
+/// @ingroup tools_background
+/// \class Subtractor
+/// Class that helps perform jet background subtraction.
+///
+/// This class derives from Transformer and makes use of a pointer to
+/// a BackgroundEstimatorBase object in order to determine the background
+/// in the vicinity of a given jet and then subtract area*background from
+/// the jet. It can also be initialised with a specific fixed value for the 
+/// background pt density.
+///
+/// \section input Input conditions
+/// 
+/// The original jet must have area support (4-vector)
+///
+/// \section output Output/interface
+/// 
+/// The underlying structure of the returned, subtracted jet
+/// (i.e. constituents, pieces, etc.) is identical to that of the
+/// original jet.
+///
+class Subtractor : public Transformer{
+public:
+  /// define a subtractor based on a BackgroundEstimator
+  Subtractor(BackgroundEstimatorBase * bge) : 
+    _bge(bge), _rho(-1.0) {}
+
+  /// define a subtractor that uses a fixed value of rho, the background
+  /// pt density per unit area (which must be positive)
+  Subtractor(double rho);
+
+  /// default constructor
+  Subtractor() : _bge(0), _rho(_invalid_rho) {}
+
+  /// default dtor
+  virtual ~Subtractor(){};
+
+  /// returns a jet that's subtracted
+  ///
+  /// \param jet    the jet that is to be subtracted
+  /// \return       the subtracted jet
+  virtual PseudoJet result(const PseudoJet & jet) const;
+
+  /// class description
+  virtual std::string description() const;
+
+protected:
+
+  /// the tool used to estimate the background
+  /// if has to be mutable in case its underlying selector takes a reference jet
+  mutable BackgroundEstimatorBase * _bge;
+  /// the fixed value of rho to use if the user has selected that option
+  double _rho;
+
+  /// a value of rho that is used as a default to label that the stored
+  /// rho is not valid for subtraction. 
+  //
+  // NB: there are two reasons for not having the value written here:
+  // 1) that it caused problems on karnak with g++ 4.0.1 and 2) that
+  // we anyway like -infinity as a default, and since that's a function,
+  // that's not allowed in an include file.
+  static const double _invalid_rho;
+};
+
+FASTJET_END_NAMESPACE
+
+#endif  // __FASTJET_TOOLS_SUBTRACTOR_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/TopTaggerBase.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/TopTaggerBase.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/TopTaggerBase.cc	(revision 5)
@@ -0,0 +1,72 @@
+//STARTHEADER
+// $Id: TopTaggerBase.cc 999 2013-03-04 11:48:06Z pavel $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include <fastjet/tools/TopTaggerBase.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+using namespace std;
+
+// compute the W helicity angle
+//
+// The helicity angle is a standard observable in top decays, used to
+// determine the Lorentz structure of the top- W coupling [13]. It is
+// defined as the angle, measured in the rest frame of the
+// reconstructed W, between the reconstructed top's flight direction
+// and one of the W decay products. Normally, it is studied in
+// semi-leptonic top decays, where the charge of the lepton uniquely
+// identifies these decay products. In hadronic top decays there is an
+// ambiguity which we resolve by choosing the lower pT subjet, as
+// measured in the lab frame.
+//
+// The jet passed to this function is expected to already have
+// the structure of a top, including a functional "W()" call;
+// the W must be made of two pieces.
+double TopTaggerBase::_cos_theta_W(const PseudoJet & res) const{
+  // the two jets of interest: top and lower-pt prong of W
+  const PseudoJet & W  = res.structure_of<TopTaggerBase>().W();
+  vector<PseudoJet> W_pieces = W.pieces();
+  assert(W_pieces.size() == 2);
+  //assert(W_pieces[0].perp2() >= W_pieces[1].perp2());
+  //PseudoJet W2  = W_pieces[1];
+  // extract the softer of the two W pieces.
+  PseudoJet W2 =  (W_pieces[0].perp2() < W_pieces[1].perp2())
+                    ? W_pieces[0] 
+                    : W_pieces[1];
+  PseudoJet top = res;
+  
+  // transform these jets into jets in the rest frame of the W
+  W2.unboost(W);
+  top.unboost(W);
+
+  return (W2.px()*top.px() + W2.py()*top.py() + W2.pz()*top.pz())/
+    sqrt(W2.modp2() * top.modp2());
+}
+
+
+FASTJET_END_NAMESPACE
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/TopTaggerBase.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/TopTaggerBase.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/TopTaggerBase.hh	(revision 5)
@@ -0,0 +1,105 @@
+#ifndef __FASTJET_TOP_TAGGER_BASE_HH__
+#define __FASTJET_TOP_TAGGER_BASE_HH__
+
+//STARTHEADER
+// $Id: TopTaggerBase.hh 2689 2011-11-14 14:51:06Z soyez $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include <fastjet/internal/base.hh>
+#include <fastjet/tools/Transformer.hh>
+
+FASTJET_BEGIN_NAMESPACE
+
+class TopTaggerBase;
+class TopTaggerBaseStructure;
+
+//----------------------------------------------------------------------
+/// @ingroup tools_taggers
+/// \class TopTaggerBase
+/// A base class that provides a common interface for top taggers
+/// that are able to return a W (in addition to the top itself).
+///
+/// Top taggers that derive from this should satisfy the following 
+/// criteria:
+///
+/// - their underlying structure should derive from TopTaggerBaseStructure
+/// - tagged tops should have two pieces, the first of which is the W candidate
+/// - they should apply the top and W selectors to decide if the top has been
+///   tagged
+class TopTaggerBase : public Transformer {
+public:
+  TopTaggerBase() : _top_selector(SelectorIdentity()),
+                    _W_selector(SelectorIdentity()),
+                    _top_selector_set(false),
+                    _W_selector_set(false)              {}
+
+  /// the type of the associated structure
+  typedef TopTaggerBaseStructure StructureType;
+
+  /// sets the selector that is applied to the top candidate
+  void set_top_selector(const Selector & sel) {_top_selector = sel; _top_selector_set = true;}
+  /// sets  the selector that is applied to the W candidate
+  void set_W_selector  (const Selector & sel) {_W_selector   = sel; _W_selector_set = true;}
+  
+  /// returns a description of the top and W selectors
+  virtual std::string description_of_selectors() const {
+    std::string descr;
+    if (_top_selector_set) descr = ", top selector: "+_top_selector.description();
+    if (_W_selector_set) descr += ", W selector: "+_W_selector.description();
+    return descr;
+  }
+
+protected:
+  /// computes the W helicity angle
+  double _cos_theta_W(const PseudoJet & result) const;
+
+  Selector _top_selector, _W_selector;
+  bool _top_selector_set, _W_selector_set;
+};
+
+
+//----------------------------------------------------------------------
+/// @ingroup tools_taggers
+/// \class TopTaggerBaseStructure
+/// class that specifies the structure common to all top taggers
+///
+/// Note that this specifies only the W, non_W part of the
+/// interface. An actual top tagger structure class will also need to
+/// derive from a PseudoJetStructureBase type class
+/// (e.g. CompositeJetStructure)
+class TopTaggerBaseStructure {
+public:
+  virtual const PseudoJet & W() const = 0;
+  virtual const PseudoJet & non_W() const = 0;
+  virtual ~TopTaggerBaseStructure() {}
+};
+
+
+FASTJET_END_NAMESPACE
+
+#endif  //  __FASTJET_TOP_TAGGER_BASE_HH__
+
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Transformer.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Transformer.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/tools/Transformer.hh	(revision 5)
@@ -0,0 +1,96 @@
+//STARTHEADER
+// $Id: Transformer.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_TRANSFORMER_HH__
+#define __FASTJET_TRANSFORMER_HH__
+
+#include <fastjet/PseudoJet.hh>
+#include <fastjet/FunctionOfPseudoJet.hh>
+#include <fastjet/PseudoJetStructureBase.hh>
+
+FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
+
+// forward declarations of what we will have down here
+class Transformer;
+
+/// @ingroup tools_generic
+/// \class Transformer
+///
+/// Base (abstract) class for a jet transformer.
+///
+/// A transformer, when it acts on a jet, returns a modified version
+/// of that jet, one that may have a different momentum and/or
+/// different internal structure.
+///
+/// The typical usage of a class derived from Transformer is
+/// \code
+///   SomeTransformer transformer(...);
+///   PseudoJet transformed_jet = transformer(original_jet);
+///   // or
+///   vector<PseudoJet> transformed_jets = transformer(original_jets);
+/// \endcode
+///
+/// For many transformers, the transformed jets have
+/// transformer-specific information that can be accessed through the
+///
+/// \code
+///   transformed_jet.structure_of<SomeTransformer>().transformer_specific_info();
+/// \endcode
+///
+/// See the description of the Filter class for a more detailed usage
+/// example. See the FastJet manual to find out how to implement
+/// new transformers.
+///
+class Transformer : public FunctionOfPseudoJet<PseudoJet>{
+public:
+  /// default ctor
+  Transformer(){}
+
+  /// default dtor
+  virtual ~Transformer(){}
+
+  /// the result of the Transformer acting on the PseudoJet.
+  /// this _has_ to be overloaded in derived classes
+  /// \param original   the PseudoJet input to the Transformer
+  virtual PseudoJet result(const PseudoJet & original) const = 0;
+
+  /// This should be overloaded to return a description of the
+  /// Transformer
+  virtual std::string description() const = 0;
+
+  /// A typedef that is needed to ensure that the
+  /// PseudoJet::structure_of() template function works
+  //
+  // Make sure you reimplement this appropriately in any
+  // derived classes
+  typedef PseudoJetStructureBase StructureType;
+};
+
+FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
+
+#endif // __FASTJET_TRANSFORMER_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/fastjet/version.hh
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/fastjet/version.hh	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/fastjet/version.hh	(revision 5)
@@ -0,0 +1,41 @@
+//STARTHEADER
+// $Id: version.hh 2577 2011-09-13 15:11:38Z salam $
+//
+// Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+//  FastJet is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  The algorithms that underlie FastJet have required considerable
+//  development and are described in hep-ph/0512210. If you use
+//  FastJet as part of work towards a scientific publication, please
+//  include a citation to the FastJet paper.
+//
+//  FastJet is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_VERSION_HH__
+#define __FASTJET_VERSION_HH__
+
+#include<string>
+#include "fastjet/config.h"
+
+FASTJET_BEGIN_NAMESPACE
+
+const char* fastjet_version = FASTJET_PACKAGE_VERSION;
+
+FASTJET_END_NAMESPACE
+
+#endif // __FASTJET_VERSION_HH__
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/VERSION
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/VERSION	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/VERSION	(revision 5)
@@ -0,0 +1,1 @@
+8.0.5
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/license.terms
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/license.terms	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/license.terms	(revision 5)
@@ -0,0 +1,39 @@
+This software is copyrighted by the Regents of the University of
+California, Sun Microsystems, Inc., Scriptics Corporation,
+and other parties.  The following terms apply to all files associated
+with the software unless explicitly disclaimed in individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that this
+notice is included verbatim in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file where
+they apply.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
+IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+GOVERNMENT USE: If you are acquiring this software on behalf of the
+U.S. government, the Government shall have only "Restricted Rights"
+in the software and related documentation as defined in the Federal 
+Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
+are acquiring the software on behalf of the Department of Defense, the
+software shall be classified as "Commercial Computer Software" and the
+Government shall have only "Restricted Rights" as defined in Clause
+252.227-7013 (c) (1) of DFARs.  Notwithstanding the foregoing, the
+authors grant the U.S. Government and others acting in its behalf
+permission to use and distribute the software in accordance with the
+terms specified in this license. 
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/panic.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/panic.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/panic.c	(revision 5)
@@ -0,0 +1,101 @@
+/* 
+ * panic.c --
+ *
+ *	Source code for the "panic" library procedure for Tcl;
+ *	individual applications will probably override this with
+ *	an application-specific panic procedure.
+ *
+ * Copyright (c) 1988-1993 The Regents of the University of California.
+ * Copyright (c) 1994 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: panic.c,v 1.1 2008-06-04 13:58:02 demin Exp $
+ */
+
+#include <stdio.h>
+#ifdef NO_STDLIB_H
+#   include "../compat/stdlib.h"
+#else
+#   include <stdlib.h>
+#endif
+
+#define panic panicDummy
+#include "tcl.h"
+#undef panic
+
+# undef TCL_STORAGE_CLASS
+# define TCL_STORAGE_CLASS DLLEXPORT
+
+EXTERN void		panic _ANSI_ARGS_((char *format, char *arg1,
+			    char *arg2, char *arg3, char *arg4, char *arg5,
+			    char *arg6, char *arg7, char *arg8));
+
+/*
+ * The panicProc variable contains a pointer to an application
+ * specific panic procedure.
+ */
+
+void (*panicProc) _ANSI_ARGS_(TCL_VARARGS(char *,format)) = NULL;
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetPanicProc --
+ *
+ *	Replace the default panic behavior with the specified functiion.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Sets the panicProc variable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetPanicProc(proc)
+    void (*proc) _ANSI_ARGS_(TCL_VARARGS(char *,format));
+{
+    panicProc = proc;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * panic --
+ *
+ *	Print an error message and kill the process.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The process dies, entering the debugger if possible.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* VARARGS ARGSUSED */
+void
+panic(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
+    char *format;		/* Format string, suitable for passing to
+				 * fprintf. */
+    char *arg1, *arg2, *arg3;	/* Additional arguments (variable in number)
+				 * to pass to fprintf. */
+    char *arg4, *arg5, *arg6, *arg7, *arg8;
+{
+    if (panicProc != NULL) {
+	(void) (*panicProc)(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+    } else {
+	(void) fprintf(stderr, format, arg1, arg2, arg3, arg4, arg5, arg6,
+		arg7, arg8);
+	(void) fprintf(stderr, "\n");
+	(void) fflush(stderr);
+	abort();
+    }
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tcl.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tcl.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tcl.h	(revision 5)
@@ -0,0 +1,1564 @@
+/*
+ * tcl.h --
+ *
+ *	This header file describes the externally-visible facilities
+ *	of the Tcl interpreter.
+ *
+ * Copyright (c) 1987-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1993-1996 Lucent Technologies.
+ * Copyright (c) 1998-1999 Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tcl.h,v 1.1 2008-06-04 13:58:02 demin Exp $
+ */
+
+#ifndef _TCL
+#define _TCL
+
+/*
+ * When version numbers change here, must also go into the following files
+ * and update the version numbers:
+ *
+ * README
+ * library/init.tcl	(only if major.minor changes, not patchlevel)
+ * unix/configure.in
+ * win/makefile.bc	(only if major.minor changes, not patchlevel)
+ * win/makefile.vc	(only if major.minor changes, not patchlevel)
+ * win/README
+ * win/README.binary
+ * mac/README
+ *
+ * The release level should be  0 for alpha, 1 for beta, and 2 for
+ * final/patch.  The release serial value is the number that follows the
+ * "a", "b", or "p" in the patch level; for example, if the patch level
+ * is 7.6b2, TCL_RELEASE_SERIAL is 2.  It restarts at 1 whenever the
+ * release level is changed, except for the final release which is 0
+ * (the first patch will start at 1).
+ */
+
+#define TCL_MAJOR_VERSION   8
+#define TCL_MINOR_VERSION   0
+#define TCL_RELEASE_LEVEL   2
+#define TCL_RELEASE_SERIAL  5
+
+#define TCL_VERSION	    "8.0"
+#define TCL_PATCH_LEVEL	    "8.0.5"
+
+/*
+ * The following definitions set up the proper options for Windows
+ * compilers.  We use this method because there is no autoconf equivalent.
+ */
+
+#ifndef __WIN32__
+#   if defined(_WIN32) || defined(WIN32)
+#	define __WIN32__
+#   endif
+#endif
+
+#ifdef __WIN32__
+#   ifndef STRICT
+#	define STRICT
+#   endif
+#   ifndef USE_PROTOTYPE
+#	define USE_PROTOTYPE 1
+#   endif
+#   ifndef HAS_STDARG
+#	define HAS_STDARG 1
+#   endif
+#   ifndef USE_PROTOTYPE
+#	define USE_PROTOTYPE 1
+#   endif
+
+/*
+ * Under Windows we need to call Tcl_Alloc in all cases to avoid competing
+ * C run-time library issues.
+ */
+
+#   ifndef USE_TCLALLOC
+#	define USE_TCLALLOC 1
+#   endif
+#endif /* __WIN32__ */
+
+/*
+ * The following definitions set up the proper options for Macintosh
+ * compilers.  We use this method because there is no autoconf equivalent.
+ */
+
+#ifdef MAC_TCL
+#   ifndef HAS_STDARG
+#	define HAS_STDARG 1
+#   endif
+#   ifndef USE_TCLALLOC
+#	define USE_TCLALLOC 1
+#   endif
+#   ifndef NO_STRERROR
+#	define NO_STRERROR 1
+#   endif
+#endif
+
+/*
+ * Utility macros: STRINGIFY takes an argument and wraps it in "" (double
+ * quotation marks), JOIN joins two arguments.
+ */
+
+#define VERBATIM(x) x
+#ifdef _MSC_VER
+# define STRINGIFY(x) STRINGIFY1(x)
+# define STRINGIFY1(x) #x
+# define JOIN(a,b) JOIN1(a,b)
+# define JOIN1(a,b) a##b
+#else
+# ifdef RESOURCE_INCLUDED
+#  define STRINGIFY(x) STRINGIFY1(x)
+#  define STRINGIFY1(x) #x
+#  define JOIN(a,b) JOIN1(a,b)
+#  define JOIN1(a,b) a##b
+# else
+#  ifdef __STDC__
+#   define STRINGIFY(x) #x
+#   define JOIN(a,b) a##b
+#  else
+#   define STRINGIFY(x) "x"
+#   define JOIN(a,b) VERBATIM(a)VERBATIM(b)
+#  endif
+# endif
+#endif
+
+/* 
+ * A special definition used to allow this header file to be included 
+ * in resource files so that they can get obtain version information from
+ * this file.  Resource compilers don't like all the C stuff, like typedefs
+ * and procedure declarations, that occur below.
+ */
+
+#ifndef RESOURCE_INCLUDED
+
+#ifndef BUFSIZ
+#include <stdio.h>
+#endif
+
+/*
+ * Definitions that allow Tcl functions with variable numbers of
+ * arguments to be used with either varargs.h or stdarg.h.  TCL_VARARGS
+ * is used in procedure prototypes.  TCL_VARARGS_DEF is used to declare
+ * the arguments in a function definiton: it takes the type and name of
+ * the first argument and supplies the appropriate argument declaration
+ * string for use in the function definition.  TCL_VARARGS_START
+ * initializes the va_list data structure and returns the first argument.
+ */
+
+#if defined(__STDC__) || defined(HAS_STDARG)
+#   define TCL_VARARGS(type, name) (type name, ...)
+#   define TCL_VARARGS_DEF(type, name) (type name, ...)
+#   define TCL_VARARGS_START(type, name, list) (va_start(list, name), name)
+#else
+#   ifdef __cplusplus
+#	define TCL_VARARGS(type, name) (type name, ...)
+#	define TCL_VARARGS_DEF(type, name) (type va_alist, ...)
+#   else
+#	define TCL_VARARGS(type, name) ()
+#	define TCL_VARARGS_DEF(type, name) (va_alist)
+#   endif
+#   define TCL_VARARGS_START(type, name, list) \
+	(va_start(list), va_arg(list, type))
+#endif
+
+/*
+ * Macros used to declare a function to be exported by a DLL.
+ * Used by Windows, maps to no-op declarations on non-Windows systems.
+ * The default build on windows is for a DLL, which causes the DLLIMPORT
+ * and DLLEXPORT macros to be nonempty. To build a static library, the
+ * macro STATIC_BUILD should be defined.
+ * The support follows the convention that a macro called BUILD_xxxx, where
+ * xxxx is the name of a library we are building, is set on the compile line
+ * for sources that are to be placed in the library. See BUILD_tcl in this
+ * file for an example of how the macro is to be used.
+ */
+
+#ifdef __WIN32__
+# ifdef STATIC_BUILD
+#  define DLLIMPORT
+#  define DLLEXPORT
+# else
+#  if defined(_MSC_VER) || (defined(__GNUC__) && defined(__declspec))
+#   define DLLIMPORT __declspec(dllimport)
+#   define DLLEXPORT __declspec(dllexport)
+#  else
+#   define DLLIMPORT
+#   define DLLEXPORT
+#  endif
+# endif
+#else
+# define DLLIMPORT
+# define DLLEXPORT
+#endif
+
+#ifdef TCL_STORAGE_CLASS
+# undef TCL_STORAGE_CLASS
+#endif
+#ifdef BUILD_tcl
+# define TCL_STORAGE_CLASS DLLEXPORT
+#else
+# define TCL_STORAGE_CLASS DLLIMPORT
+#endif
+
+/*
+ * Definitions that allow this header file to be used either with or
+ * without ANSI C features like function prototypes.
+ */
+
+#undef _ANSI_ARGS_
+#undef CONST
+
+#if ((defined(__STDC__) || defined(SABER)) && !defined(NO_PROTOTYPE)) || defined(__cplusplus) || defined(USE_PROTOTYPE)
+#   define _USING_PROTOTYPES_ 1
+#   define _ANSI_ARGS_(x)	x
+#   define CONST const
+#else
+#   define _ANSI_ARGS_(x)	()
+#   define CONST
+#endif
+
+#ifdef __cplusplus
+#   define EXTERN extern "C" TCL_STORAGE_CLASS
+#else
+#   define EXTERN extern TCL_STORAGE_CLASS
+#endif
+
+/*
+ * Macro to use instead of "void" for arguments that must have
+ * type "void *" in ANSI C;  maps them to type "char *" in
+ * non-ANSI systems.
+ */
+#ifndef __WIN32__
+#ifndef VOID
+#   ifdef __STDC__
+#       define VOID void
+#   else
+#       define VOID char
+#   endif
+#endif
+#else /* __WIN32__ */
+/*
+ * The following code is copied from winnt.h
+ */
+#ifndef VOID
+#define VOID void
+typedef char CHAR;
+typedef short SHORT;
+typedef long LONG;
+#endif
+#endif /* __WIN32__ */
+
+/*
+ * Miscellaneous declarations.
+ */
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef _CLIENTDATA
+#   if defined(__STDC__) || defined(__cplusplus)
+    typedef void *ClientData;
+#   else
+    typedef int *ClientData;
+#   endif /* __STDC__ */
+#define _CLIENTDATA
+#endif
+
+/*
+ * Data structures defined opaquely in this module. The definitions below
+ * just provide dummy types. A few fields are made visible in Tcl_Interp
+ * structures, namely those used for returning a string result from
+ * commands. Direct access to the result field is discouraged in Tcl 8.0.
+ * The interpreter result is either an object or a string, and the two
+ * values are kept consistent unless some C code sets interp->result
+ * directly. Programmers should use either the procedure Tcl_GetObjResult()
+ * or Tcl_GetStringResult() to read the interpreter's result. See the
+ * SetResult man page for details.
+ * 
+ * Note: any change to the Tcl_Interp definition below must be mirrored
+ * in the "real" definition in tclInt.h.
+ *
+ * Note: Tcl_ObjCmdProc procedures do not directly set result and freeProc.
+ * Instead, they set a Tcl_Obj member in the "real" structure that can be
+ * accessed with Tcl_GetObjResult() and Tcl_SetObjResult().
+ */
+
+typedef struct Tcl_Interp {
+    char *result;		/* If the last command returned a string
+				 * result, this points to it. */
+    void (*freeProc) _ANSI_ARGS_((char *blockPtr));
+				/* Zero means the string result is
+				 * statically allocated. TCL_DYNAMIC means
+				 * it was allocated with ckalloc and should
+				 * be freed with ckfree. Other values give
+				 * the address of procedure to invoke to
+				 * free the result. Tcl_Eval must free it
+				 * before executing next command. */
+    int errorLine;              /* When TCL_ERROR is returned, this gives
+                                 * the line number within the command where
+                                 * the error occurred (1 if first line). */
+} Tcl_Interp;
+
+typedef struct Tcl_AsyncHandler_ *Tcl_AsyncHandler;
+typedef struct Tcl_Channel_ *Tcl_Channel;
+typedef struct Tcl_Command_ *Tcl_Command;
+typedef struct Tcl_Event Tcl_Event;
+typedef struct Tcl_Pid_ *Tcl_Pid;
+typedef struct Tcl_RegExp_ *Tcl_RegExp;
+typedef struct Tcl_TimerToken_ *Tcl_TimerToken;
+typedef struct Tcl_Trace_ *Tcl_Trace;
+typedef struct Tcl_Var_ *Tcl_Var;
+
+/*
+ * When a TCL command returns, the interpreter contains a result from the
+ * command. Programmers are strongly encouraged to use one of the
+ * procedures Tcl_GetObjResult() or Tcl_GetStringResult() to read the
+ * interpreter's result. See the SetResult man page for details. Besides
+ * this result, the command procedure returns an integer code, which is 
+ * one of the following:
+ *
+ * TCL_OK		Command completed normally; the interpreter's
+ *			result contains	the command's result.
+ * TCL_ERROR		The command couldn't be completed successfully;
+ *			the interpreter's result describes what went wrong.
+ * TCL_RETURN		The command requests that the current procedure
+ *			return; the interpreter's result contains the
+ *			procedure's return value.
+ * TCL_BREAK		The command requests that the innermost loop
+ *			be exited; the interpreter's result is meaningless.
+ * TCL_CONTINUE		Go on to the next iteration of the current loop;
+ *			the interpreter's result is meaningless.
+ */
+
+#define TCL_OK		0
+#define TCL_ERROR	1
+#define TCL_RETURN	2
+#define TCL_BREAK	3
+#define TCL_CONTINUE	4
+
+#define TCL_RESULT_SIZE 200
+
+/*
+ * Argument descriptors for math function callbacks in expressions:
+ */
+
+typedef enum {TCL_INT, TCL_DOUBLE, TCL_EITHER} Tcl_ValueType;
+typedef struct Tcl_Value {
+    Tcl_ValueType type;		/* Indicates intValue or doubleValue is
+				 * valid, or both. */
+    long intValue;		/* Integer value. */
+    double doubleValue;		/* Double-precision floating value. */
+} Tcl_Value;
+
+/*
+ * Forward declaration of Tcl_Obj to prevent an error when the forward
+ * reference to Tcl_Obj is encountered in the procedure types declared 
+ * below.
+ */
+
+struct Tcl_Obj;
+
+/*
+ * Procedure types defined by Tcl:
+ */
+
+typedef int (Tcl_AppInitProc) _ANSI_ARGS_((Tcl_Interp *interp));
+typedef int (Tcl_AsyncProc) _ANSI_ARGS_((ClientData clientData,
+	Tcl_Interp *interp, int code));
+typedef void (Tcl_ChannelProc) _ANSI_ARGS_((ClientData clientData, int mask));
+typedef void (Tcl_CloseProc) _ANSI_ARGS_((ClientData data));
+typedef void (Tcl_CmdDeleteProc) _ANSI_ARGS_((ClientData clientData));
+typedef int (Tcl_CmdProc) _ANSI_ARGS_((ClientData clientData,
+	Tcl_Interp *interp, int argc, char *argv[]));
+typedef void (Tcl_CmdTraceProc) _ANSI_ARGS_((ClientData clientData,
+	Tcl_Interp *interp, int level, char *command, Tcl_CmdProc *proc,
+	ClientData cmdClientData, int argc, char *argv[]));
+typedef void (Tcl_DupInternalRepProc) _ANSI_ARGS_((struct Tcl_Obj *srcPtr, 
+        struct Tcl_Obj *dupPtr));
+typedef int (Tcl_EventProc) _ANSI_ARGS_((Tcl_Event *evPtr, int flags));
+typedef void (Tcl_EventCheckProc) _ANSI_ARGS_((ClientData clientData,
+	int flags));
+typedef int (Tcl_EventDeleteProc) _ANSI_ARGS_((Tcl_Event *evPtr,
+        ClientData clientData));
+typedef void (Tcl_EventSetupProc) _ANSI_ARGS_((ClientData clientData,
+	int flags));
+typedef void (Tcl_ExitProc) _ANSI_ARGS_((ClientData clientData));
+typedef void (Tcl_FileProc) _ANSI_ARGS_((ClientData clientData, int mask));
+typedef void (Tcl_FileFreeProc) _ANSI_ARGS_((ClientData clientData));
+typedef void (Tcl_FreeInternalRepProc) _ANSI_ARGS_((struct Tcl_Obj *objPtr));
+typedef void (Tcl_FreeProc) _ANSI_ARGS_((char *blockPtr));
+typedef void (Tcl_IdleProc) _ANSI_ARGS_((ClientData clientData));
+typedef void (Tcl_InterpDeleteProc) _ANSI_ARGS_((ClientData clientData,
+	Tcl_Interp *interp));
+typedef int (Tcl_MathProc) _ANSI_ARGS_((ClientData clientData,
+	Tcl_Interp *interp, Tcl_Value *args, Tcl_Value *resultPtr));
+typedef void (Tcl_NamespaceDeleteProc) _ANSI_ARGS_((ClientData clientData));
+typedef int (Tcl_ObjCmdProc) _ANSI_ARGS_((ClientData clientData,
+	Tcl_Interp *interp, int objc, struct Tcl_Obj * CONST objv[]));
+typedef int (Tcl_PackageInitProc) _ANSI_ARGS_((Tcl_Interp *interp));
+typedef void (Tcl_TcpAcceptProc) _ANSI_ARGS_((ClientData callbackData,
+        Tcl_Channel chan, char *address, int port));
+typedef void (Tcl_TimerProc) _ANSI_ARGS_((ClientData clientData));
+typedef int (Tcl_SetFromAnyProc) _ANSI_ARGS_((Tcl_Interp *interp,
+	struct Tcl_Obj *objPtr));
+typedef void (Tcl_UpdateStringProc) _ANSI_ARGS_((struct Tcl_Obj *objPtr));
+typedef char *(Tcl_VarTraceProc) _ANSI_ARGS_((ClientData clientData,
+	Tcl_Interp *interp, char *part1, char *part2, int flags));
+
+/*
+ * The following structure represents a type of object, which is a
+ * particular internal representation for an object plus a set of
+ * procedures that provide standard operations on objects of that type.
+ */
+
+typedef struct Tcl_ObjType {
+    char *name;			/* Name of the type, e.g. "int". */
+    Tcl_FreeInternalRepProc *freeIntRepProc;
+				/* Called to free any storage for the type's
+				 * internal rep. NULL if the internal rep
+				 * does not need freeing. */
+    Tcl_DupInternalRepProc *dupIntRepProc;
+    				/* Called to create a new object as a copy
+				 * of an existing object. */
+    Tcl_UpdateStringProc *updateStringProc;
+    				/* Called to update the string rep from the
+				 * type's internal representation. */
+    Tcl_SetFromAnyProc *setFromAnyProc;
+    				/* Called to convert the object's internal
+				 * rep to this type. Frees the internal rep
+				 * of the old type. Returns TCL_ERROR on
+				 * failure. */
+} Tcl_ObjType;
+
+/*
+ * One of the following structures exists for each object in the Tcl
+ * system. An object stores a value as either a string, some internal
+ * representation, or both.
+ */
+
+typedef struct Tcl_Obj {
+    int refCount;		/* When 0 the object will be freed. */
+    char *bytes;		/* This points to the first byte of the
+				 * object's string representation. The array
+				 * must be followed by a null byte (i.e., at
+				 * offset length) but may also contain
+				 * embedded null characters. The array's
+				 * storage is allocated by ckalloc. NULL
+				 * means the string rep is invalid and must
+				 * be regenerated from the internal rep.
+				 * Clients should use Tcl_GetStringFromObj
+				 * to get a pointer to the byte array as a
+				 * readonly value. */
+    int length;			/* The number of bytes at *bytes, not
+				 * including the terminating null. */
+    Tcl_ObjType *typePtr;	/* Denotes the object's type. Always
+				 * corresponds to the type of the object's
+				 * internal rep. NULL indicates the object
+				 * has no internal rep (has no type). */
+    union {			/* The internal representation: */
+	long longValue;		/*   - an long integer value */
+	double doubleValue;	/*   - a double-precision floating value */
+	VOID *otherValuePtr;	/*   - another, type-specific value */
+	struct {		/*   - internal rep as two pointers */
+	    VOID *ptr1;
+	    VOID *ptr2;
+	} twoPtrValue;
+    } internalRep;
+} Tcl_Obj;
+
+/*
+ * Macros to increment and decrement a Tcl_Obj's reference count, and to
+ * test whether an object is shared (i.e. has reference count > 1).
+ * Note: clients should use Tcl_DecrRefCount() when they are finished using
+ * an object, and should never call TclFreeObj() directly. TclFreeObj() is
+ * only defined and made public in tcl.h to support Tcl_DecrRefCount's macro
+ * definition. Note also that Tcl_DecrRefCount() refers to the parameter
+ * "obj" twice. This means that you should avoid calling it with an
+ * expression that is expensive to compute or has side effects.
+ */
+
+EXTERN void		Tcl_IncrRefCount _ANSI_ARGS_((Tcl_Obj *objPtr));
+EXTERN void		Tcl_DecrRefCount _ANSI_ARGS_((Tcl_Obj *objPtr));
+EXTERN int		Tcl_IsShared _ANSI_ARGS_((Tcl_Obj *objPtr));
+
+#ifdef TCL_MEM_DEBUG
+#   define Tcl_IncrRefCount(objPtr) \
+	Tcl_DbIncrRefCount(objPtr, __FILE__, __LINE__)
+#   define Tcl_DecrRefCount(objPtr) \
+	Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__)
+#   define Tcl_IsShared(objPtr) \
+	Tcl_DbIsShared(objPtr, __FILE__, __LINE__)
+#else
+#   define Tcl_IncrRefCount(objPtr) \
+	++(objPtr)->refCount
+#   define Tcl_DecrRefCount(objPtr) \
+	if (--(objPtr)->refCount <= 0) TclFreeObj(objPtr)
+#   define Tcl_IsShared(objPtr) \
+	((objPtr)->refCount > 1)
+#endif
+
+/*
+ * Macros and definitions that help to debug the use of Tcl objects.
+ * When TCL_MEM_DEBUG is defined, the Tcl_New* declarations are 
+ * overridden to call debugging versions of the object creation procedures.
+ */
+
+EXTERN Tcl_Obj *	Tcl_NewBooleanObj _ANSI_ARGS_((int boolValue));
+EXTERN Tcl_Obj *	Tcl_NewDoubleObj _ANSI_ARGS_((double doubleValue));
+EXTERN Tcl_Obj *	Tcl_NewIntObj _ANSI_ARGS_((int intValue));
+EXTERN Tcl_Obj *	Tcl_NewListObj _ANSI_ARGS_((int objc,
+			    Tcl_Obj *CONST objv[]));
+EXTERN Tcl_Obj *	Tcl_NewLongObj _ANSI_ARGS_((long longValue));
+EXTERN Tcl_Obj *	Tcl_NewObj _ANSI_ARGS_((void));
+EXTERN Tcl_Obj *	Tcl_NewStringObj _ANSI_ARGS_((char *bytes,
+			    int length));
+
+#ifdef TCL_MEM_DEBUG
+#  define Tcl_NewBooleanObj(val) \
+     Tcl_DbNewBooleanObj(val, __FILE__, __LINE__)
+#  define Tcl_NewDoubleObj(val) \
+     Tcl_DbNewDoubleObj(val, __FILE__, __LINE__)
+#  define Tcl_NewIntObj(val) \
+     Tcl_DbNewLongObj(val, __FILE__, __LINE__)
+#  define Tcl_NewListObj(objc, objv) \
+     Tcl_DbNewListObj(objc, objv, __FILE__, __LINE__)
+#  define Tcl_NewLongObj(val) \
+     Tcl_DbNewLongObj(val, __FILE__, __LINE__)
+#  define Tcl_NewObj() \
+     Tcl_DbNewObj(__FILE__, __LINE__)
+#  define Tcl_NewStringObj(bytes, len) \
+     Tcl_DbNewStringObj(bytes, len, __FILE__, __LINE__)
+#endif /* TCL_MEM_DEBUG */
+
+/*
+ * The following definitions support Tcl's namespace facility.
+ * Note: the first five fields must match exactly the fields in a
+ * Namespace structure (see tcl.h). 
+ */
+
+typedef struct Tcl_Namespace {
+    char *name;                 /* The namespace's name within its parent
+				 * namespace. This contains no ::'s. The
+				 * name of the global namespace is ""
+				 * although "::" is an synonym. */
+    char *fullName;             /* The namespace's fully qualified name.
+				 * This starts with ::. */
+    ClientData clientData;      /* Arbitrary value associated with this
+				 * namespace. */
+    Tcl_NamespaceDeleteProc* deleteProc;
+                                /* Procedure invoked when deleting the
+				 * namespace to, e.g., free clientData. */
+    struct Tcl_Namespace* parentPtr;
+                                /* Points to the namespace that contains
+				 * this one. NULL if this is the global
+				 * namespace. */
+} Tcl_Namespace;
+
+/*
+ * The following structure represents a call frame, or activation record.
+ * A call frame defines a naming context for a procedure call: its local
+ * scope (for local variables) and its namespace scope (used for non-local
+ * variables; often the global :: namespace). A call frame can also define
+ * the naming context for a namespace eval or namespace inscope command:
+ * the namespace in which the command's code should execute. The
+ * Tcl_CallFrame structures exist only while procedures or namespace
+ * eval/inscope's are being executed, and provide a Tcl call stack.
+ * 
+ * A call frame is initialized and pushed using Tcl_PushCallFrame and
+ * popped using Tcl_PopCallFrame. Storage for a Tcl_CallFrame must be
+ * provided by the Tcl_PushCallFrame caller, and callers typically allocate
+ * them on the C call stack for efficiency. For this reason, Tcl_CallFrame
+ * is defined as a structure and not as an opaque token. However, most
+ * Tcl_CallFrame fields are hidden since applications should not access
+ * them directly; others are declared as "dummyX".
+ *
+ * WARNING!! The structure definition must be kept consistent with the
+ * CallFrame structure in tclInt.h. If you change one, change the other.
+ */
+
+typedef struct Tcl_CallFrame {
+    Tcl_Namespace *nsPtr;
+    int dummy1;
+    int dummy2;
+    char *dummy3;
+    char *dummy4;
+    char *dummy5;
+    int dummy6;
+    char *dummy7;
+    char *dummy8;
+    int dummy9;
+    char* dummy10;
+} Tcl_CallFrame;
+
+/*
+ * Information about commands that is returned by Tcl_GetCommandInfo and
+ * passed to Tcl_SetCommandInfo. objProc is an objc/objv object-based
+ * command procedure while proc is a traditional Tcl argc/argv
+ * string-based procedure. Tcl_CreateObjCommand and Tcl_CreateCommand
+ * ensure that both objProc and proc are non-NULL and can be called to
+ * execute the command. However, it may be faster to call one instead of
+ * the other. The member isNativeObjectProc is set to 1 if an
+ * object-based procedure was registered by Tcl_CreateObjCommand, and to
+ * 0 if a string-based procedure was registered by Tcl_CreateCommand.
+ * The other procedure is typically set to a compatibility wrapper that
+ * does string-to-object or object-to-string argument conversions then
+ * calls the other procedure.
+ */
+     
+typedef struct Tcl_CmdInfo {
+    int isNativeObjectProc;	 /* 1 if objProc was registered by a call to
+				  * Tcl_CreateObjCommand; 0 otherwise.
+				  * Tcl_SetCmdInfo does not modify this
+				  * field. */
+    Tcl_ObjCmdProc *objProc;	 /* Command's object-based procedure. */
+    ClientData objClientData;	 /* ClientData for object proc. */
+    Tcl_CmdProc *proc;		 /* Command's string-based procedure. */
+    ClientData clientData;	 /* ClientData for string proc. */
+    Tcl_CmdDeleteProc *deleteProc;
+                                 /* Procedure to call when command is
+                                  * deleted. */
+    ClientData deleteData;	 /* Value to pass to deleteProc (usually
+				  * the same as clientData). */
+    Tcl_Namespace *namespacePtr; /* Points to the namespace that contains
+				  * this command. Note that Tcl_SetCmdInfo
+				  * will not change a command's namespace;
+				  * use Tcl_RenameCommand to do that. */
+
+} Tcl_CmdInfo;
+
+/*
+ * The structure defined below is used to hold dynamic strings.  The only
+ * field that clients should use is the string field, and they should
+ * never modify it.
+ */
+
+#define TCL_DSTRING_STATIC_SIZE 200
+typedef struct Tcl_DString {
+    char *string;		/* Points to beginning of string:  either
+				 * staticSpace below or a malloced array. */
+    int length;			/* Number of non-NULL characters in the
+				 * string. */
+    int spaceAvl;		/* Total number of bytes available for the
+				 * string and its terminating NULL char. */
+    char staticSpace[TCL_DSTRING_STATIC_SIZE];
+				/* Space to use in common case where string
+				 * is small. */
+} Tcl_DString;
+
+#define Tcl_DStringLength(dsPtr) ((dsPtr)->length)
+#define Tcl_DStringValue(dsPtr) ((dsPtr)->string)
+#define Tcl_DStringTrunc Tcl_DStringSetLength
+
+/*
+ * Definitions for the maximum number of digits of precision that may
+ * be specified in the "tcl_precision" variable, and the number of
+ * characters of buffer space required by Tcl_PrintDouble.
+ */
+ 
+#define TCL_MAX_PREC 17
+#define TCL_DOUBLE_SPACE (TCL_MAX_PREC+10)
+
+/*
+ * Flag that may be passed to Tcl_ConvertElement to force it not to
+ * output braces (careful!  if you change this flag be sure to change
+ * the definitions at the front of tclUtil.c).
+ */
+
+#define TCL_DONT_USE_BRACES	1
+
+/*
+ * Flag that may be passed to Tcl_GetIndexFromObj to force it to disallow
+ * abbreviated strings.
+ */
+
+#define TCL_EXACT	1
+
+/*
+ * Flag values passed to Tcl_RecordAndEval.
+ * WARNING: these bit choices must not conflict with the bit choices
+ * for evalFlag bits in tclInt.h!!
+ */
+
+#define TCL_NO_EVAL		0x10000
+#define TCL_EVAL_GLOBAL		0x20000
+
+/*
+ * Special freeProc values that may be passed to Tcl_SetResult (see
+ * the man page for details):
+ */
+
+#define TCL_VOLATILE	((Tcl_FreeProc *) 1)
+#define TCL_STATIC	((Tcl_FreeProc *) 0)
+#define TCL_DYNAMIC	((Tcl_FreeProc *) 3)
+
+/*
+ * Flag values passed to variable-related procedures.
+ */
+
+#define TCL_GLOBAL_ONLY		 1
+#define TCL_NAMESPACE_ONLY	 2
+#define TCL_APPEND_VALUE	 4
+#define TCL_LIST_ELEMENT	 8
+#define TCL_TRACE_READS		 0x10
+#define TCL_TRACE_WRITES	 0x20
+#define TCL_TRACE_UNSETS	 0x40
+#define TCL_TRACE_DESTROYED	 0x80
+#define TCL_INTERP_DESTROYED	 0x100
+#define TCL_LEAVE_ERR_MSG	 0x200
+#define TCL_PARSE_PART1		 0x400
+
+/*
+ * Types for linked variables:
+ */
+
+#define TCL_LINK_INT		1
+#define TCL_LINK_DOUBLE		2
+#define TCL_LINK_BOOLEAN	3
+#define TCL_LINK_STRING		4
+#define TCL_LINK_READ_ONLY	0x80
+
+/*
+ * The following declarations either map ckalloc and ckfree to
+ * malloc and free, or they map them to procedures with all sorts
+ * of debugging hooks defined in tclCkalloc.c.
+ */
+
+EXTERN char *		Tcl_Alloc _ANSI_ARGS_((unsigned int size));
+EXTERN void		Tcl_Free _ANSI_ARGS_((char *ptr));
+EXTERN char *		Tcl_Realloc _ANSI_ARGS_((char *ptr,
+			    unsigned int size));
+
+#ifdef TCL_MEM_DEBUG
+
+#  define Tcl_Alloc(x) Tcl_DbCkalloc(x, __FILE__, __LINE__)
+#  define Tcl_Free(x)  Tcl_DbCkfree(x, __FILE__, __LINE__)
+#  define Tcl_Realloc(x,y) Tcl_DbCkrealloc((x), (y),__FILE__, __LINE__)
+#  define ckalloc(x) Tcl_DbCkalloc(x, __FILE__, __LINE__)
+#  define ckfree(x)  Tcl_DbCkfree(x, __FILE__, __LINE__)
+#  define ckrealloc(x,y) Tcl_DbCkrealloc((x), (y),__FILE__, __LINE__)
+
+EXTERN int		Tcl_DumpActiveMemory _ANSI_ARGS_((char *fileName));
+EXTERN void		Tcl_ValidateAllMemory _ANSI_ARGS_((char *file,
+			    int line));
+
+#else
+
+/*
+ * If USE_TCLALLOC is true, then we need to call Tcl_Alloc instead of
+ * the native malloc/free.  The only time USE_TCLALLOC should not be
+ * true is when compiling the Tcl/Tk libraries on Unix systems.  In this
+ * case we can safely call the native malloc/free directly as a performance
+ * optimization.
+ */
+
+#  if USE_TCLALLOC
+#     define ckalloc(x) Tcl_Alloc(x)
+#     define ckfree(x) Tcl_Free(x)
+#     define ckrealloc(x,y) Tcl_Realloc(x,y)
+#  else
+#     define ckalloc(x) malloc(x)
+#     define ckfree(x)  free(x)
+#     define ckrealloc(x,y) realloc(x,y)
+#  endif
+#  define Tcl_DumpActiveMemory(x)
+#  define Tcl_ValidateAllMemory(x,y)
+
+#endif /* TCL_MEM_DEBUG */
+
+/*
+ * Forward declaration of Tcl_HashTable.  Needed by some C++ compilers
+ * to prevent errors when the forward reference to Tcl_HashTable is
+ * encountered in the Tcl_HashEntry structure.
+ */
+
+#ifdef __cplusplus
+struct Tcl_HashTable;
+#endif
+
+/*
+ * Structure definition for an entry in a hash table.  No-one outside
+ * Tcl should access any of these fields directly;  use the macros
+ * defined below.
+ */
+
+typedef struct Tcl_HashEntry {
+    struct Tcl_HashEntry *nextPtr;	/* Pointer to next entry in this
+					 * hash bucket, or NULL for end of
+					 * chain. */
+    struct Tcl_HashTable *tablePtr;	/* Pointer to table containing entry. */
+    struct Tcl_HashEntry **bucketPtr;	/* Pointer to bucket that points to
+					 * first entry in this entry's chain:
+					 * used for deleting the entry. */
+    ClientData clientData;		/* Application stores something here
+					 * with Tcl_SetHashValue. */
+    union {				/* Key has one of these forms: */
+	char *oneWordValue;		/* One-word value for key. */
+	int words[1];			/* Multiple integer words for key.
+					 * The actual size will be as large
+					 * as necessary for this table's
+					 * keys. */
+	char string[4];			/* String for key.  The actual size
+					 * will be as large as needed to hold
+					 * the key. */
+    } key;				/* MUST BE LAST FIELD IN RECORD!! */
+} Tcl_HashEntry;
+
+/*
+ * Structure definition for a hash table.  Must be in tcl.h so clients
+ * can allocate space for these structures, but clients should never
+ * access any fields in this structure.
+ */
+
+#define TCL_SMALL_HASH_TABLE 4
+typedef struct Tcl_HashTable {
+    Tcl_HashEntry **buckets;		/* Pointer to bucket array.  Each
+					 * element points to first entry in
+					 * bucket's hash chain, or NULL. */
+    Tcl_HashEntry *staticBuckets[TCL_SMALL_HASH_TABLE];
+					/* Bucket array used for small tables
+					 * (to avoid mallocs and frees). */
+    int numBuckets;			/* Total number of buckets allocated
+					 * at **bucketPtr. */
+    int numEntries;			/* Total number of entries present
+					 * in table. */
+    int rebuildSize;			/* Enlarge table when numEntries gets
+					 * to be this large. */
+    int downShift;			/* Shift count used in hashing
+					 * function.  Designed to use high-
+					 * order bits of randomized keys. */
+    int mask;				/* Mask value used in hashing
+					 * function. */
+    int keyType;			/* Type of keys used in this table. 
+					 * It's either TCL_STRING_KEYS,
+					 * TCL_ONE_WORD_KEYS, or an integer
+					 * giving the number of ints that
+                                         * is the size of the key.
+					 */
+    Tcl_HashEntry *(*findProc) _ANSI_ARGS_((struct Tcl_HashTable *tablePtr,
+	    CONST char *key));
+    Tcl_HashEntry *(*createProc) _ANSI_ARGS_((struct Tcl_HashTable *tablePtr,
+	    CONST char *key, int *newPtr));
+} Tcl_HashTable;
+
+/*
+ * Structure definition for information used to keep track of searches
+ * through hash tables:
+ */
+
+typedef struct Tcl_HashSearch {
+    Tcl_HashTable *tablePtr;		/* Table being searched. */
+    int nextIndex;			/* Index of next bucket to be
+					 * enumerated after present one. */
+    Tcl_HashEntry *nextEntryPtr;	/* Next entry to be enumerated in the
+					 * the current bucket. */
+} Tcl_HashSearch;
+
+/*
+ * Acceptable key types for hash tables:
+ */
+
+#define TCL_STRING_KEYS		0
+#define TCL_ONE_WORD_KEYS	1
+
+/*
+ * Macros for clients to use to access fields of hash entries:
+ */
+
+#define Tcl_GetHashValue(h) ((h)->clientData)
+#define Tcl_SetHashValue(h, value) ((h)->clientData = (ClientData) (value))
+#define Tcl_GetHashKey(tablePtr, h) \
+    ((char *) (((tablePtr)->keyType == TCL_ONE_WORD_KEYS) ? (h)->key.oneWordValue \
+						: (h)->key.string))
+
+/*
+ * Macros to use for clients to use to invoke find and create procedures
+ * for hash tables:
+ */
+
+#define Tcl_FindHashEntry(tablePtr, key) \
+	(*((tablePtr)->findProc))(tablePtr, key)
+#define Tcl_CreateHashEntry(tablePtr, key, newPtr) \
+	(*((tablePtr)->createProc))(tablePtr, key, newPtr)
+
+/*
+ * Flag values to pass to Tcl_DoOneEvent to disable searches
+ * for some kinds of events:
+ */
+
+#define TCL_DONT_WAIT		(1<<1)
+#define TCL_WINDOW_EVENTS	(1<<2)
+#define TCL_FILE_EVENTS		(1<<3)
+#define TCL_TIMER_EVENTS	(1<<4)
+#define TCL_IDLE_EVENTS		(1<<5)	/* WAS 0x10 ???? */
+#define TCL_ALL_EVENTS		(~TCL_DONT_WAIT)
+
+/*
+ * The following structure defines a generic event for the Tcl event
+ * system.  These are the things that are queued in calls to Tcl_QueueEvent
+ * and serviced later by Tcl_DoOneEvent.  There can be many different
+ * kinds of events with different fields, corresponding to window events,
+ * timer events, etc.  The structure for a particular event consists of
+ * a Tcl_Event header followed by additional information specific to that
+ * event.
+ */
+
+struct Tcl_Event {
+    Tcl_EventProc *proc;	/* Procedure to call to service this event. */
+    struct Tcl_Event *nextPtr;	/* Next in list of pending events, or NULL. */
+};
+
+/*
+ * Positions to pass to Tcl_QueueEvent:
+ */
+
+typedef enum {
+    TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, TCL_QUEUE_MARK
+} Tcl_QueuePosition;
+
+/*
+ * Values to pass to Tcl_SetServiceMode to specify the behavior of notifier
+ * event routines.
+ */
+
+#define TCL_SERVICE_NONE 0
+#define TCL_SERVICE_ALL 1
+
+/*
+ * The following structure keeps is used to hold a time value, either as
+ * an absolute time (the number of seconds from the epoch) or as an
+ * elapsed time. On Unix systems the epoch is Midnight Jan 1, 1970 GMT.
+ * On Macintosh systems the epoch is Midnight Jan 1, 1904 GMT.
+ */
+
+typedef struct Tcl_Time {
+    long sec;			/* Seconds. */
+    long usec;			/* Microseconds. */
+} Tcl_Time;
+
+/*
+ * Bits to pass to Tcl_CreateFileHandler and Tcl_CreateChannelHandler
+ * to indicate what sorts of events are of interest:
+ */
+
+#define TCL_READABLE	(1<<1)
+#define TCL_WRITABLE	(1<<2)
+#define TCL_EXCEPTION	(1<<3)
+
+/*
+ * Flag values to pass to Tcl_OpenCommandChannel to indicate the
+ * disposition of the stdio handles.  TCL_STDIN, TCL_STDOUT, TCL_STDERR,
+ * are also used in Tcl_GetStdChannel.
+ */
+
+#define TCL_STDIN		(1<<1)	
+#define TCL_STDOUT		(1<<2)
+#define TCL_STDERR		(1<<3)
+#define TCL_ENFORCE_MODE	(1<<4)
+
+/*
+ * Typedefs for the various operations in a channel type:
+ */
+
+typedef int	(Tcl_DriverBlockModeProc) _ANSI_ARGS_((
+		    ClientData instanceData, int mode));
+typedef int	(Tcl_DriverCloseProc) _ANSI_ARGS_((ClientData instanceData,
+		    Tcl_Interp *interp));
+typedef int	(Tcl_DriverInputProc) _ANSI_ARGS_((ClientData instanceData,
+		    char *buf, int toRead, int *errorCodePtr));
+typedef int	(Tcl_DriverOutputProc) _ANSI_ARGS_((ClientData instanceData,
+		    char *buf, int toWrite, int *errorCodePtr));
+typedef int	(Tcl_DriverSeekProc) _ANSI_ARGS_((ClientData instanceData,
+		    long offset, int mode, int *errorCodePtr));
+typedef int	(Tcl_DriverSetOptionProc) _ANSI_ARGS_((
+		    ClientData instanceData, Tcl_Interp *interp,
+	            char *optionName, char *value));
+typedef int	(Tcl_DriverGetOptionProc) _ANSI_ARGS_((
+		    ClientData instanceData, Tcl_Interp *interp,
+		    char *optionName, Tcl_DString *dsPtr));
+typedef void	(Tcl_DriverWatchProc) _ANSI_ARGS_((
+		    ClientData instanceData, int mask));
+typedef int	(Tcl_DriverGetHandleProc) _ANSI_ARGS_((
+		    ClientData instanceData, int direction,
+		    ClientData *handlePtr));
+
+/*
+ * Enum for different end of line translation and recognition modes.
+ */
+
+typedef enum Tcl_EolTranslation {
+    TCL_TRANSLATE_AUTO,			/* Eol == \r, \n and \r\n. */
+    TCL_TRANSLATE_CR,			/* Eol == \r. */
+    TCL_TRANSLATE_LF,			/* Eol == \n. */
+    TCL_TRANSLATE_CRLF			/* Eol == \r\n. */
+} Tcl_EolTranslation;
+
+/*
+ * struct Tcl_ChannelType:
+ *
+ * One such structure exists for each type (kind) of channel.
+ * It collects together in one place all the functions that are
+ * part of the specific channel type.
+ */
+
+typedef struct Tcl_ChannelType {
+    char *typeName;			/* The name of the channel type in Tcl
+                                         * commands. This storage is owned by
+                                         * channel type. */
+    Tcl_DriverBlockModeProc *blockModeProc;
+    					/* Set blocking mode for the
+                                         * raw channel. May be NULL. */
+    Tcl_DriverCloseProc *closeProc;	/* Procedure to call to close
+                                         * the channel. */
+    Tcl_DriverInputProc *inputProc;	/* Procedure to call for input
+                                         * on channel. */
+    Tcl_DriverOutputProc *outputProc;	/* Procedure to call for output
+                                         * on channel. */
+    Tcl_DriverSeekProc *seekProc;	/* Procedure to call to seek
+                                         * on the channel. May be NULL. */
+    Tcl_DriverSetOptionProc *setOptionProc;
+    					/* Set an option on a channel. */
+    Tcl_DriverGetOptionProc *getOptionProc;
+    					/* Get an option from a channel. */
+    Tcl_DriverWatchProc *watchProc;	/* Set up the notifier to watch
+                                         * for events on this channel. */
+    Tcl_DriverGetHandleProc *getHandleProc;
+					/* Get an OS handle from the channel
+                                         * or NULL if not supported. */
+    VOID *reserved;			/* reserved for future expansion */
+} Tcl_ChannelType;
+
+/*
+ * The following flags determine whether the blockModeProc above should
+ * set the channel into blocking or nonblocking mode. They are passed
+ * as arguments to the blockModeProc procedure in the above structure.
+ */
+
+#define TCL_MODE_BLOCKING 0		/* Put channel into blocking mode. */
+#define TCL_MODE_NONBLOCKING 1		/* Put channel into nonblocking
+					 * mode. */
+
+/*
+ * Enum for different types of file paths.
+ */
+
+typedef enum Tcl_PathType {
+    TCL_PATH_ABSOLUTE,
+    TCL_PATH_RELATIVE,
+    TCL_PATH_VOLUME_RELATIVE
+} Tcl_PathType;
+
+/*
+ * Exported Tcl procedures:
+ */
+
+EXTERN void		Tcl_AddErrorInfo _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *message));
+EXTERN void		Tcl_AddObjErrorInfo _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *message, int length));
+EXTERN void		Tcl_AllowExceptions _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN int		Tcl_AppendAllObjTypes _ANSI_ARGS_((
+			    Tcl_Interp *interp, Tcl_Obj *objPtr));
+EXTERN void		Tcl_AppendElement _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string));
+EXTERN void		Tcl_AppendResult _ANSI_ARGS_(
+			    TCL_VARARGS(Tcl_Interp *,interp));
+EXTERN void		Tcl_AppendToObj _ANSI_ARGS_((Tcl_Obj *objPtr,
+			    char *bytes, int length));
+EXTERN void		Tcl_AppendStringsToObj _ANSI_ARGS_(
+			    TCL_VARARGS(Tcl_Obj *,interp));
+EXTERN Tcl_AsyncHandler	Tcl_AsyncCreate _ANSI_ARGS_((Tcl_AsyncProc *proc,
+			    ClientData clientData));
+EXTERN void		Tcl_AsyncDelete _ANSI_ARGS_((Tcl_AsyncHandler async));
+EXTERN int		Tcl_AsyncInvoke _ANSI_ARGS_((Tcl_Interp *interp,
+			    int code));
+EXTERN void		Tcl_AsyncMark _ANSI_ARGS_((Tcl_AsyncHandler async));
+EXTERN int		Tcl_AsyncReady _ANSI_ARGS_((void));
+EXTERN char		Tcl_Backslash _ANSI_ARGS_((CONST char *src,
+			    int *readPtr));
+EXTERN int		Tcl_BadChannelOption _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *optionName, char *optionList));
+EXTERN void		Tcl_CallWhenDeleted _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_InterpDeleteProc *proc,
+			    ClientData clientData));
+EXTERN void		Tcl_CancelIdleCall _ANSI_ARGS_((Tcl_IdleProc *idleProc,
+			    ClientData clientData));
+#define Tcl_Ckalloc Tcl_Alloc
+#define Tcl_Ckfree Tcl_Free
+#define Tcl_Ckrealloc Tcl_Realloc
+EXTERN int		Tcl_Close _ANSI_ARGS_((Tcl_Interp *interp,
+        		    Tcl_Channel chan));
+EXTERN int		Tcl_CommandComplete _ANSI_ARGS_((char *cmd));
+EXTERN char *		Tcl_Concat _ANSI_ARGS_((int argc, char **argv));
+EXTERN Tcl_Obj *	Tcl_ConcatObj _ANSI_ARGS_((int objc,
+			    Tcl_Obj *CONST objv[]));
+EXTERN int		Tcl_ConvertCountedElement _ANSI_ARGS_((CONST char *src,
+			    int length, char *dst, int flags));
+EXTERN int		Tcl_ConvertElement _ANSI_ARGS_((CONST char *src,
+			    char *dst, int flags));
+EXTERN int		Tcl_ConvertToType _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr, Tcl_ObjType *typePtr));
+EXTERN int		Tcl_CreateAlias _ANSI_ARGS_((Tcl_Interp *slave,
+			    char *slaveCmd, Tcl_Interp *target,
+        		    char *targetCmd, int argc, char **argv));
+EXTERN int		Tcl_CreateAliasObj _ANSI_ARGS_((Tcl_Interp *slave,
+			    char *slaveCmd, Tcl_Interp *target,
+        		    char *targetCmd, int objc,
+		            Tcl_Obj *CONST objv[]));
+EXTERN Tcl_Channel	Tcl_CreateChannel _ANSI_ARGS_((
+    			    Tcl_ChannelType *typePtr, char *chanName,
+                            ClientData instanceData, int mask));
+EXTERN void		Tcl_CreateChannelHandler _ANSI_ARGS_((
+			    Tcl_Channel chan, int mask,
+                            Tcl_ChannelProc *proc, ClientData clientData));
+EXTERN void		Tcl_CreateCloseHandler _ANSI_ARGS_((
+			    Tcl_Channel chan, Tcl_CloseProc *proc,
+                            ClientData clientData));
+EXTERN Tcl_Command	Tcl_CreateCommand _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *cmdName, Tcl_CmdProc *proc,
+			    ClientData clientData,
+			    Tcl_CmdDeleteProc *deleteProc));
+EXTERN void		Tcl_CreateEventSource _ANSI_ARGS_((
+			    Tcl_EventSetupProc *setupProc,
+			    Tcl_EventCheckProc *checkProc,
+			    ClientData clientData));
+EXTERN void		Tcl_CreateFileHandler _ANSI_ARGS_((
+    			    int fd, int mask, Tcl_FileProc *proc,
+			    ClientData clientData));
+EXTERN Tcl_Interp *	Tcl_CreateInterp _ANSI_ARGS_((void));
+EXTERN void		Tcl_CreateMathFunc _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *name, int numArgs, Tcl_ValueType *argTypes,
+			    Tcl_MathProc *proc, ClientData clientData));
+EXTERN Tcl_Command	Tcl_CreateObjCommand _ANSI_ARGS_((
+			    Tcl_Interp *interp, char *cmdName,
+			    Tcl_ObjCmdProc *proc, ClientData clientData,
+			    Tcl_CmdDeleteProc *deleteProc));
+EXTERN Tcl_Interp *	Tcl_CreateSlave _ANSI_ARGS_((Tcl_Interp *interp,
+		            char *slaveName, int isSafe));
+EXTERN Tcl_TimerToken	Tcl_CreateTimerHandler _ANSI_ARGS_((int milliseconds,
+			    Tcl_TimerProc *proc, ClientData clientData));
+EXTERN Tcl_Trace	Tcl_CreateTrace _ANSI_ARGS_((Tcl_Interp *interp,
+			    int level, Tcl_CmdTraceProc *proc,
+			    ClientData clientData));
+EXTERN char *		Tcl_DbCkalloc _ANSI_ARGS_((unsigned int size,
+			    char *file, int line));
+EXTERN int		Tcl_DbCkfree _ANSI_ARGS_((char *ptr,
+			    char *file, int line));
+EXTERN char *		Tcl_DbCkrealloc _ANSI_ARGS_((char *ptr,
+			    unsigned int size, char *file, int line));
+EXTERN void		Tcl_DbDecrRefCount _ANSI_ARGS_((Tcl_Obj *objPtr,
+			    char *file, int line));
+EXTERN void		Tcl_DbIncrRefCount _ANSI_ARGS_((Tcl_Obj *objPtr,
+			    char *file, int line));
+EXTERN int		Tcl_DbIsShared _ANSI_ARGS_((Tcl_Obj *objPtr,
+			    char *file, int line));
+EXTERN Tcl_Obj *	Tcl_DbNewBooleanObj _ANSI_ARGS_((int boolValue,
+                            char *file, int line));
+EXTERN Tcl_Obj *	Tcl_DbNewDoubleObj _ANSI_ARGS_((double doubleValue,
+                            char *file, int line));
+EXTERN Tcl_Obj *	Tcl_DbNewListObj _ANSI_ARGS_((int objc,
+			    Tcl_Obj *CONST objv[], char *file, int line));
+EXTERN Tcl_Obj *	Tcl_DbNewLongObj _ANSI_ARGS_((long longValue,
+                            char *file, int line));
+EXTERN Tcl_Obj *	Tcl_DbNewObj _ANSI_ARGS_((char *file, int line));
+EXTERN Tcl_Obj *	Tcl_DbNewStringObj _ANSI_ARGS_((char *bytes,
+			    int length, char *file, int line));
+EXTERN void		Tcl_DeleteAssocData _ANSI_ARGS_((Tcl_Interp *interp,
+                            char *name));
+EXTERN int		Tcl_DeleteCommand _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *cmdName));
+EXTERN int		Tcl_DeleteCommandFromToken _ANSI_ARGS_((
+			    Tcl_Interp *interp, Tcl_Command command));
+EXTERN void		Tcl_DeleteChannelHandler _ANSI_ARGS_((
+    			    Tcl_Channel chan, Tcl_ChannelProc *proc,
+                            ClientData clientData));
+EXTERN void		Tcl_DeleteCloseHandler _ANSI_ARGS_((
+			    Tcl_Channel chan, Tcl_CloseProc *proc,
+                            ClientData clientData));
+EXTERN void		Tcl_DeleteEvents _ANSI_ARGS_((
+			    Tcl_EventDeleteProc *proc,
+                            ClientData clientData));
+EXTERN void		Tcl_DeleteEventSource _ANSI_ARGS_((
+			    Tcl_EventSetupProc *setupProc,
+			    Tcl_EventCheckProc *checkProc,
+			    ClientData clientData));
+EXTERN void		Tcl_DeleteExitHandler _ANSI_ARGS_((Tcl_ExitProc *proc,
+			    ClientData clientData));
+EXTERN void		Tcl_DeleteFileHandler _ANSI_ARGS_((int fd));
+EXTERN void		Tcl_DeleteHashEntry _ANSI_ARGS_((
+			    Tcl_HashEntry *entryPtr));
+EXTERN void		Tcl_DeleteHashTable _ANSI_ARGS_((
+			    Tcl_HashTable *tablePtr));
+EXTERN void		Tcl_DeleteInterp _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN void		Tcl_DeleteTimerHandler _ANSI_ARGS_((
+			    Tcl_TimerToken token));
+EXTERN void		Tcl_DeleteTrace _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Trace trace));
+EXTERN void		Tcl_DetachPids _ANSI_ARGS_((int numPids, Tcl_Pid *pidPtr));
+EXTERN void		Tcl_DontCallWhenDeleted _ANSI_ARGS_((
+			    Tcl_Interp *interp, Tcl_InterpDeleteProc *proc,
+			    ClientData clientData));
+EXTERN int		Tcl_DoOneEvent _ANSI_ARGS_((int flags));
+EXTERN void		Tcl_DoWhenIdle _ANSI_ARGS_((Tcl_IdleProc *proc,
+			    ClientData clientData));
+EXTERN char *		Tcl_DStringAppend _ANSI_ARGS_((Tcl_DString *dsPtr,
+			    CONST char *string, int length));
+EXTERN char *		Tcl_DStringAppendElement _ANSI_ARGS_((
+			    Tcl_DString *dsPtr, CONST char *string));
+EXTERN void		Tcl_DStringEndSublist _ANSI_ARGS_((Tcl_DString *dsPtr));
+EXTERN void		Tcl_DStringFree _ANSI_ARGS_((Tcl_DString *dsPtr));
+EXTERN void		Tcl_DStringGetResult _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_DString *dsPtr));
+EXTERN void		Tcl_DStringInit _ANSI_ARGS_((Tcl_DString *dsPtr));
+EXTERN void		Tcl_DStringResult _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_DString *dsPtr));
+EXTERN void		Tcl_DStringSetLength _ANSI_ARGS_((Tcl_DString *dsPtr,
+			    int length));
+EXTERN void		Tcl_DStringStartSublist _ANSI_ARGS_((
+			    Tcl_DString *dsPtr));
+EXTERN Tcl_Obj *	Tcl_DuplicateObj _ANSI_ARGS_((Tcl_Obj *objPtr));
+EXTERN int		Tcl_Eof _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN char *		Tcl_ErrnoId _ANSI_ARGS_((void));
+EXTERN char *		Tcl_ErrnoMsg _ANSI_ARGS_((int err));
+EXTERN int		Tcl_Eval _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string));
+EXTERN int		Tcl_EvalFile _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *fileName));
+EXTERN void		Tcl_EventuallyFree _ANSI_ARGS_((ClientData clientData,
+			    Tcl_FreeProc *freeProc));
+EXTERN int		Tcl_EvalObj _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr));
+EXTERN int		Tcl_ExposeCommand _ANSI_ARGS_((Tcl_Interp *interp,
+        		    char *hiddenCmdToken, char *cmdName));
+EXTERN int		Tcl_ExprBoolean _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, int *ptr));
+EXTERN int		Tcl_ExprBooleanObj _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr, int *ptr));
+EXTERN int		Tcl_ExprDouble _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, double *ptr));
+EXTERN int		Tcl_ExprDoubleObj _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr, double *ptr));
+EXTERN int		Tcl_ExprLong _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, long *ptr));
+EXTERN int		Tcl_ExprLongObj _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr, long *ptr));
+EXTERN int		Tcl_ExprObj _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr, Tcl_Obj **resultPtrPtr));
+EXTERN int		Tcl_ExprString _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string));
+EXTERN void		Tcl_Finalize _ANSI_ARGS_((void));
+EXTERN void		Tcl_FindExecutable _ANSI_ARGS_((char *argv0));
+EXTERN Tcl_HashEntry *	Tcl_FirstHashEntry _ANSI_ARGS_((
+			    Tcl_HashTable *tablePtr,
+			    Tcl_HashSearch *searchPtr));
+EXTERN int		Tcl_Flush _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN void		TclFreeObj _ANSI_ARGS_((Tcl_Obj *objPtr));
+EXTERN void		Tcl_FreeResult _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN int		Tcl_GetAlias _ANSI_ARGS_((Tcl_Interp *interp,
+       			    char *slaveCmd, Tcl_Interp **targetInterpPtr,
+                            char **targetCmdPtr, int *argcPtr,
+			    char ***argvPtr));
+EXTERN int		Tcl_GetAliasObj _ANSI_ARGS_((Tcl_Interp *interp,
+       			    char *slaveCmd, Tcl_Interp **targetInterpPtr,
+                            char **targetCmdPtr, int *objcPtr,
+			    Tcl_Obj ***objv));
+EXTERN ClientData	Tcl_GetAssocData _ANSI_ARGS_((Tcl_Interp *interp,
+                            char *name, Tcl_InterpDeleteProc **procPtr));
+EXTERN int		Tcl_GetBoolean _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, int *boolPtr));
+EXTERN int		Tcl_GetBooleanFromObj _ANSI_ARGS_((
+			    Tcl_Interp *interp, Tcl_Obj *objPtr,
+			    int *boolPtr));
+EXTERN int		Tcl_GetChannelHandle _ANSI_ARGS_((Tcl_Channel chan,
+	        	    int direction, ClientData *handlePtr));
+EXTERN ClientData	Tcl_GetChannelInstanceData _ANSI_ARGS_((
+    			    Tcl_Channel chan));
+EXTERN int		Tcl_GetChannelMode _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN char *		Tcl_GetChannelName _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN int		Tcl_GetChannelOption _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Channel chan, char *optionName,
+			    Tcl_DString *dsPtr));
+EXTERN Tcl_ChannelType * Tcl_GetChannelType _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN int		Tcl_GetCommandInfo _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *cmdName, Tcl_CmdInfo *infoPtr));
+EXTERN char *		Tcl_GetCommandName _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Command command));
+EXTERN int		Tcl_GetDouble _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, double *doublePtr));
+EXTERN int		Tcl_GetDoubleFromObj _ANSI_ARGS_((
+			    Tcl_Interp *interp, Tcl_Obj *objPtr,
+			    double *doublePtr));
+EXTERN int		Tcl_GetErrno _ANSI_ARGS_((void));
+EXTERN char *		Tcl_GetHostName _ANSI_ARGS_((void));
+EXTERN int		Tcl_GetIndexFromObj _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr, char **tablePtr, char *msg,
+			    int flags, int *indexPtr));
+EXTERN int		Tcl_GetInt _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, int *intPtr));
+EXTERN int		Tcl_GetInterpPath _ANSI_ARGS_((Tcl_Interp *askInterp,
+			    Tcl_Interp *slaveInterp));
+EXTERN int		Tcl_GetIntFromObj _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr, int *intPtr));
+EXTERN int		Tcl_GetLongFromObj _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr, long *longPtr));
+EXTERN Tcl_Interp *	Tcl_GetMaster _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN CONST char *	Tcl_GetNameOfExecutable _ANSI_ARGS_((void));
+EXTERN Tcl_Obj *	Tcl_GetObjResult _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN Tcl_ObjType *	Tcl_GetObjType _ANSI_ARGS_((char *typeName));
+EXTERN int		Tcl_GetOpenFile _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, int write, int checkUsage,
+			    ClientData *filePtr));
+EXTERN Tcl_PathType	Tcl_GetPathType _ANSI_ARGS_((char *path));
+EXTERN int		Tcl_Gets _ANSI_ARGS_((Tcl_Channel chan,
+        		    Tcl_DString *dsPtr));
+EXTERN int		Tcl_GetsObj _ANSI_ARGS_((Tcl_Channel chan,
+        		    Tcl_Obj *objPtr));
+EXTERN int		Tcl_GetServiceMode _ANSI_ARGS_((void));
+EXTERN Tcl_Interp *	Tcl_GetSlave _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *slaveName));
+EXTERN char *		Tcl_GetStringFromObj _ANSI_ARGS_((Tcl_Obj *objPtr,
+			    int *lengthPtr));
+EXTERN char *		Tcl_GetStringResult _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN char *		Tcl_GetVar _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *varName, int flags));
+EXTERN char *		Tcl_GetVar2 _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *part1, char *part2, int flags));
+EXTERN int		Tcl_GlobalEval _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *command));
+EXTERN int		Tcl_GlobalEvalObj _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr));
+EXTERN char *		Tcl_HashStats _ANSI_ARGS_((Tcl_HashTable *tablePtr));
+EXTERN int		Tcl_HideCommand _ANSI_ARGS_((Tcl_Interp *interp,
+		            char *cmdName, char *hiddenCmdToken));
+EXTERN void		Tcl_InitHashTable _ANSI_ARGS_((Tcl_HashTable *tablePtr,
+			    int keyType));
+EXTERN void		Tcl_InitMemory _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN int		Tcl_InputBlocked _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN int		Tcl_InputBuffered _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN int		Tcl_InterpDeleted _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN int		Tcl_IsSafe _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN void		Tcl_InvalidateStringRep _ANSI_ARGS_((
+			    Tcl_Obj *objPtr));
+EXTERN char *		Tcl_JoinPath _ANSI_ARGS_((int argc, char **argv,
+			    Tcl_DString *resultPtr));
+EXTERN int		Tcl_LinkVar _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *varName, char *addr, int type));
+EXTERN int		Tcl_ListObjAppendList _ANSI_ARGS_((
+			    Tcl_Interp *interp, Tcl_Obj *listPtr, 
+			    Tcl_Obj *elemListPtr));
+EXTERN int		Tcl_ListObjAppendElement _ANSI_ARGS_((
+			    Tcl_Interp *interp, Tcl_Obj *listPtr,
+			    Tcl_Obj *objPtr));
+EXTERN int		Tcl_ListObjGetElements _ANSI_ARGS_((
+			    Tcl_Interp *interp, Tcl_Obj *listPtr,
+			    int *objcPtr, Tcl_Obj ***objvPtr));
+EXTERN int		Tcl_ListObjIndex _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *listPtr, int index, 
+			    Tcl_Obj **objPtrPtr));
+EXTERN int		Tcl_ListObjLength _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *listPtr, int *intPtr));
+EXTERN int		Tcl_ListObjReplace _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *listPtr, int first, int count,
+			    int objc, Tcl_Obj *CONST objv[]));
+EXTERN void		Tcl_Main _ANSI_ARGS_((int argc, char **argv,
+			    Tcl_AppInitProc *appInitProc));
+EXTERN Tcl_Channel	Tcl_MakeFileChannel _ANSI_ARGS_((ClientData handle,
+			    int mode));
+EXTERN int		Tcl_MakeSafe _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN Tcl_Channel	Tcl_MakeTcpClientChannel _ANSI_ARGS_((
+    			    ClientData tcpSocket));
+EXTERN char *		Tcl_Merge _ANSI_ARGS_((int argc, char **argv));
+EXTERN Tcl_HashEntry *	Tcl_NextHashEntry _ANSI_ARGS_((
+			    Tcl_HashSearch *searchPtr));
+EXTERN void		Tcl_NotifyChannel _ANSI_ARGS_((Tcl_Channel channel,
+			    int mask));
+EXTERN Tcl_Obj *	Tcl_ObjGetVar2 _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
+			    int flags));
+EXTERN Tcl_Obj *	Tcl_ObjSetVar2 _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
+			    Tcl_Obj *newValuePtr, int flags));
+EXTERN Tcl_Channel	Tcl_OpenCommandChannel _ANSI_ARGS_((
+    			    Tcl_Interp *interp, int argc, char **argv,
+			    int flags));
+EXTERN Tcl_Channel	Tcl_OpenFileChannel _ANSI_ARGS_((Tcl_Interp *interp,
+        		    char *fileName, char *modeString,
+                            int permissions));
+EXTERN Tcl_Channel	Tcl_OpenTcpClient _ANSI_ARGS_((Tcl_Interp *interp,
+			    int port, char *address, char *myaddr,
+		            int myport, int async));
+EXTERN Tcl_Channel	Tcl_OpenTcpServer _ANSI_ARGS_((Tcl_Interp *interp,
+		            int port, char *host,
+        		    Tcl_TcpAcceptProc *acceptProc,
+			    ClientData callbackData));
+EXTERN char *		Tcl_ParseVar _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, char **termPtr));
+EXTERN int		Tcl_PkgProvide _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *name, char *version));
+EXTERN char *		Tcl_PkgRequire _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *name, char *version, int exact));
+EXTERN char *		Tcl_PosixError _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN void		Tcl_Preserve _ANSI_ARGS_((ClientData data));
+EXTERN void		Tcl_PrintDouble _ANSI_ARGS_((Tcl_Interp *interp,
+			    double value, char *dst));
+EXTERN int		Tcl_PutEnv _ANSI_ARGS_((CONST char *string));
+EXTERN void		Tcl_QueueEvent _ANSI_ARGS_((Tcl_Event *evPtr,
+			    Tcl_QueuePosition position));
+EXTERN int		Tcl_Read _ANSI_ARGS_((Tcl_Channel chan,
+	        	    char *bufPtr, int toRead));
+EXTERN void		Tcl_ReapDetachedProcs _ANSI_ARGS_((void));
+EXTERN int		Tcl_RecordAndEval _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *cmd, int flags));
+EXTERN int		Tcl_RecordAndEvalObj _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *cmdPtr, int flags));
+EXTERN Tcl_RegExp	Tcl_RegExpCompile _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string));
+EXTERN int		Tcl_RegExpExec _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_RegExp regexp, char *string, char *start));
+EXTERN int		Tcl_RegExpMatch _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, char *pattern));
+EXTERN void		Tcl_RegExpRange _ANSI_ARGS_((Tcl_RegExp regexp,
+			    int index, char **startPtr, char **endPtr));
+EXTERN void		Tcl_RegisterObjType _ANSI_ARGS_((
+			    Tcl_ObjType *typePtr));
+EXTERN void		Tcl_Release _ANSI_ARGS_((ClientData clientData));
+EXTERN void		Tcl_ResetResult _ANSI_ARGS_((Tcl_Interp *interp));
+#define Tcl_Return Tcl_SetResult
+EXTERN int		Tcl_ScanCountedElement _ANSI_ARGS_((CONST char *string,
+			    int length, int *flagPtr));
+EXTERN int		Tcl_ScanElement _ANSI_ARGS_((CONST char *string,
+			    int *flagPtr));
+EXTERN int		Tcl_Seek _ANSI_ARGS_((Tcl_Channel chan,
+        		    int offset, int mode));
+EXTERN int		Tcl_ServiceAll _ANSI_ARGS_((void));
+EXTERN int		Tcl_ServiceEvent _ANSI_ARGS_((int flags));
+EXTERN void		Tcl_SetAssocData _ANSI_ARGS_((Tcl_Interp *interp,
+                            char *name, Tcl_InterpDeleteProc *proc,
+                            ClientData clientData));
+EXTERN void		Tcl_SetBooleanObj _ANSI_ARGS_((Tcl_Obj *objPtr, 
+			    int boolValue));
+EXTERN void		Tcl_SetChannelBufferSize _ANSI_ARGS_((
+			    Tcl_Channel chan, int sz));
+EXTERN int		Tcl_SetChannelOption _ANSI_ARGS_((
+			    Tcl_Interp *interp, Tcl_Channel chan,
+	        	    char *optionName, char *newValue));
+EXTERN int		Tcl_SetCommandInfo _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *cmdName, Tcl_CmdInfo *infoPtr));
+EXTERN void		Tcl_SetDoubleObj _ANSI_ARGS_((Tcl_Obj *objPtr, 
+			    double doubleValue));
+EXTERN void		Tcl_SetErrno _ANSI_ARGS_((int err));
+EXTERN void		Tcl_SetErrorCode _ANSI_ARGS_(
+    			    TCL_VARARGS(Tcl_Interp *,arg1));
+EXTERN void		Tcl_SetIntObj _ANSI_ARGS_((Tcl_Obj *objPtr, 
+			    int intValue));
+EXTERN void		Tcl_SetListObj _ANSI_ARGS_((Tcl_Obj *objPtr, 
+			    int objc, Tcl_Obj *CONST objv[]));
+EXTERN void		Tcl_SetLongObj _ANSI_ARGS_((Tcl_Obj *objPtr, 
+			    long longValue));
+EXTERN void		Tcl_SetMaxBlockTime _ANSI_ARGS_((Tcl_Time *timePtr));
+EXTERN void		Tcl_SetObjErrorCode _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *errorObjPtr));
+EXTERN void		Tcl_SetObjLength _ANSI_ARGS_((Tcl_Obj *objPtr,
+			    int length));
+EXTERN void		Tcl_SetObjResult _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *resultObjPtr));
+EXTERN void		Tcl_SetPanicProc _ANSI_ARGS_((void (*proc)
+			    _ANSI_ARGS_(TCL_VARARGS(char *, format))));
+EXTERN int		Tcl_SetRecursionLimit _ANSI_ARGS_((Tcl_Interp *interp,
+			    int depth));
+EXTERN void		Tcl_SetResult _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, Tcl_FreeProc *freeProc));
+EXTERN int		Tcl_SetServiceMode _ANSI_ARGS_((int mode));
+EXTERN void		Tcl_SetStdChannel _ANSI_ARGS_((Tcl_Channel channel,
+			    int type));
+EXTERN void		Tcl_SetStringObj _ANSI_ARGS_((Tcl_Obj *objPtr, 
+			    char *bytes, int length));
+EXTERN void		Tcl_SetTimer _ANSI_ARGS_((Tcl_Time *timePtr));
+EXTERN char *		Tcl_SetVar _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *varName, char *newValue, int flags));
+EXTERN char *		Tcl_SetVar2 _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *part1, char *part2, char *newValue,
+			    int flags));
+EXTERN char *		Tcl_SignalId _ANSI_ARGS_((int sig));
+EXTERN char *		Tcl_SignalMsg _ANSI_ARGS_((int sig));
+EXTERN void		Tcl_SourceRCFile _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN int		Tcl_SplitList _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *list, int *argcPtr, char ***argvPtr));
+EXTERN void		Tcl_SplitPath _ANSI_ARGS_((char *path,
+			    int *argcPtr, char ***argvPtr));
+EXTERN void		Tcl_StaticPackage _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *pkgName, Tcl_PackageInitProc *initProc,
+			    Tcl_PackageInitProc *safeInitProc));
+EXTERN int		Tcl_StringMatch _ANSI_ARGS_((char *string,
+			    char *pattern));
+EXTERN int		Tcl_Tell _ANSI_ARGS_((Tcl_Channel chan));
+#define Tcl_TildeSubst Tcl_TranslateFileName
+EXTERN int		Tcl_TraceVar _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *varName, int flags, Tcl_VarTraceProc *proc,
+			    ClientData clientData));
+EXTERN int		Tcl_TraceVar2 _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *part1, char *part2, int flags,
+			    Tcl_VarTraceProc *proc, ClientData clientData));
+EXTERN char *		Tcl_TranslateFileName _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *name, Tcl_DString *bufferPtr));
+EXTERN int		Tcl_Ungets _ANSI_ARGS_((Tcl_Channel chan, char *str,
+			    int len, int atHead));
+EXTERN void		Tcl_UnlinkVar _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *varName));
+EXTERN int		Tcl_UnsetVar _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *varName, int flags));
+EXTERN int		Tcl_UnsetVar2 _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *part1, char *part2, int flags));
+EXTERN void		Tcl_UntraceVar _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *varName, int flags, Tcl_VarTraceProc *proc,
+			    ClientData clientData));
+EXTERN void		Tcl_UntraceVar2 _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *part1, char *part2, int flags,
+			    Tcl_VarTraceProc *proc, ClientData clientData));
+EXTERN void		Tcl_UpdateLinkedVar _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *varName));
+EXTERN int		Tcl_UpVar _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *frameName, char *varName,
+			    char *localName, int flags));
+EXTERN int		Tcl_UpVar2 _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *frameName, char *part1, char *part2,
+			    char *localName, int flags));
+EXTERN int		Tcl_VarEval _ANSI_ARGS_(
+    			    TCL_VARARGS(Tcl_Interp *,interp));
+EXTERN ClientData	Tcl_VarTraceInfo _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *varName, int flags,
+			    Tcl_VarTraceProc *procPtr,
+			    ClientData prevClientData));
+EXTERN ClientData	Tcl_VarTraceInfo2 _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *part1, char *part2, int flags,
+			    Tcl_VarTraceProc *procPtr,
+			    ClientData prevClientData));
+EXTERN Tcl_Pid		Tcl_WaitPid _ANSI_ARGS_((Tcl_Pid pid, int *statPtr, 
+			    int options));
+EXTERN int		Tcl_Write _ANSI_ARGS_((Tcl_Channel chan,
+			    char *s, int slen));
+EXTERN void		Tcl_WrongNumArgs _ANSI_ARGS_((Tcl_Interp *interp,
+			    int objc, Tcl_Obj *CONST objv[], char *message));
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS
+
+/*
+ * Convenience declaration of Tcl_AppInit for backwards compatibility.
+ * This function is not *implemented* by the tcl library, so the storage
+ * class is neither DLLEXPORT nor DLLIMPORT
+ */
+
+EXTERN int             Tcl_AppInit _ANSI_ARGS_((Tcl_Interp *interp));
+
+#endif /* RESOURCE_INCLUDED */
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
+
+#endif /* _TCL */
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclAlloc.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclAlloc.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclAlloc.c	(revision 5)
@@ -0,0 +1,219 @@
+/* 
+ * tclAlloc.c --
+ *
+ *	This is a very fast storage allocator.  It allocates blocks of a
+ *	small number of different sizes, and keeps free lists of each size.
+ *	Blocks that don't exactly fit are passed up to the next larger size.
+ *	Blocks over a certain size are directly allocated from the system.
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ *
+ * Portions contributed by Chris Kingsley, Jack Jansen and Ray Johnson.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclAlloc.c,v 1.1 2008-06-04 13:58:03 demin Exp $
+ */
+
+#include "tclInt.h"
+#include "tclPort.h"
+
+#ifdef TCL_DEBUG
+#   define DEBUG
+/* #define MSTATS */
+#   define RCHECK
+#endif
+
+//typedef unsigned long caddr_t;
+
+/*
+ * The overhead on a block is at least 4 bytes.  When free, this space
+ * contains a pointer to the next free block, and the bottom two bits must
+ * be zero.  When in use, the first byte is set to MAGIC, and the second
+ * byte is the size index.  The remaining bytes are for alignment.
+ * If range checking is enabled then a second word holds the size of the
+ * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC).
+ * The order of elements is critical: ov_magic must overlay the low order
+ * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern.
+ */
+
+union overhead {
+    union overhead *ov_next;	/* when free */
+    struct {
+	unsigned char	ovu_magic0;	/* magic number */
+	unsigned char	ovu_index;	/* bucket # */
+	unsigned char	ovu_unused;	/* unused */
+	unsigned char	ovu_magic1;	/* other magic number */
+#ifdef RCHECK
+	unsigned short	ovu_rmagic;	/* range magic number */
+	unsigned long	ovu_size;	/* actual block size */
+#endif
+    } ovu;
+#define ov_magic0	ovu.ovu_magic0
+#define ov_magic1	ovu.ovu_magic1
+#define ov_index	ovu.ovu_index
+#define ov_rmagic	ovu.ovu_rmagic
+#define ov_size	ovu.ovu_size
+};
+
+
+#define MAGIC		0xef		/* magic # on accounting info */
+#define RMAGIC		0x5555		/* magic # on range info */
+
+#ifdef RCHECK
+#define	RSLOP		sizeof (unsigned short)
+#else
+#define	RSLOP		0
+#endif
+
+#define OVERHEAD (sizeof(union overhead) + RSLOP)
+
+/*
+ * nextf[i] is the pointer to the next free block of size 2^(i+3).  The
+ * smallest allocatable block is 8 bytes.  The overhead information
+ * precedes the data area returned to the user.
+ */
+
+#define NBUCKETS	13
+#define MAXMALLOC	(1<<(NBUCKETS+2))
+
+#ifdef MSTATS
+
+/*
+ * nmalloc[i] is the difference between the number of mallocs and frees
+ * for a given block size.
+ */
+
+static	unsigned int nmalloc[NBUCKETS+1];
+#include <stdio.h>
+#endif
+
+#if defined(DEBUG) || defined(RCHECK)
+#define	ASSERT(p)   if (!(p)) panic(# p)
+#define RANGE_ASSERT(p) if (!(p)) panic(# p)
+#else
+#define	ASSERT(p)
+#define RANGE_ASSERT(p)
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpAlloc --
+ *
+ *	Allocate more memory.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+TclpAlloc(
+    unsigned int nbytes)	/* Number of bytes to allocate. */
+{
+    return (char*) malloc(nbytes);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpFree --
+ *
+ *	Free memory.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpFree(
+    char *cp)		/* Pointer to memory to free. */
+{   
+    free(cp);
+    return;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpRealloc --
+ *
+ *	Reallocate memory.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+TclpRealloc(
+    char *cp,			/* Pointer to alloced block. */
+    unsigned int nbytes)	/* New size of memory. */
+{   
+    return (char*) realloc(cp, nbytes);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * mstats --
+ *
+ *	Prints two lines of numbers, one showing the length of the 
+ *	free list for each size category, the second showing the 
+ *	number of mallocs - frees for each size category.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef MSTATS
+void
+mstats(
+    char *s)	/* Where to write info. */
+{
+    register int i, j;
+    register union overhead *p;
+    int totfree = 0,
+	totused = 0;
+
+    fprintf(stderr, "Memory allocation statistics %s\nTclpFree:\t", s);
+    for (i = 0; i < NBUCKETS; i++) {
+	for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
+	    fprintf(stderr, " %d", j);
+	totfree += j * (1 << (i + 3));
+    }
+    fprintf(stderr, "\nused:\t");
+    for (i = 0; i < NBUCKETS; i++) {
+	fprintf(stderr, " %d", nmalloc[i]);
+	totused += nmalloc[i] * (1 << (i + 3));
+    }
+    fprintf(stderr, "\n\tTotal small in use: %d, total free: %d\n",
+	    totused, totfree);
+    fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %d\n", 
+	    MAXMALLOC, nmalloc[NBUCKETS]);
+}
+#endif
+
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclAsync.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclAsync.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclAsync.c	(revision 5)
@@ -0,0 +1,270 @@
+/* 
+ * tclAsync.c --
+ *
+ *	This file provides low-level support needed to invoke signal
+ *	handlers in a safe way.  The code here doesn't actually handle
+ *	signals, though.  This code is based on proposals made by
+ *	Mark Diekhans and Don Libes.
+ *
+ * Copyright (c) 1993 The Regents of the University of California.
+ * Copyright (c) 1994 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclAsync.c,v 1.1 2008-06-04 13:58:03 demin Exp $
+ */
+
+#include "tclInt.h"
+
+/*
+ * One of the following structures exists for each asynchronous
+ * handler:
+ */
+
+typedef struct AsyncHandler {
+    int ready;				/* Non-zero means this handler should
+					 * be invoked in the next call to
+					 * Tcl_AsyncInvoke. */
+    struct AsyncHandler *nextPtr;	/* Next in list of all handlers for
+					 * the process. */
+    Tcl_AsyncProc *proc;		/* Procedure to call when handler
+					 * is invoked. */
+    ClientData clientData;		/* Value to pass to handler when it
+					 * is invoked. */
+} AsyncHandler;
+
+/*
+ * The variables below maintain a list of all existing handlers.
+ */
+
+static AsyncHandler *firstHandler;	/* First handler defined for process,
+					 * or NULL if none. */
+static AsyncHandler *lastHandler;	/* Last handler or NULL. */
+
+/*
+ * The variable below is set to 1 whenever a handler becomes ready and
+ * it is cleared to zero whenever Tcl_AsyncInvoke is called.  It can be
+ * checked elsewhere in the application by calling Tcl_AsyncReady to see
+ * if Tcl_AsyncInvoke should be invoked.
+ */
+
+static int asyncReady = 0;
+
+/*
+ * The variable below indicates whether Tcl_AsyncInvoke is currently
+ * working.  If so then we won't set asyncReady again until
+ * Tcl_AsyncInvoke returns.
+ */
+
+static int asyncActive = 0;
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AsyncCreate --
+ *
+ *	This procedure creates the data structures for an asynchronous
+ *	handler, so that no memory has to be allocated when the handler
+ *	is activated.
+ *
+ * Results:
+ *	The return value is a token for the handler, which can be used
+ *	to activate it later on.
+ *
+ * Side effects:
+ *	Information about the handler is recorded.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_AsyncHandler
+Tcl_AsyncCreate(proc, clientData)
+    Tcl_AsyncProc *proc;		/* Procedure to call when handler
+					 * is invoked. */
+    ClientData clientData;		/* Argument to pass to handler. */
+{
+    AsyncHandler *asyncPtr;
+
+    asyncPtr = (AsyncHandler *) ckalloc(sizeof(AsyncHandler));
+    asyncPtr->ready = 0;
+    asyncPtr->nextPtr = NULL;
+    asyncPtr->proc = proc;
+    asyncPtr->clientData = clientData;
+    if (firstHandler == NULL) {
+	firstHandler = asyncPtr;
+    } else {
+	lastHandler->nextPtr = asyncPtr;
+    }
+    lastHandler = asyncPtr;
+    return (Tcl_AsyncHandler) asyncPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AsyncMark --
+ *
+ *	This procedure is called to request that an asynchronous handler
+ *	be invoked as soon as possible.  It's typically called from
+ *	an interrupt handler, where it isn't safe to do anything that
+ *	depends on or modifies application state.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The handler gets marked for invocation later.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_AsyncMark(async)
+    Tcl_AsyncHandler async;		/* Token for handler. */
+{
+    ((AsyncHandler *) async)->ready = 1;
+    if (!asyncActive) {
+	asyncReady = 1;
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AsyncInvoke --
+ *
+ *	This procedure is called at a "safe" time at background level
+ *	to invoke any active asynchronous handlers.
+ *
+ * Results:
+ *	The return value is a normal Tcl result, which is intended to
+ *	replace the code argument as the current completion code for
+ *	interp.
+ *
+ * Side effects:
+ *	Depends on the handlers that are active.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_AsyncInvoke(interp, code)
+    Tcl_Interp *interp;			/* If invoked from Tcl_Eval just after
+					 * completing a command, points to
+					 * interpreter.  Otherwise it is
+					 * NULL. */
+    int code; 				/* If interp is non-NULL, this gives
+					 * completion code from command that
+					 * just completed. */
+{
+    AsyncHandler *asyncPtr;
+
+    if (asyncReady == 0) {
+	return code;
+    }
+    asyncReady = 0;
+    asyncActive = 1;
+    if (interp == NULL) {
+	code = 0;
+    }
+
+    /*
+     * Make one or more passes over the list of handlers, invoking
+     * at most one handler in each pass.  After invoking a handler,
+     * go back to the start of the list again so that (a) if a new
+     * higher-priority handler gets marked while executing a lower
+     * priority handler, we execute the higher-priority handler
+     * next, and (b) if a handler gets deleted during the execution
+     * of a handler, then the list structure may change so it isn't
+     * safe to continue down the list anyway.
+     */
+
+    while (1) {
+	for (asyncPtr = firstHandler; asyncPtr != NULL;
+		asyncPtr = asyncPtr->nextPtr) {
+	    if (asyncPtr->ready) {
+		break;
+	    }
+	}
+	if (asyncPtr == NULL) {
+	    break;
+	}
+	asyncPtr->ready = 0;
+	code = (*asyncPtr->proc)(asyncPtr->clientData, interp, code);
+    }
+    asyncActive = 0;
+    return code;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AsyncDelete --
+ *
+ *	Frees up all the state for an asynchronous handler.  The handler
+ *	should never be used again.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The state associated with the handler is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_AsyncDelete(async)
+    Tcl_AsyncHandler async;		/* Token for handler to delete. */
+{
+    AsyncHandler *asyncPtr = (AsyncHandler *) async;
+    AsyncHandler *prevPtr;
+
+    if (firstHandler == asyncPtr) {
+	firstHandler = asyncPtr->nextPtr;
+	if (firstHandler == NULL) {
+	    lastHandler = NULL;
+	}
+    } else {
+	prevPtr = firstHandler;
+	while (prevPtr->nextPtr != asyncPtr) {
+	    prevPtr = prevPtr->nextPtr;
+	}
+	prevPtr->nextPtr = asyncPtr->nextPtr;
+	if (lastHandler == asyncPtr) {
+	    lastHandler = prevPtr;
+	}
+    }
+    ckfree((char *) asyncPtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AsyncReady --
+ *
+ *	This procedure can be used to tell whether Tcl_AsyncInvoke
+ *	needs to be called.  This procedure is the external interface
+ *	for checking the internal asyncReady variable.
+ *
+ * Results:
+ * 	The return value is 1 whenever a handler is ready and is 0
+ *	when no handlers are ready.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_AsyncReady()
+{
+    return asyncReady;
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclBasic.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclBasic.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclBasic.c	(revision 5)
@@ -0,0 +1,3814 @@
+/* 
+ * tclBasic.c --
+ *
+ *	Contains the basic facilities for TCL command interpretation,
+ *	including interpreter creation and deletion, command creation
+ *	and deletion, and command parsing and execution.
+ *
+ * Copyright (c) 1987-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclBasic.c,v 1.1 2008-06-04 13:58:03 demin Exp $
+ */
+
+#include "tclInt.h"
+#include "tclCompile.h"
+#ifndef TCL_GENERIC_ONLY
+#   include "tclPort.h"
+#endif
+
+/*
+ * Static procedures in this file:
+ */
+
+static void		DeleteInterpProc _ANSI_ARGS_((Tcl_Interp *interp));
+static void		HiddenCmdsDeleteProc _ANSI_ARGS_((
+			    ClientData clientData, Tcl_Interp *interp));
+
+/*
+ * The following structure defines the commands in the Tcl core.
+ */
+
+typedef struct {
+    char *name;			/* Name of object-based command. */
+    Tcl_CmdProc *proc;		/* String-based procedure for command. */
+    Tcl_ObjCmdProc *objProc;	/* Object-based procedure for command. */
+    CompileProc *compileProc;	/* Procedure called to compile command. */
+    int isSafe;			/* If non-zero, command will be present
+                                 * in safe interpreter. Otherwise it will
+                                 * be hidden. */
+} CmdInfo;
+
+/*
+ * The built-in commands, and the procedures that implement them:
+ */
+
+static CmdInfo builtInCmds[] = {
+    /*
+     * Commands in the generic core. Note that at least one of the proc or
+     * objProc members should be non-NULL. This avoids infinitely recursive
+     * calls between TclInvokeObjectCommand and TclInvokeStringCommand if a
+     * command name is computed at runtime and results in the name of a
+     * compiled command.
+     */
+
+    {"append",		(Tcl_CmdProc *) NULL,	Tcl_AppendObjCmd,
+        (CompileProc *) NULL,		1},
+    {"array",		(Tcl_CmdProc *) NULL,	Tcl_ArrayObjCmd,
+        (CompileProc *) NULL,		1},
+    {"break",		Tcl_BreakCmd,		(Tcl_ObjCmdProc *) NULL,
+        TclCompileBreakCmd,		1},
+    {"case",		(Tcl_CmdProc *) NULL,	Tcl_CaseObjCmd,
+        (CompileProc *) NULL,		1},
+    {"catch",		(Tcl_CmdProc *) NULL,	Tcl_CatchObjCmd,	
+        TclCompileCatchCmd,		1},
+    {"concat",		(Tcl_CmdProc *) NULL,	Tcl_ConcatObjCmd,
+        (CompileProc *) NULL,		1},
+    {"continue",	Tcl_ContinueCmd,	(Tcl_ObjCmdProc *) NULL,
+        TclCompileContinueCmd,		1},
+    {"error",		(Tcl_CmdProc *) NULL,	Tcl_ErrorObjCmd,
+        (CompileProc *) NULL,		1},
+    {"eval",		(Tcl_CmdProc *) NULL,	Tcl_EvalObjCmd,
+        (CompileProc *) NULL,		1},
+    {"expr",		(Tcl_CmdProc *) NULL,	Tcl_ExprObjCmd,
+        TclCompileExprCmd,		1},
+    {"for",		Tcl_ForCmd,		(Tcl_ObjCmdProc *) NULL,
+        TclCompileForCmd,		1},
+    {"foreach",		(Tcl_CmdProc *) NULL,	Tcl_ForeachObjCmd,
+        TclCompileForeachCmd,		1},
+    {"format",		(Tcl_CmdProc *) NULL,	Tcl_FormatObjCmd,
+        (CompileProc *) NULL,		1},
+    {"global",		(Tcl_CmdProc *) NULL,	Tcl_GlobalObjCmd,
+        (CompileProc *) NULL,		1},
+    {"if",		Tcl_IfCmd,		(Tcl_ObjCmdProc *) NULL,
+        TclCompileIfCmd,		1},
+    {"incr",		Tcl_IncrCmd,		(Tcl_ObjCmdProc *) NULL,
+        TclCompileIncrCmd,		1},
+    {"info",		(Tcl_CmdProc *) NULL,	Tcl_InfoObjCmd,
+        (CompileProc *) NULL,		1},
+    {"join",		(Tcl_CmdProc *) NULL,	Tcl_JoinObjCmd,
+        (CompileProc *) NULL,		1},
+    {"lappend",		(Tcl_CmdProc *) NULL,	Tcl_LappendObjCmd,
+        (CompileProc *) NULL,		1},
+    {"add",		(Tcl_CmdProc *) NULL,	Tcl_LappendObjCmd,
+        (CompileProc *) NULL,		1},
+    {"lindex",		(Tcl_CmdProc *) NULL,	Tcl_LindexObjCmd,
+        (CompileProc *) NULL,		1},
+    {"linsert",		(Tcl_CmdProc *) NULL,	Tcl_LinsertObjCmd,
+        (CompileProc *) NULL,		1},
+    {"list",		(Tcl_CmdProc *) NULL,	Tcl_ListObjCmd,
+        (CompileProc *) NULL,		1},
+    {"llength",		(Tcl_CmdProc *) NULL,	Tcl_LlengthObjCmd,
+        (CompileProc *) NULL,		1},
+    {"lrange",		(Tcl_CmdProc *) NULL,	Tcl_LrangeObjCmd,
+        (CompileProc *) NULL,		1},
+    {"lreplace",	(Tcl_CmdProc *) NULL,	Tcl_LreplaceObjCmd,
+        (CompileProc *) NULL,		1},
+    {"lsort",		(Tcl_CmdProc *) NULL,	Tcl_LsortObjCmd,
+        (CompileProc *) NULL,		1},
+    {"namespace",	(Tcl_CmdProc *) NULL,	Tcl_NamespaceObjCmd,
+        (CompileProc *) NULL,		1},
+    {"proc",		(Tcl_CmdProc *) NULL,	Tcl_ProcObjCmd,	
+        (CompileProc *) NULL,		1},
+    {"return",		(Tcl_CmdProc *) NULL,	Tcl_ReturnObjCmd,	
+        (CompileProc *) NULL,		1},
+    {"scan",		Tcl_ScanCmd,		(Tcl_ObjCmdProc *) NULL,
+        (CompileProc *) NULL,		1},
+    {"set",		Tcl_SetCmd,		(Tcl_ObjCmdProc *) NULL,    
+        TclCompileSetCmd,		1},
+    {"split",		(Tcl_CmdProc *) NULL,	Tcl_SplitObjCmd,
+        (CompileProc *) NULL,		1},
+    {"string",		(Tcl_CmdProc *) NULL,	Tcl_StringObjCmd,
+        (CompileProc *) NULL,		1},
+    {"subst",		Tcl_SubstCmd,		(Tcl_ObjCmdProc *) NULL,
+        (CompileProc *) NULL,		1},
+    {"trace",		Tcl_TraceCmd,		(Tcl_ObjCmdProc *) NULL,
+        (CompileProc *) NULL,		1},
+    {"unset",		(Tcl_CmdProc *) NULL,	Tcl_UnsetObjCmd,	
+        (CompileProc *) NULL,		1},
+    {"uplevel",		(Tcl_CmdProc *) NULL,	Tcl_UplevelObjCmd,	
+        (CompileProc *) NULL,		1},
+    {"upvar",		(Tcl_CmdProc *) NULL,	Tcl_UpvarObjCmd,	
+        (CompileProc *) NULL,		1},
+    {"variable",	(Tcl_CmdProc *) NULL,	Tcl_VariableObjCmd,
+        (CompileProc *) NULL,		1},
+    {"while",		Tcl_WhileCmd,		(Tcl_ObjCmdProc *) NULL,    
+        TclCompileWhileCmd,		1},
+
+    {NULL,		(Tcl_CmdProc *) NULL,	(Tcl_ObjCmdProc *) NULL,
+        (CompileProc *) NULL,		0}
+};
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CreateInterp --
+ *
+ *	Create a new TCL command interpreter.
+ *
+ * Results:
+ *	The return value is a token for the interpreter, which may be
+ *	used in calls to procedures like Tcl_CreateCmd, Tcl_Eval, or
+ *	Tcl_DeleteInterp.
+ *
+ * Side effects:
+ *	The command interpreter is initialized with an empty variable
+ *	table and the built-in commands.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Interp *
+Tcl_CreateInterp()
+{
+    register Interp *iPtr;
+    register Command *cmdPtr;
+    register CmdInfo *cmdInfoPtr;
+    union {
+	char c[sizeof(short)];
+	short s;
+    } order;
+
+    /*
+     * Panic if someone updated the CallFrame structure without
+     * also updating the Tcl_CallFrame structure (or vice versa).
+     */  
+
+    if (sizeof(Tcl_CallFrame) != sizeof(CallFrame)) {
+	/*NOTREACHED*/
+        panic("Tcl_CallFrame and CallFrame are not the same size");
+    }
+
+    /*
+     * Initialize support for namespaces and create the global namespace
+     * (whose name is ""; an alias is "::"). This also initializes the
+     * Tcl object type table and other object management code.
+     */
+
+    TclInitNamespaces();
+    
+    iPtr = (Interp *) ckalloc(sizeof(Interp));
+    iPtr->result = iPtr->resultSpace;
+    iPtr->freeProc = 0;
+    iPtr->objResultPtr = Tcl_NewObj(); /* an empty object */
+    Tcl_IncrRefCount(iPtr->objResultPtr);
+    iPtr->errorLine = 0;
+    Tcl_InitHashTable(&iPtr->mathFuncTable, TCL_STRING_KEYS);
+    iPtr->numLevels = 0;
+    iPtr->maxNestingDepth = 1000;
+    iPtr->framePtr = NULL;
+    iPtr->varFramePtr = NULL;
+    iPtr->activeTracePtr = NULL;
+    iPtr->returnCode = TCL_OK;
+    iPtr->errorInfo = NULL;
+    iPtr->errorCode = NULL;
+    iPtr->appendResult = NULL;
+    iPtr->appendAvl = 0;
+    iPtr->appendUsed = 0;
+    iPtr->cmdCount = 0;
+    iPtr->termOffset = 0;
+    iPtr->compileEpoch = 0;
+    iPtr->compiledProcPtr = NULL;
+    iPtr->resolverPtr = NULL;
+    iPtr->evalFlags = 0;
+    iPtr->scriptFile = NULL;
+    iPtr->flags = 0;
+    iPtr->tracePtr = NULL;
+    iPtr->assocData = (Tcl_HashTable *) NULL;
+    iPtr->execEnvPtr = NULL;	      /* set after namespaces initialized */
+    iPtr->emptyObjPtr = Tcl_NewObj(); /* another empty object */
+    Tcl_IncrRefCount(iPtr->emptyObjPtr);
+    iPtr->resultSpace[0] = 0;
+
+    iPtr->globalNsPtr = NULL;	/* force creation of global ns below */
+    iPtr->globalNsPtr = (Namespace *) Tcl_CreateNamespace(
+	    (Tcl_Interp *) iPtr, "", (ClientData) NULL,
+	    (Tcl_NamespaceDeleteProc *) NULL);
+    if (iPtr->globalNsPtr == NULL) {
+        panic("Tcl_CreateInterp: can't create global namespace");
+    }
+
+    /*
+     * Initialize support for code compilation. Do this after initializing
+     * namespaces since TclCreateExecEnv will try to reference a Tcl
+     * variable (it links to the Tcl "tcl_traceExec" variable).
+     */
+    
+    iPtr->execEnvPtr = TclCreateExecEnv((Tcl_Interp *) iPtr);
+
+    /*
+     * Create the core commands. Do it here, rather than calling
+     * Tcl_CreateCommand, because it's faster (there's no need to check for
+     * a pre-existing command by the same name). If a command has a
+     * Tcl_CmdProc but no Tcl_ObjCmdProc, set the Tcl_ObjCmdProc to
+     * TclInvokeStringCommand. This is an object-based wrapper procedure
+     * that extracts strings, calls the string procedure, and creates an
+     * object for the result. Similarly, if a command has a Tcl_ObjCmdProc
+     * but no Tcl_CmdProc, set the Tcl_CmdProc to TclInvokeObjectCommand.
+     */
+
+    for (cmdInfoPtr = builtInCmds;  cmdInfoPtr->name != NULL;
+	    cmdInfoPtr++) {
+	int new;
+	Tcl_HashEntry *hPtr;
+
+	if ((cmdInfoPtr->proc == (Tcl_CmdProc *) NULL)
+	        && (cmdInfoPtr->objProc == (Tcl_ObjCmdProc *) NULL)
+	        && (cmdInfoPtr->compileProc == (CompileProc *) NULL)) {
+	    panic("Tcl_CreateInterp: builtin command with NULL string and object command procs and a NULL compile proc\n");
+	}
+	
+	hPtr = Tcl_CreateHashEntry(&iPtr->globalNsPtr->cmdTable,
+	        cmdInfoPtr->name, &new);
+	if (new) {
+	    cmdPtr = (Command *) ckalloc(sizeof(Command));
+	    cmdPtr->hPtr = hPtr;
+	    cmdPtr->nsPtr = iPtr->globalNsPtr;
+	    cmdPtr->refCount = 1;
+	    cmdPtr->cmdEpoch = 0;
+	    cmdPtr->compileProc = cmdInfoPtr->compileProc;
+	    if (cmdInfoPtr->proc == (Tcl_CmdProc *) NULL) {
+		cmdPtr->proc = TclInvokeObjectCommand;
+		cmdPtr->clientData = (ClientData) cmdPtr;
+	    } else {
+		cmdPtr->proc = cmdInfoPtr->proc;
+		cmdPtr->clientData = (ClientData) NULL;
+	    }
+	    if (cmdInfoPtr->objProc == (Tcl_ObjCmdProc *) NULL) {
+		cmdPtr->objProc = TclInvokeStringCommand;
+		cmdPtr->objClientData = (ClientData) cmdPtr;
+	    } else {
+		cmdPtr->objProc = cmdInfoPtr->objProc;
+		cmdPtr->objClientData = (ClientData) NULL;
+	    }
+	    cmdPtr->deleteProc = NULL;
+	    cmdPtr->deleteData = (ClientData) NULL;
+	    cmdPtr->deleted = 0;
+	    cmdPtr->importRefPtr = NULL;
+	    Tcl_SetHashValue(hPtr, cmdPtr);
+	}
+    }
+
+    /*
+     *  Initialize/Create "errorInfo" and "errorCode" global vars
+     *  (because some part of the C code assume they exists
+     *   and we can get a seg fault otherwise (in multiple 
+     *   interps loading of extensions for instance) --dl)
+     */
+     /*
+      *  We can't assume that because we initialize 
+      *  the variables here, they won't be unset later.
+      *  so we had 2 choices:
+      *    + Check every place where a GetVar of those is used 
+      *      and the NULL result is not checked (like in tclLoad.c)
+      *    + Make SetVar,... NULL friendly
+      *  We choosed the second option because :
+      *    + It is easy and low cost to check for NULL pointer before
+      *      calling strlen()
+      *    + It can be helpfull to other people using those API
+      *    + Passing a NULL value to those closest 'meaning' is empty string
+      *      (specially with the new objects where 0 bytes strings are ok)
+      * So the following init is commented out:              -- dl
+      */
+    /*
+      (void)Tcl_SetVar2((Tcl_Interp *)iPtr, "errorInfo", (char *) NULL, "",
+         TCL_GLOBAL_ONLY);
+      (void)Tcl_SetVar2((Tcl_Interp *)iPtr, "errorCode", (char *) NULL, "NONE",
+	    TCL_GLOBAL_ONLY);
+     */
+
+    /*
+     * Set up variables such as tcl_version.
+     */
+
+    Tcl_SetVar((Tcl_Interp *) iPtr, "tcl_patchLevel", TCL_PATCH_LEVEL,
+	    TCL_GLOBAL_ONLY);
+    Tcl_SetVar((Tcl_Interp *) iPtr, "tcl_version", TCL_VERSION,
+	    TCL_GLOBAL_ONLY);
+    Tcl_TraceVar2((Tcl_Interp *) iPtr, "tcl_precision", (char *) NULL,
+	    TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+	    TclPrecTraceProc, (ClientData) NULL);
+
+    /*
+     * Compute the byte order of this machine.
+     */
+
+    order.s = 1;
+    Tcl_SetVar2((Tcl_Interp *) iPtr, "tcl_platform", "byteOrder",
+	    (order.c[0] == 1) ? "littleEndian" : "bigEndian",
+	    TCL_GLOBAL_ONLY);
+    
+    return (Tcl_Interp *) iPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tcl_CallWhenDeleted --
+ *
+ *	Arrange for a procedure to be called before a given
+ *	interpreter is deleted. The procedure is called as soon
+ *	as Tcl_DeleteInterp is called; if Tcl_CallWhenDeleted is
+ *	called on an interpreter that has already been deleted,
+ *	the procedure will be called when the last Tcl_Release is
+ *	done on the interpreter.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	When Tcl_DeleteInterp is invoked to delete interp,
+ *	proc will be invoked.  See the manual entry for
+ *	details.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tcl_CallWhenDeleted(interp, proc, clientData)
+    Tcl_Interp *interp;		/* Interpreter to watch. */
+    Tcl_InterpDeleteProc *proc;	/* Procedure to call when interpreter
+				 * is about to be deleted. */
+    ClientData clientData;	/* One-word value to pass to proc. */
+{
+    Interp *iPtr = (Interp *) interp;
+    static int assocDataCounter = 0;
+    int new;
+    char buffer[128];
+    AssocData *dPtr = (AssocData *) ckalloc(sizeof(AssocData));
+    Tcl_HashEntry *hPtr;
+
+    sprintf(buffer, "Assoc Data Key #%d", assocDataCounter);
+    assocDataCounter++;
+
+    if (iPtr->assocData == (Tcl_HashTable *) NULL) {
+        iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
+        Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
+    }
+    hPtr = Tcl_CreateHashEntry(iPtr->assocData, buffer, &new);
+    dPtr->proc = proc;
+    dPtr->clientData = clientData;
+    Tcl_SetHashValue(hPtr, dPtr);
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tcl_DontCallWhenDeleted --
+ *
+ *	Cancel the arrangement for a procedure to be called when
+ *	a given interpreter is deleted.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	If proc and clientData were previously registered as a
+ *	callback via Tcl_CallWhenDeleted, they are unregistered.
+ *	If they weren't previously registered then nothing
+ *	happens.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tcl_DontCallWhenDeleted(interp, proc, clientData)
+    Tcl_Interp *interp;		/* Interpreter to watch. */
+    Tcl_InterpDeleteProc *proc;	/* Procedure to call when interpreter
+				 * is about to be deleted. */
+    ClientData clientData;	/* One-word value to pass to proc. */
+{
+    Interp *iPtr = (Interp *) interp;
+    Tcl_HashTable *hTablePtr;
+    Tcl_HashSearch hSearch;
+    Tcl_HashEntry *hPtr;
+    AssocData *dPtr;
+
+    hTablePtr = iPtr->assocData;
+    if (hTablePtr == (Tcl_HashTable *) NULL) {
+        return;
+    }
+    for (hPtr = Tcl_FirstHashEntry(hTablePtr, &hSearch); hPtr != NULL;
+	    hPtr = Tcl_NextHashEntry(&hSearch)) {
+        dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
+        if ((dPtr->proc == proc) && (dPtr->clientData == clientData)) {
+            ckfree((char *) dPtr);
+            Tcl_DeleteHashEntry(hPtr);
+            return;
+        }
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetAssocData --
+ *
+ *	Creates a named association between user-specified data, a delete
+ *	function and this interpreter. If the association already exists
+ *	the data is overwritten with the new data. The delete function will
+ *	be invoked when the interpreter is deleted.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Sets the associated data, creates the association if needed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetAssocData(interp, name, proc, clientData)
+    Tcl_Interp *interp;		/* Interpreter to associate with. */
+    char *name;			/* Name for association. */
+    Tcl_InterpDeleteProc *proc;	/* Proc to call when interpreter is
+                                 * about to be deleted. */
+    ClientData clientData;	/* One-word value to pass to proc. */
+{
+    Interp *iPtr = (Interp *) interp;
+    AssocData *dPtr;
+    Tcl_HashEntry *hPtr;
+    int new;
+
+    if (iPtr->assocData == (Tcl_HashTable *) NULL) {
+        iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
+        Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
+    }
+    hPtr = Tcl_CreateHashEntry(iPtr->assocData, name, &new);
+    if (new == 0) {
+        dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
+    } else {
+        dPtr = (AssocData *) ckalloc(sizeof(AssocData));
+    }
+    dPtr->proc = proc;
+    dPtr->clientData = clientData;
+
+    Tcl_SetHashValue(hPtr, dPtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DeleteAssocData --
+ *
+ *	Deletes a named association of user-specified data with
+ *	the specified interpreter.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Deletes the association.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DeleteAssocData(interp, name)
+    Tcl_Interp *interp;			/* Interpreter to associate with. */
+    char *name;				/* Name of association. */
+{
+    Interp *iPtr = (Interp *) interp;
+    AssocData *dPtr;
+    Tcl_HashEntry *hPtr;
+
+    if (iPtr->assocData == (Tcl_HashTable *) NULL) {
+        return;
+    }
+    hPtr = Tcl_FindHashEntry(iPtr->assocData, name);
+    if (hPtr == (Tcl_HashEntry *) NULL) {
+        return;
+    }
+    dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
+    if (dPtr->proc != NULL) {
+        (dPtr->proc) (dPtr->clientData, interp);
+    }
+    ckfree((char *) dPtr);
+    Tcl_DeleteHashEntry(hPtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetAssocData --
+ *
+ *	Returns the client data associated with this name in the
+ *	specified interpreter.
+ *
+ * Results:
+ *	The client data in the AssocData record denoted by the named
+ *	association, or NULL.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ClientData
+Tcl_GetAssocData(interp, name, procPtr)
+    Tcl_Interp *interp;			/* Interpreter associated with. */
+    char *name;				/* Name of association. */
+    Tcl_InterpDeleteProc **procPtr;	/* Pointer to place to store address
+					 * of current deletion callback. */
+{
+    Interp *iPtr = (Interp *) interp;
+    AssocData *dPtr;
+    Tcl_HashEntry *hPtr;
+
+    if (iPtr->assocData == (Tcl_HashTable *) NULL) {
+        return (ClientData) NULL;
+    }
+    hPtr = Tcl_FindHashEntry(iPtr->assocData, name);
+    if (hPtr == (Tcl_HashEntry *) NULL) {
+        return (ClientData) NULL;
+    }
+    dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
+    if (procPtr != (Tcl_InterpDeleteProc **) NULL) {
+        *procPtr = dPtr->proc;
+    }
+    return dPtr->clientData;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteInterpProc --
+ *
+ *	Helper procedure to delete an interpreter. This procedure is
+ *	called when the last call to Tcl_Preserve on this interpreter
+ *	is matched by a call to Tcl_Release. The procedure cleans up
+ *	all resources used in the interpreter and calls all currently
+ *	registered interpreter deletion callbacks.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Whatever the interpreter deletion callbacks do. Frees resources
+ *	used by the interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DeleteInterpProc(interp)
+    Tcl_Interp *interp;			/* Interpreter to delete. */
+{
+    Interp *iPtr = (Interp *) interp;
+    Tcl_HashEntry *hPtr;
+    Tcl_HashSearch search;
+    Tcl_HashTable *hTablePtr;
+    AssocData *dPtr;
+    ResolverScheme *resPtr, *nextResPtr;
+
+    /*
+     * Punt if there is an error in the Tcl_Release/Tcl_Preserve matchup.
+     */
+    
+    if (iPtr->numLevels > 0) {
+        panic("DeleteInterpProc called with active evals");
+    }
+
+    /*
+     * The interpreter should already be marked deleted; otherwise how
+     * did we get here?
+     */
+
+    if (!(iPtr->flags & DELETED)) {
+        panic("DeleteInterpProc called on interpreter not marked deleted");
+    }
+
+    /*
+     * Dismantle everything in the global namespace except for the
+     * "errorInfo" and "errorCode" variables. These remain until the
+     * namespace is actually destroyed, in case any errors occur.
+     *   
+     * Dismantle the namespace here, before we clear the assocData. If any
+     * background errors occur here, they will be deleted below.
+     */
+    
+    TclTeardownNamespace(iPtr->globalNsPtr);
+
+    /*
+     * Tear down the math function table.
+     */
+
+    for (hPtr = Tcl_FirstHashEntry(&iPtr->mathFuncTable, &search);
+	     hPtr != NULL;
+             hPtr = Tcl_NextHashEntry(&search)) {
+	ckfree((char *) Tcl_GetHashValue(hPtr));
+    }
+    Tcl_DeleteHashTable(&iPtr->mathFuncTable);
+
+    /*
+     * Invoke deletion callbacks; note that a callback can create new
+     * callbacks, so we iterate.
+     */
+
+    while (iPtr->assocData != (Tcl_HashTable *) NULL) {
+        hTablePtr = iPtr->assocData;
+        iPtr->assocData = (Tcl_HashTable *) NULL;
+        for (hPtr = Tcl_FirstHashEntry(hTablePtr, &search);
+                 hPtr != NULL;
+                 hPtr = Tcl_FirstHashEntry(hTablePtr, &search)) {
+            dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
+            Tcl_DeleteHashEntry(hPtr);
+            if (dPtr->proc != NULL) {
+                (*dPtr->proc)(dPtr->clientData, interp);
+            }
+            ckfree((char *) dPtr);
+        }
+        Tcl_DeleteHashTable(hTablePtr);
+        ckfree((char *) hTablePtr);
+    }
+
+    /*
+     * Finish deleting the global namespace.
+     */
+    
+    Tcl_DeleteNamespace((Tcl_Namespace *) iPtr->globalNsPtr);
+
+    /*
+     * Free up the result *after* deleting variables, since variable
+     * deletion could have transferred ownership of the result string
+     * to Tcl.
+     */
+
+    Tcl_FreeResult(interp);
+    interp->result = NULL;
+    Tcl_DecrRefCount(iPtr->objResultPtr);
+    iPtr->objResultPtr = NULL;
+    if (iPtr->errorInfo != NULL) {
+	ckfree(iPtr->errorInfo);
+        iPtr->errorInfo = NULL;
+    }
+    if (iPtr->errorCode != NULL) {
+	ckfree(iPtr->errorCode);
+        iPtr->errorCode = NULL;
+    }
+    if (iPtr->appendResult != NULL) {
+	ckfree(iPtr->appendResult);
+        iPtr->appendResult = NULL;
+    }
+    while (iPtr->tracePtr != NULL) {
+	Trace *nextPtr = iPtr->tracePtr->nextPtr;
+
+	ckfree((char *) iPtr->tracePtr);
+	iPtr->tracePtr = nextPtr;
+    }
+    if (iPtr->execEnvPtr != NULL) {
+	TclDeleteExecEnv(iPtr->execEnvPtr);
+    }
+    Tcl_DecrRefCount(iPtr->emptyObjPtr);
+    iPtr->emptyObjPtr = NULL;
+
+    resPtr = iPtr->resolverPtr;
+    while (resPtr) {
+	nextResPtr = resPtr->nextPtr;
+	ckfree(resPtr->name);
+	ckfree((char *) resPtr);
+        resPtr = nextResPtr;
+    }
+    
+    ckfree((char *) iPtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_InterpDeleted --
+ *
+ *	Returns nonzero if the interpreter has been deleted with a call
+ *	to Tcl_DeleteInterp.
+ *
+ * Results:
+ *	Nonzero if the interpreter is deleted, zero otherwise.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_InterpDeleted(interp)
+    Tcl_Interp *interp;
+{
+    return (((Interp *) interp)->flags & DELETED) ? 1 : 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DeleteInterp --
+ *
+ *	Ensures that the interpreter will be deleted eventually. If there
+ *	are no Tcl_Preserve calls in effect for this interpreter, it is
+ *	deleted immediately, otherwise the interpreter is deleted when
+ *	the last Tcl_Preserve is matched by a call to Tcl_Release. In either
+ *	case, the procedure runs the currently registered deletion callbacks. 
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The interpreter is marked as deleted. The caller may still use it
+ *	safely if there are calls to Tcl_Preserve in effect for the
+ *	interpreter, but further calls to Tcl_Eval etc in this interpreter
+ *	will fail.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DeleteInterp(interp)
+    Tcl_Interp *interp;		/* Token for command interpreter (returned
+				 * by a previous call to Tcl_CreateInterp). */
+{
+    Interp *iPtr = (Interp *) interp;
+
+    /*
+     * If the interpreter has already been marked deleted, just punt.
+     */
+
+    if (iPtr->flags & DELETED) {
+        return;
+    }
+    
+    /*
+     * Mark the interpreter as deleted. No further evals will be allowed.
+     */
+
+    iPtr->flags |= DELETED;
+
+    /*
+     * Ensure that the interpreter is eventually deleted.
+     */
+
+    Tcl_EventuallyFree((ClientData) interp,
+            (Tcl_FreeProc *) DeleteInterpProc);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HiddenCmdsDeleteProc --
+ *
+ *	Called on interpreter deletion to delete all the hidden
+ *	commands in an interpreter.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Frees up memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+HiddenCmdsDeleteProc(clientData, interp)
+    ClientData clientData;		/* The hidden commands hash table. */
+    Tcl_Interp *interp;			/* The interpreter being deleted. */
+{
+    Tcl_HashTable *hiddenCmdTblPtr;
+    Tcl_HashEntry *hPtr;
+    Tcl_HashSearch hSearch;
+    Command *cmdPtr;
+
+    hiddenCmdTblPtr = (Tcl_HashTable *) clientData;
+    for (hPtr = Tcl_FirstHashEntry(hiddenCmdTblPtr, &hSearch);
+	     hPtr != NULL;
+             hPtr = Tcl_FirstHashEntry(hiddenCmdTblPtr, &hSearch)) {
+
+        /*
+         * Cannot use Tcl_DeleteCommand because (a) the command is not
+         * in the command hash table, and (b) that table has already been
+         * deleted above. Hence we emulate what it does, below.
+         */
+        
+        cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
+
+	/*
+         * The code here is tricky.  We can't delete the hash table entry
+         * before invoking the deletion callback because there are cases
+         * where the deletion callback needs to invoke the command (e.g.
+         * object systems such as OTcl).  However, this means that the
+         * callback could try to delete or rename the command.  The deleted
+         * flag allows us to detect these cases and skip nested deletes.
+         */
+
+        if (cmdPtr->deleted) {
+
+	    /*
+             * Another deletion is already in progress.  Remove the hash
+             * table entry now, but don't invoke a callback or free the
+             * command structure.
+             */
+
+            Tcl_DeleteHashEntry(cmdPtr->hPtr);
+            cmdPtr->hPtr = NULL;
+            continue;
+        }
+        cmdPtr->deleted = 1;
+        if (cmdPtr->deleteProc != NULL) {
+            (*cmdPtr->deleteProc)(cmdPtr->deleteData);
+        }
+
+	/*
+	 * Bump the command epoch counter. This will invalidate all cached
+         * references that refer to this command.
+	 */
+	
+        cmdPtr->cmdEpoch++;
+
+	/*
+         * Don't use hPtr to delete the hash entry here, because it's
+         * possible that the deletion callback renamed the command.
+         * Instead, use cmdPtr->hptr, and make sure that no-one else
+         * has already deleted the hash entry.
+         */
+
+        if (cmdPtr->hPtr != NULL) {
+            Tcl_DeleteHashEntry(cmdPtr->hPtr);
+        }
+	
+        /*
+	 * Now free the Command structure, unless there is another reference
+	 * to it from a CmdName Tcl object in some ByteCode code
+	 * sequence. In that case, delay the cleanup until all references
+	 * are either discarded (when a ByteCode is freed) or replaced by a
+	 * new reference (when a cached CmdName Command reference is found
+	 * to be invalid and TclExecuteByteCode looks up the command in the
+	 * command hashtable).
+	 */
+	
+	TclCleanupCommand(cmdPtr);
+    }
+    Tcl_DeleteHashTable(hiddenCmdTblPtr);
+    ckfree((char *) hiddenCmdTblPtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_HideCommand --
+ *
+ *	Makes a command hidden so that it cannot be invoked from within
+ *	an interpreter, only from within an ancestor.
+ *
+ * Results:
+ *	A standard Tcl result; also leaves a message in interp->result
+ *	if an error occurs.
+ *
+ * Side effects:
+ *	Removes a command from the command table and create an entry
+ *      into the hidden command table under the specified token name.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_HideCommand(interp, cmdName, hiddenCmdToken)
+    Tcl_Interp *interp;		/* Interpreter in which to hide command. */
+    char *cmdName;		/* Name of command to hide. */
+    char *hiddenCmdToken;	/* Token name of the to-be-hidden command. */
+{
+    Interp *iPtr = (Interp *) interp;
+    Tcl_Command cmd;
+    Command *cmdPtr;
+    Tcl_HashTable *hTblPtr;
+    Tcl_HashEntry *hPtr;
+    int new;
+
+    if (iPtr->flags & DELETED) {
+
+        /*
+         * The interpreter is being deleted. Do not create any new
+         * structures, because it is not safe to modify the interpreter.
+         */
+        
+        return TCL_ERROR;
+    }
+
+    /*
+     * Disallow hiding of commands that are currently in a namespace or
+     * renaming (as part of hiding) into a namespace.
+     *
+     * (because the current implementation with a single global table
+     *  and the needed uniqueness of names cause problems with namespaces)
+     *
+     * we don't need to check for "::" in cmdName because the real check is
+     * on the nsPtr below.
+     *
+     * hiddenCmdToken is just a string which is not interpreted in any way.
+     * It may contain :: but the string is not interpreted as a namespace
+     * qualifier command name. Thus, hiding foo::bar to foo::bar and then
+     * trying to expose or invoke ::foo::bar will NOT work; but if the
+     * application always uses the same strings it will get consistent
+     * behaviour.
+     *
+     * But as we currently limit ourselves to the global namespace only
+     * for the source, in order to avoid potential confusion,
+     * lets prevent "::" in the token too.  --dl
+     */
+
+    if (strstr(hiddenCmdToken, "::") != NULL) {
+        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                "cannot use namespace qualifiers as hidden command",
+		"token (rename)", (char *) NULL);
+        return TCL_ERROR;
+    }
+
+    /*
+     * Find the command to hide. An error is returned if cmdName can't
+     * be found. Look up the command only from the global namespace.
+     * Full path of the command must be given if using namespaces.
+     */
+
+    cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
+	    /*flags*/ TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
+    if (cmd == (Tcl_Command) NULL) {
+	return TCL_ERROR;
+    }
+    cmdPtr = (Command *) cmd;
+
+    /*
+     * Check that the command is really in global namespace
+     */
+
+    if ( cmdPtr->nsPtr != iPtr->globalNsPtr ) {
+        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                "can only hide global namespace commands",
+		" (use rename then hide)", (char *) NULL);
+        return TCL_ERROR;
+    }
+    
+    /*
+     * Initialize the hidden command table if necessary.
+     */
+
+    hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclHiddenCmds",
+            NULL);
+    if (hTblPtr == (Tcl_HashTable *) NULL) {
+        hTblPtr = (Tcl_HashTable *)
+	        ckalloc((unsigned) sizeof(Tcl_HashTable));
+        Tcl_InitHashTable(hTblPtr, TCL_STRING_KEYS);
+        Tcl_SetAssocData(interp, "tclHiddenCmds", HiddenCmdsDeleteProc,
+                (ClientData) hTblPtr);
+    }
+
+    /*
+     * It is an error to move an exposed command to a hidden command with
+     * hiddenCmdToken if a hidden command with the name hiddenCmdToken already
+     * exists.
+     */
+    
+    hPtr = Tcl_CreateHashEntry(hTblPtr, hiddenCmdToken, &new);
+    if (!new) {
+        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                "hidden command named \"", hiddenCmdToken, "\" already exists",
+                (char *) NULL);
+        return TCL_ERROR;
+    }
+
+    /*
+     * Nb : This code is currently 'like' a rename to a specialy set apart
+     * name table. Changes here and in TclRenameCommand must
+     * be kept in synch untill the common parts are actually
+     * factorized out.
+     */
+
+    /*
+     * Remove the hash entry for the command from the interpreter command
+     * table. This is like deleting the command, so bump its command epoch;
+     * this invalidates any cached references that point to the command.
+     */
+
+    if (cmdPtr->hPtr != NULL) {
+        Tcl_DeleteHashEntry(cmdPtr->hPtr);
+        cmdPtr->hPtr = (Tcl_HashEntry *) NULL;
+	cmdPtr->cmdEpoch++;
+    }
+
+    /*
+     * Now link the hash table entry with the command structure.
+     * We ensured above that the nsPtr was right.
+     */
+    
+    cmdPtr->hPtr = hPtr;
+    Tcl_SetHashValue(hPtr, (ClientData) cmdPtr);
+
+    /*
+     * If the command being hidden has a compile procedure, increment the
+     * interpreter's compileEpoch to invalidate its compiled code. This
+     * makes sure that we don't later try to execute old code compiled with
+     * command-specific (i.e., inline) bytecodes for the now-hidden
+     * command. This field is checked in Tcl_EvalObj and ObjInterpProc,
+     * and code whose compilation epoch doesn't match is recompiled.
+     */
+
+    if (cmdPtr->compileProc != NULL) {
+	iPtr->compileEpoch++;
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ExposeCommand --
+ *
+ *	Makes a previously hidden command callable from inside the
+ *	interpreter instead of only by its ancestors.
+ *
+ * Results:
+ *	A standard Tcl result. If an error occurs, a message is left
+ *	in interp->result.
+ *
+ * Side effects:
+ *	Moves commands from one hash table to another.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_ExposeCommand(interp, hiddenCmdToken, cmdName)
+    Tcl_Interp *interp;		/* Interpreter in which to make command
+                                 * callable. */
+    char *hiddenCmdToken;	/* Name of hidden command. */
+    char *cmdName;		/* Name of to-be-exposed command. */
+{
+    Interp *iPtr = (Interp *) interp;
+    Command *cmdPtr;
+    Namespace *nsPtr;
+    Tcl_HashEntry *hPtr;
+    Tcl_HashTable *hTblPtr;
+    int new;
+
+    if (iPtr->flags & DELETED) {
+        /*
+         * The interpreter is being deleted. Do not create any new
+         * structures, because it is not safe to modify the interpreter.
+         */
+        
+        return TCL_ERROR;
+    }
+
+    /*
+     * Check that we have a regular name for the command
+     * (that the user is not trying to do an expose and a rename
+     *  (to another namespace) at the same time)
+     */
+
+    if (strstr(cmdName, "::") != NULL) {
+        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                "can not expose to a namespace ",
+		"(use expose to toplevel, then rename)",
+                 (char *) NULL);
+        return TCL_ERROR;
+    }
+
+    /*
+     * Find the hash table for the hidden commands; error out if there
+     * is none.
+     */
+
+    hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclHiddenCmds",
+            NULL);
+    if (hTblPtr == NULL) {
+        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                "unknown hidden command \"", hiddenCmdToken,
+                "\"", (char *) NULL);
+        return TCL_ERROR;
+    }
+        
+    /*
+     * Get the command from the hidden command table:
+     */
+
+    hPtr = Tcl_FindHashEntry(hTblPtr, hiddenCmdToken);
+    if (hPtr == (Tcl_HashEntry *) NULL) {
+        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                "unknown hidden command \"", hiddenCmdToken,
+                "\"", (char *) NULL);
+        return TCL_ERROR;
+    }
+    cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
+    
+
+    /*
+     * Check that we have a true global namespace
+     * command (enforced by Tcl_HideCommand() but let's double
+     * check. (If it was not, we would not really know how to
+     * handle it).
+     */
+    if ( cmdPtr->nsPtr != iPtr->globalNsPtr ) {
+	/* 
+	 * This case is theoritically impossible,
+	 * we might rather panic() than 'nicely' erroring out ?
+	 */
+        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                "trying to expose a non global command name space command",
+		(char *) NULL);
+        return TCL_ERROR;
+    }
+    
+    /* This is the global table */
+    nsPtr = cmdPtr->nsPtr;
+
+    /*
+     * It is an error to overwrite an existing exposed command as a result
+     * of exposing a previously hidden command.
+     */
+
+    hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, cmdName, &new);
+    if (!new) {
+        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                "exposed command \"", cmdName,
+                "\" already exists", (char *) NULL);
+        return TCL_ERROR;
+    }
+
+    /*
+     * Remove the hash entry for the command from the interpreter hidden
+     * command table.
+     */
+
+    if (cmdPtr->hPtr != NULL) {
+        Tcl_DeleteHashEntry(cmdPtr->hPtr);
+        cmdPtr->hPtr = NULL;
+    }
+
+    /*
+     * Now link the hash table entry with the command structure.
+     * This is like creating a new command, so deal with any shadowing
+     * of commands in the global namespace.
+     */
+    
+    cmdPtr->hPtr = hPtr;
+
+    Tcl_SetHashValue(hPtr, (ClientData) cmdPtr);
+
+    /*
+     * Not needed as we are only in the global namespace
+     * (but would be needed again if we supported namespace command hiding)
+     *
+     * TclResetShadowedCmdRefs(interp, cmdPtr);
+     */
+
+
+    /*
+     * If the command being exposed has a compile procedure, increment
+     * interpreter's compileEpoch to invalidate its compiled code. This
+     * makes sure that we don't later try to execute old code compiled
+     * assuming the command is hidden. This field is checked in Tcl_EvalObj
+     * and ObjInterpProc, and code whose compilation epoch doesn't match is
+     * recompiled.
+     */
+
+    if (cmdPtr->compileProc != NULL) {
+	iPtr->compileEpoch++;
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CreateCommand --
+ *
+ *	Define a new command in a command table.
+ *
+ * Results:
+ *	The return value is a token for the command, which can
+ *	be used in future calls to Tcl_GetCommandName.
+ *
+ * Side effects:
+ *	If a command named cmdName already exists for interp, it is deleted.
+ *	In the future, when cmdName is seen as the name of a command by
+ *	Tcl_Eval, proc will be called. To support the bytecode interpreter,
+ *	the command is created with a wrapper Tcl_ObjCmdProc
+ *	(TclInvokeStringCommand) that eventially calls proc. When the
+ *	command is deleted from the table, deleteProc will be called.
+ *	See the manual entry for details on the calling sequence.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Command
+Tcl_CreateCommand(interp, cmdName, proc, clientData, deleteProc)
+    Tcl_Interp *interp;		/* Token for command interpreter returned by
+				 * a previous call to Tcl_CreateInterp. */
+    char *cmdName;		/* Name of command. If it contains namespace
+				 * qualifiers, the new command is put in the
+				 * specified namespace; otherwise it is put
+				 * in the global namespace. */
+    Tcl_CmdProc *proc;		/* Procedure to associate with cmdName. */
+    ClientData clientData;	/* Arbitrary value passed to string proc. */
+    Tcl_CmdDeleteProc *deleteProc;
+				/* If not NULL, gives a procedure to call
+				 * when this command is deleted. */
+{
+    Interp *iPtr = (Interp *) interp;
+    ImportRef *oldRefPtr = NULL;
+    Namespace *nsPtr, *dummy1, *dummy2;
+    Command *cmdPtr, *refCmdPtr;
+    Tcl_HashEntry *hPtr;
+    char *tail;
+    int new;
+    ImportedCmdData *dataPtr;
+
+    if (iPtr->flags & DELETED) {
+	/*
+	 * The interpreter is being deleted.  Don't create any new
+	 * commands; it's not safe to muck with the interpreter anymore.
+	 */
+
+	return (Tcl_Command) NULL;
+    }
+
+    /*
+     * Determine where the command should reside. If its name contains 
+     * namespace qualifiers, we put it in the specified namespace; 
+     * otherwise, we always put it in the global namespace.
+     */
+
+    if (strstr(cmdName, "::") != NULL) {
+       TclGetNamespaceForQualName(interp, cmdName, (Namespace *) NULL,
+           CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
+       if ((nsPtr == NULL) || (tail == NULL)) {
+	    return (Tcl_Command) NULL;
+	}
+    } else {
+	nsPtr = iPtr->globalNsPtr;
+	tail = cmdName;
+    }
+    
+    hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
+    if (!new) {
+	/*
+	 * Command already exists. Delete the old one.
+	 * Be careful to preserve any existing import links so we can
+	 * restore them down below.  That way, you can redefine a
+	 * command and its import status will remain intact.
+	 */
+
+	cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
+	oldRefPtr = cmdPtr->importRefPtr;
+	cmdPtr->importRefPtr = NULL;
+
+	Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
+	hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
+	if (!new) {
+	    /*
+	     * If the deletion callback recreated the command, just throw
+             * away the new command (if we try to delete it again, we
+             * could get stuck in an infinite loop).
+	     */
+
+	     ckfree((char*) cmdPtr);
+	}
+    }
+    cmdPtr = (Command *) ckalloc(sizeof(Command));
+    Tcl_SetHashValue(hPtr, cmdPtr);
+    cmdPtr->hPtr = hPtr;
+    cmdPtr->nsPtr = nsPtr;
+    cmdPtr->refCount = 1;
+    cmdPtr->cmdEpoch = 0;
+    cmdPtr->compileProc = (CompileProc *) NULL;
+    cmdPtr->objProc = TclInvokeStringCommand;
+    cmdPtr->objClientData = (ClientData) cmdPtr;
+    cmdPtr->proc = proc;
+    cmdPtr->clientData = clientData;
+    cmdPtr->deleteProc = deleteProc;
+    cmdPtr->deleteData = clientData;
+    cmdPtr->deleted = 0;
+    cmdPtr->importRefPtr = NULL;
+
+    /*
+     * Plug in any existing import references found above.  Be sure
+     * to update all of these references to point to the new command.
+     */
+
+    if (oldRefPtr != NULL) {
+	cmdPtr->importRefPtr = oldRefPtr;
+	while (oldRefPtr != NULL) {
+	    refCmdPtr = oldRefPtr->importedCmdPtr;
+	    dataPtr = (ImportedCmdData*)refCmdPtr->objClientData;
+	    dataPtr->realCmdPtr = cmdPtr;
+	    oldRefPtr = oldRefPtr->nextPtr;
+	}
+    }
+
+    /*
+     * We just created a command, so in its namespace and all of its parent
+     * namespaces, it may shadow global commands with the same name. If any
+     * shadowed commands are found, invalidate all cached command references
+     * in the affected namespaces.
+     */
+    
+    TclResetShadowedCmdRefs(interp, cmdPtr);
+    return (Tcl_Command) cmdPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CreateObjCommand --
+ *
+ *	Define a new object-based command in a command table.
+ *
+ * Results:
+ *	The return value is a token for the command, which can
+ *	be used in future calls to Tcl_NameOfCommand.
+ *
+ * Side effects:
+ *	If no command named "cmdName" already exists for interp, one is
+ *	created. Otherwise, if a command does exist, then if the
+ *	object-based Tcl_ObjCmdProc is TclInvokeStringCommand, we assume
+ *	Tcl_CreateCommand was called previously for the same command and
+ *	just set its Tcl_ObjCmdProc to the argument "proc"; otherwise, we
+ *	delete the old command.
+ *
+ *	In the future, during bytecode evaluation when "cmdName" is seen as
+ *	the name of a command by Tcl_EvalObj or Tcl_Eval, the object-based
+ *	Tcl_ObjCmdProc proc will be called. When the command is deleted from
+ *	the table, deleteProc will be called. See the manual entry for
+ *	details on the calling sequence.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Command
+Tcl_CreateObjCommand(interp, cmdName, proc, clientData, deleteProc)
+    Tcl_Interp *interp;		/* Token for command interpreter (returned
+				 * by previous call to Tcl_CreateInterp). */
+    char *cmdName;		/* Name of command. If it contains namespace
+				 * qualifiers, the new command is put in the
+				 * specified namespace; otherwise it is put
+				 * in the global namespace. */
+    Tcl_ObjCmdProc *proc;	/* Object-based procedure to associate with
+				 * name. */
+    ClientData clientData;	/* Arbitrary value to pass to object
+    				 * procedure. */
+    Tcl_CmdDeleteProc *deleteProc;
+				/* If not NULL, gives a procedure to call
+				 * when this command is deleted. */
+{
+    Interp *iPtr = (Interp *) interp;
+    ImportRef *oldRefPtr = NULL;
+    Namespace *nsPtr, *dummy1, *dummy2;
+    Command *cmdPtr, *refCmdPtr;
+    Tcl_HashEntry *hPtr;
+    char *tail;
+    int new;
+    ImportedCmdData *dataPtr;
+
+    if (iPtr->flags & DELETED) {
+	/*
+	 * The interpreter is being deleted.  Don't create any new
+	 * commands;  it's not safe to muck with the interpreter anymore.
+	 */
+
+	return (Tcl_Command) NULL;
+    }
+
+    /*
+     * Determine where the command should reside. If its name contains 
+     * namespace qualifiers, we put it in the specified namespace; 
+     * otherwise, we always put it in the global namespace.
+     */
+
+    if (strstr(cmdName, "::") != NULL) {
+       TclGetNamespaceForQualName(interp, cmdName, (Namespace *) NULL,
+           CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
+       if ((nsPtr == NULL) || (tail == NULL)) {
+	    return (Tcl_Command) NULL;
+	}
+    } else {
+	nsPtr = iPtr->globalNsPtr;
+	tail = cmdName;
+    }
+
+    hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
+    if (!new) {
+	cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
+
+	/*
+	 * Command already exists. If its object-based Tcl_ObjCmdProc is
+	 * TclInvokeStringCommand, we just set its Tcl_ObjCmdProc to the
+	 * argument "proc". Otherwise, we delete the old command. 
+	 */
+
+	if (cmdPtr->objProc == TclInvokeStringCommand) {
+	    cmdPtr->objProc = proc;
+	    cmdPtr->objClientData = clientData;
+            cmdPtr->deleteProc = deleteProc;
+            cmdPtr->deleteData = clientData;
+	    return (Tcl_Command) cmdPtr;
+	}
+
+	/*
+	 * Otherwise, we delete the old command.  Be careful to preserve
+	 * any existing import links so we can restore them down below.
+	 * That way, you can redefine a command and its import status
+	 * will remain intact.
+	 */
+
+	oldRefPtr = cmdPtr->importRefPtr;
+	cmdPtr->importRefPtr = NULL;
+
+	Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
+	hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
+	if (!new) {
+	    /*
+	     * If the deletion callback recreated the command, just throw
+	     * away the new command (if we try to delete it again, we
+	     * could get stuck in an infinite loop).
+	     */
+
+	     ckfree((char *) Tcl_GetHashValue(hPtr));
+	}
+    }
+    cmdPtr = (Command *) ckalloc(sizeof(Command));
+    Tcl_SetHashValue(hPtr, cmdPtr);
+    cmdPtr->hPtr = hPtr;
+    cmdPtr->nsPtr = nsPtr;
+    cmdPtr->refCount = 1;
+    cmdPtr->cmdEpoch = 0;
+    cmdPtr->compileProc = (CompileProc *) NULL;
+    cmdPtr->objProc = proc;
+    cmdPtr->objClientData = clientData;
+    cmdPtr->proc = TclInvokeObjectCommand;
+    cmdPtr->clientData = (ClientData) cmdPtr;
+    cmdPtr->deleteProc = deleteProc;
+    cmdPtr->deleteData = clientData;
+    cmdPtr->deleted = 0;
+    cmdPtr->importRefPtr = NULL;
+
+    /*
+     * Plug in any existing import references found above.  Be sure
+     * to update all of these references to point to the new command.
+     */
+
+    if (oldRefPtr != NULL) {
+	cmdPtr->importRefPtr = oldRefPtr;
+	while (oldRefPtr != NULL) {
+	    refCmdPtr = oldRefPtr->importedCmdPtr;
+	    dataPtr = (ImportedCmdData*)refCmdPtr->objClientData;
+	    dataPtr->realCmdPtr = cmdPtr;
+	    oldRefPtr = oldRefPtr->nextPtr;
+	}
+    }
+    
+    /*
+     * We just created a command, so in its namespace and all of its parent
+     * namespaces, it may shadow global commands with the same name. If any
+     * shadowed commands are found, invalidate all cached command references
+     * in the affected namespaces.
+     */
+    
+    TclResetShadowedCmdRefs(interp, cmdPtr);
+    return (Tcl_Command) cmdPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInvokeStringCommand --
+ *
+ *	"Wrapper" Tcl_ObjCmdProc used to call an existing string-based
+ *	Tcl_CmdProc if no object-based procedure exists for a command. A
+ *	pointer to this procedure is stored as the Tcl_ObjCmdProc in a
+ *	Command structure. It simply turns around and calls the string
+ *	Tcl_CmdProc in the Command structure.
+ *
+ * Results:
+ *	A standard Tcl object result value.
+ *
+ * Side effects:
+ *	Besides those side effects of the called Tcl_CmdProc,
+ *	TclInvokeStringCommand allocates and frees storage.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclInvokeStringCommand(clientData, interp, objc, objv)
+    ClientData clientData;	/* Points to command's Command structure. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    register int objc;		/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    register Command *cmdPtr = (Command *) clientData;
+    register int i;
+    int result;
+
+    /*
+     * This procedure generates an argv array for the string arguments. It
+     * starts out with stack-allocated space but uses dynamically-allocated
+     * storage if needed.
+     */
+
+#define NUM_ARGS 20
+    char *(argStorage[NUM_ARGS]);
+    char **argv = argStorage;
+
+    /*
+     * Create the string argument array "argv". Make sure argv is large
+     * enough to hold the objc arguments plus 1 extra for the zero
+     * end-of-argv word.
+     * THIS FAILS IF ANY ARGUMENT OBJECT CONTAINS AN EMBEDDED NULL.
+     */
+
+    if ((objc + 1) > NUM_ARGS) {
+	argv = (char **) ckalloc((unsigned)(objc + 1) * sizeof(char *));
+    }
+
+    for (i = 0;  i < objc;  i++) {
+	argv[i] = Tcl_GetStringFromObj(objv[i], (int *) NULL);
+    }
+    argv[objc] = 0;
+
+    /*
+     * Invoke the command's string-based Tcl_CmdProc.
+     */
+
+    result = (*cmdPtr->proc)(cmdPtr->clientData, interp, objc, argv);
+
+    /*
+     * Free the argv array if malloc'ed storage was used.
+     */
+
+    if (argv != argStorage) {
+	ckfree((char *) argv);
+    }
+    return result;
+#undef NUM_ARGS
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInvokeObjectCommand --
+ *
+ *	"Wrapper" Tcl_CmdProc used to call an existing object-based
+ *	Tcl_ObjCmdProc if no string-based procedure exists for a command.
+ *	A pointer to this procedure is stored as the Tcl_CmdProc in a
+ *	Command structure. It simply turns around and calls the object
+ *	Tcl_ObjCmdProc in the Command structure.
+ *
+ * Results:
+ *	A standard Tcl string result value.
+ *
+ * Side effects:
+ *	Besides those side effects of the called Tcl_CmdProc,
+ *	TclInvokeStringCommand allocates and frees storage.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclInvokeObjectCommand(clientData, interp, argc, argv)
+    ClientData clientData;	/* Points to command's Command structure. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int argc;			/* Number of arguments. */
+    register char **argv;	/* Argument strings. */
+{
+    Command *cmdPtr = (Command *) clientData;
+    register Tcl_Obj *objPtr;
+    register int i;
+    int length, result;
+
+    /*
+     * This procedure generates an objv array for object arguments that hold
+     * the argv strings. It starts out with stack-allocated space but uses
+     * dynamically-allocated storage if needed.
+     */
+
+#define NUM_ARGS 20
+    Tcl_Obj *(argStorage[NUM_ARGS]);
+    register Tcl_Obj **objv = argStorage;
+
+    /*
+     * Create the object argument array "objv". Make sure objv is large
+     * enough to hold the objc arguments plus 1 extra for the zero
+     * end-of-objv word.
+     */
+
+    if ((argc + 1) > NUM_ARGS) {
+	objv = (Tcl_Obj **)
+	    ckalloc((unsigned)(argc + 1) * sizeof(Tcl_Obj *));
+    }
+
+    for (i = 0;  i < argc;  i++) {
+	length = strlen(argv[i]);
+	TclNewObj(objPtr);
+	TclInitStringRep(objPtr, argv[i], length);
+	Tcl_IncrRefCount(objPtr);
+	objv[i] = objPtr;
+    }
+    objv[argc] = 0;
+
+    /*
+     * Invoke the command's object-based Tcl_ObjCmdProc.
+     */
+
+    result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, argc, objv);
+
+    /*
+     * Move the interpreter's object result to the string result, 
+     * then reset the object result.
+     * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULL BYTES.
+     */
+
+    Tcl_SetResult(interp,
+	    TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL),
+	    TCL_VOLATILE);
+    
+    /*
+     * Decrement the ref counts for the argument objects created above,
+     * then free the objv array if malloc'ed storage was used.
+     */
+
+    for (i = 0;  i < argc;  i++) {
+	objPtr = objv[i];
+	Tcl_DecrRefCount(objPtr);
+    }
+    if (objv != argStorage) {
+	ckfree((char *) objv);
+    }
+    return result;
+#undef NUM_ARGS
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetCommandInfo --
+ *
+ *	Modifies various information about a Tcl command. Note that
+ *	this procedure will not change a command's namespace; use
+ *	Tcl_RenameCommand to do that. Also, the isNativeObjectProc
+ *	member of *infoPtr is ignored.
+ *
+ * Results:
+ *	If cmdName exists in interp, then the information at *infoPtr
+ *	is stored with the command in place of the current information
+ *	and 1 is returned. If the command doesn't exist then 0 is
+ *	returned. 
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_SetCommandInfo(interp, cmdName, infoPtr)
+    Tcl_Interp *interp;			/* Interpreter in which to look
+					 * for command. */
+    char *cmdName;			/* Name of desired command. */
+    Tcl_CmdInfo *infoPtr;		/* Where to store information about
+					 * command. */
+{
+    Tcl_Command cmd;
+    Command *cmdPtr;
+
+    cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
+            /*flags*/ 0);
+    if (cmd == (Tcl_Command) NULL) {
+	return 0;
+    }
+
+    /*
+     * The isNativeObjectProc and nsPtr members of *infoPtr are ignored.
+     */
+    
+    cmdPtr = (Command *) cmd;
+    cmdPtr->proc = infoPtr->proc;
+    cmdPtr->clientData = infoPtr->clientData;
+    if (infoPtr->objProc == (Tcl_ObjCmdProc *) NULL) {
+	cmdPtr->objProc = TclInvokeStringCommand;
+	cmdPtr->objClientData = (ClientData) cmdPtr;
+    } else {
+	cmdPtr->objProc = infoPtr->objProc;
+	cmdPtr->objClientData = infoPtr->objClientData;
+    }
+    cmdPtr->deleteProc = infoPtr->deleteProc;
+    cmdPtr->deleteData = infoPtr->deleteData;
+    return 1;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetCommandInfo --
+ *
+ *	Returns various information about a Tcl command.
+ *
+ * Results:
+ *	If cmdName exists in interp, then *infoPtr is modified to
+ *	hold information about cmdName and 1 is returned.  If the
+ *	command doesn't exist then 0 is returned and *infoPtr isn't
+ *	modified.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetCommandInfo(interp, cmdName, infoPtr)
+    Tcl_Interp *interp;			/* Interpreter in which to look
+					 * for command. */
+    char *cmdName;			/* Name of desired command. */
+    Tcl_CmdInfo *infoPtr;		/* Where to store information about
+					 * command. */
+{
+    Tcl_Command cmd;
+    Command *cmdPtr;
+
+    cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
+            /*flags*/ 0);
+    if (cmd == (Tcl_Command) NULL) {
+	return 0;
+    }
+
+    /*
+     * Set isNativeObjectProc 1 if objProc was registered by a call to
+     * Tcl_CreateObjCommand. Otherwise set it to 0.
+     */
+
+    cmdPtr = (Command *) cmd;
+    infoPtr->isNativeObjectProc =
+	    (cmdPtr->objProc != TclInvokeStringCommand);
+    infoPtr->objProc = cmdPtr->objProc;
+    infoPtr->objClientData = cmdPtr->objClientData;
+    infoPtr->proc = cmdPtr->proc;
+    infoPtr->clientData = cmdPtr->clientData;
+    infoPtr->deleteProc = cmdPtr->deleteProc;
+    infoPtr->deleteData = cmdPtr->deleteData;
+    infoPtr->namespacePtr = (Tcl_Namespace *) cmdPtr->nsPtr;
+    return 1;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetCommandName --
+ *
+ *	Given a token returned by Tcl_CreateCommand, this procedure
+ *	returns the current name of the command (which may have changed
+ *	due to renaming).
+ *
+ * Results:
+ *	The return value is the name of the given command.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_GetCommandName(interp, command)
+    Tcl_Interp *interp;		/* Interpreter containing the command. */
+    Tcl_Command command;	/* Token for command returned by a previous
+				 * call to Tcl_CreateCommand. The command
+				 * must not have been deleted. */
+{
+    Command *cmdPtr = (Command *) command;
+
+    if ((cmdPtr == NULL) || (cmdPtr->hPtr == NULL)) {
+
+	/*
+	 * This should only happen if command was "created" after the
+	 * interpreter began to be deleted, so there isn't really any
+	 * command. Just return an empty string.
+	 */
+
+	return "";
+    }
+    return Tcl_GetHashKey(cmdPtr->hPtr->tablePtr, cmdPtr->hPtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetCommandFullName --
+ *
+ *	Given a token returned by, e.g., Tcl_CreateCommand or
+ *	Tcl_FindCommand, this procedure appends to an object the command's
+ *	full name, qualified by a sequence of parent namespace names. The
+ *	command's fully-qualified name may have changed due to renaming.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The command's fully-qualified name is appended to the string
+ *	representation of objPtr. 
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_GetCommandFullName(interp, command, objPtr)
+    Tcl_Interp *interp;		/* Interpreter containing the command. */
+    Tcl_Command command;	/* Token for command returned by a previous
+				 * call to Tcl_CreateCommand. The command
+				 * must not have been deleted. */
+    Tcl_Obj *objPtr;		/* Points to the object onto which the
+				 * command's full name is appended. */
+
+{
+    Interp *iPtr = (Interp *) interp;
+    register Command *cmdPtr = (Command *) command;
+    char *name;
+
+    /*
+     * Add the full name of the containing namespace, followed by the "::"
+     * separator, and the command name.
+     */
+
+    if (cmdPtr != NULL) {
+	if (cmdPtr->nsPtr != NULL) {
+	    Tcl_AppendToObj(objPtr, cmdPtr->nsPtr->fullName, -1);
+	    if (cmdPtr->nsPtr != iPtr->globalNsPtr) {
+		Tcl_AppendToObj(objPtr, "::", 2);
+	    }
+	}
+	if (cmdPtr->hPtr != NULL) {
+	    name = Tcl_GetHashKey(cmdPtr->hPtr->tablePtr, cmdPtr->hPtr);
+	    Tcl_AppendToObj(objPtr, name, -1);
+	}
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DeleteCommand --
+ *
+ *	Remove the given command from the given interpreter.
+ *
+ * Results:
+ *	0 is returned if the command was deleted successfully.
+ *	-1 is returned if there didn't exist a command by that name.
+ *
+ * Side effects:
+ *	cmdName will no longer be recognized as a valid command for
+ *	interp.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_DeleteCommand(interp, cmdName)
+    Tcl_Interp *interp;		/* Token for command interpreter (returned
+				 * by a previous Tcl_CreateInterp call). */
+    char *cmdName;		/* Name of command to remove. */
+{
+    Tcl_Command cmd;
+
+    /*
+     *  Find the desired command and delete it.
+     */
+
+    cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
+            /*flags*/ 0);
+    if (cmd == (Tcl_Command) NULL) {
+	return -1;
+    }
+    return Tcl_DeleteCommandFromToken(interp, cmd);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DeleteCommandFromToken --
+ *
+ *	Removes the given command from the given interpreter. This procedure
+ *	resembles Tcl_DeleteCommand, but takes a Tcl_Command token instead
+ *	of a command name for efficiency.
+ *
+ * Results:
+ *	0 is returned if the command was deleted successfully.
+ *	-1 is returned if there didn't exist a command by that name.
+ *
+ * Side effects:
+ *	The command specified by "cmd" will no longer be recognized as a
+ *	valid command for "interp".
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_DeleteCommandFromToken(interp, cmd)
+    Tcl_Interp *interp;		/* Token for command interpreter returned by
+				 * a previous call to Tcl_CreateInterp. */
+    Tcl_Command cmd;            /* Token for command to delete. */
+{
+    Interp *iPtr = (Interp *) interp;
+    Command *cmdPtr = (Command *) cmd;
+    ImportRef *refPtr, *nextRefPtr;
+    Tcl_Command importCmd;
+
+    /*
+     * The code here is tricky.  We can't delete the hash table entry
+     * before invoking the deletion callback because there are cases
+     * where the deletion callback needs to invoke the command (e.g.
+     * object systems such as OTcl). However, this means that the
+     * callback could try to delete or rename the command. The deleted
+     * flag allows us to detect these cases and skip nested deletes.
+     */
+
+    if (cmdPtr->deleted) {
+	/*
+	 * Another deletion is already in progress.  Remove the hash
+	 * table entry now, but don't invoke a callback or free the
+	 * command structure.
+	 */
+
+        Tcl_DeleteHashEntry(cmdPtr->hPtr);
+	cmdPtr->hPtr = NULL;
+	return 0;
+    }
+
+    /*
+     * If the command being deleted has a compile procedure, increment the
+     * interpreter's compileEpoch to invalidate its compiled code. This
+     * makes sure that we don't later try to execute old code compiled with
+     * command-specific (i.e., inline) bytecodes for the now-deleted
+     * command. This field is checked in Tcl_EvalObj and ObjInterpProc, and
+     * code whose compilation epoch doesn't match is recompiled.
+     */
+
+    if (cmdPtr->compileProc != NULL) {
+        iPtr->compileEpoch++;
+    }
+
+    cmdPtr->deleted = 1;
+    if (cmdPtr->deleteProc != NULL) {
+	/*
+	 * Delete the command's client data. If this was an imported command
+	 * created when a command was imported into a namespace, this client
+	 * data will be a pointer to a ImportedCmdData structure describing
+	 * the "real" command that this imported command refers to.
+	 */
+	
+	(*cmdPtr->deleteProc)(cmdPtr->deleteData);
+    }
+
+    /*
+     * Bump the command epoch counter. This will invalidate all cached
+     * references that point to this command.
+     */
+    
+    cmdPtr->cmdEpoch++;
+
+    /*
+     * If this command was imported into other namespaces, then imported
+     * commands were created that refer back to this command. Delete these
+     * imported commands now.
+     */
+
+    for (refPtr = cmdPtr->importRefPtr;  refPtr != NULL;
+            refPtr = nextRefPtr) {
+	nextRefPtr = refPtr->nextPtr;
+	importCmd = (Tcl_Command) refPtr->importedCmdPtr;
+        Tcl_DeleteCommandFromToken(interp, importCmd);
+    }
+
+    /*
+     * Don't use hPtr to delete the hash entry here, because it's
+     * possible that the deletion callback renamed the command.
+     * Instead, use cmdPtr->hptr, and make sure that no-one else
+     * has already deleted the hash entry.
+     */
+
+    if (cmdPtr->hPtr != NULL) {
+	Tcl_DeleteHashEntry(cmdPtr->hPtr);
+    }
+
+    /*
+     * Mark the Command structure as no longer valid. This allows
+     * TclExecuteByteCode to recognize when a Command has logically been
+     * deleted and a pointer to this Command structure cached in a CmdName
+     * object is invalid. TclExecuteByteCode will look up the command again
+     * in the interpreter's command hashtable.
+     */
+
+    cmdPtr->objProc = NULL;
+
+    /*
+     * Now free the Command structure, unless there is another reference to
+     * it from a CmdName Tcl object in some ByteCode code sequence. In that
+     * case, delay the cleanup until all references are either discarded
+     * (when a ByteCode is freed) or replaced by a new reference (when a
+     * cached CmdName Command reference is found to be invalid and
+     * TclExecuteByteCode looks up the command in the command hashtable).
+     */
+    
+    TclCleanupCommand(cmdPtr);
+    return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCleanupCommand --
+ *
+ *	This procedure frees up a Command structure unless it is still
+ *	referenced from an interpreter's command hashtable or from a CmdName
+ *	Tcl object representing the name of a command in a ByteCode
+ *	instruction sequence. 
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Memory gets freed unless a reference to the Command structure still
+ *	exists. In that case the cleanup is delayed until the command is
+ *	deleted or when the last ByteCode referring to it is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclCleanupCommand(cmdPtr)
+    register Command *cmdPtr;	/* Points to the Command structure to
+				 * be freed. */
+{
+    cmdPtr->refCount--;
+    if (cmdPtr->refCount <= 0) {
+	ckfree((char *) cmdPtr);
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_Eval --
+ *
+ *	Execute a Tcl command in a string.
+ *
+ * Results:
+ *	The return value is one of the return codes defined in tcl.h
+ *	(such as TCL_OK), and interp->result contains a string value
+ *	to supplement the return code. The value of interp->result
+ *	will persist only until the next call to Tcl_Eval or Tcl_EvalObj:
+ *	you must copy it or lose it!
+ *
+ * Side effects:
+ *	The string is compiled to produce a ByteCode object that holds the
+ *	command's bytecode instructions. However, this ByteCode object is
+ *	lost after executing the command. The command's execution will
+ *	almost certainly have side effects. interp->termOffset is set to the
+ *	offset of the character in "string" just after the last one
+ *	successfully compiled or executed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_Eval(interp, string)
+    Tcl_Interp *interp;		/* Token for command interpreter (returned
+				 * by previous call to Tcl_CreateInterp). */
+    char *string;		/* Pointer to TCL command to execute. */
+{
+    register Tcl_Obj *cmdPtr;
+    int length = strlen(string);
+    int result;
+
+    if (length > 0) {
+	/*
+	 * Initialize a Tcl object from the command string.
+	 */
+
+	TclNewObj(cmdPtr);
+	TclInitStringRep(cmdPtr, string, length);
+	Tcl_IncrRefCount(cmdPtr);
+
+	/*
+	 * Compile and execute the bytecodes.
+	 */
+    
+	result = Tcl_EvalObj(interp, cmdPtr);
+
+	/*
+	 * Move the interpreter's object result to the string result, 
+	 * then reset the object result.
+	 * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS.
+	 */
+
+	Tcl_SetResult(interp,
+	        TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL),
+	        TCL_VOLATILE);
+
+	/*
+	 * Discard the Tcl object created to hold the command and its code.
+	 */
+	
+	Tcl_DecrRefCount(cmdPtr);	
+    } else {
+	/*
+	 * An empty string. Just reset the interpreter's result.
+	 */
+
+	Tcl_ResetResult(interp);
+	result = TCL_OK;
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_EvalObj --
+ *
+ *	Execute Tcl commands stored in a Tcl object. These commands are
+ *	compiled into bytecodes if necessary.
+ *
+ * Results:
+ *	The return value is one of the return codes defined in tcl.h
+ *	(such as TCL_OK), and the interpreter's result contains a value
+ *	to supplement the return code.
+ *
+ * Side effects:
+ *	The object is converted, if necessary, to a ByteCode object that
+ *	holds the bytecode instructions for the commands. Executing the
+ *	commands will almost certainly have side effects that depend
+ *	on those commands.
+ *
+ *	Just as in Tcl_Eval, interp->termOffset is set to the offset of the
+ *	last character executed in the objPtr's string.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#undef Tcl_EvalObj
+
+int
+Tcl_EvalObj(interp, objPtr)
+    Tcl_Interp *interp;			/* Token for command interpreter
+					 * (returned by a previous call to
+					 * Tcl_CreateInterp). */
+    Tcl_Obj *objPtr;			/* Pointer to object containing
+					 * commands to execute. */
+{
+    register Interp *iPtr = (Interp *) interp;
+    int flags;				/* Interp->evalFlags value when the
+					 * procedure was called. */
+    register ByteCode* codePtr;		/* Tcl Internal type of bytecode. */
+    int oldCount = iPtr->cmdCount;	/* Used to tell whether any commands
+					 * at all were executed. */
+    int numSrcChars;
+    register int result;
+    Namespace *namespacePtr;
+
+    /*
+     * Reset both the interpreter's string and object results and clear out
+     * any error information. This makes sure that we return an empty
+     * result if there are no commands in the command string.
+     */
+
+    Tcl_ResetResult(interp);
+
+    /*
+     * Check depth of nested calls to Tcl_Eval:  if this gets too large,
+     * it's probably because of an infinite loop somewhere.
+     */
+
+    iPtr->numLevels++;
+    if (iPtr->numLevels > iPtr->maxNestingDepth) {
+	iPtr->numLevels--;
+	Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		"too many nested calls to Tcl_EvalObj (infinite loop?)", -1);
+	return TCL_ERROR;
+    }    
+
+    /*
+     * If the interpreter has been deleted, return an error.
+     */
+    
+    if (iPtr->flags & DELETED) {
+	Tcl_ResetResult(interp);
+	Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	        "attempt to call eval in deleted interpreter", -1);
+	Tcl_SetErrorCode(interp, "CORE", "IDELETE",
+	        "attempt to call eval in deleted interpreter", (char *) NULL);
+	iPtr->numLevels--;
+	return TCL_ERROR;
+    }
+
+    /*
+     * Get the ByteCode from the object. If it exists, make sure it hasn't
+     * been invalidated by, e.g., someone redefining a command with a
+     * compile procedure (this might make the compiled code wrong). If
+     * necessary, convert the object to be a ByteCode object and compile it.
+     * Also, if the code was compiled in/for a different interpreter,
+     * or for a different namespace, or for the same namespace but
+     * with different name resolution rules, we recompile it.
+     *
+     * Precompiled objects, however, are immutable and therefore
+     * they are not recompiled, even if the epoch has changed.
+     */
+
+    if (iPtr->varFramePtr != NULL) {
+        namespacePtr = iPtr->varFramePtr->nsPtr;
+    } else {
+        namespacePtr = iPtr->globalNsPtr;
+    }
+
+    if (objPtr->typePtr == &tclByteCodeType) {
+	codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
+	
+	if ((codePtr->iPtr != iPtr)
+	        || (codePtr->compileEpoch != iPtr->compileEpoch)
+	        || (codePtr->nsPtr != namespacePtr)
+	        || (codePtr->nsEpoch != namespacePtr->resolverEpoch)) {
+            if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
+                if (codePtr->iPtr != iPtr) {
+                    panic("Tcl_EvalObj: compiled script jumped interps");
+                }
+	        codePtr->compileEpoch = iPtr->compileEpoch;
+            } else {
+                tclByteCodeType.freeIntRepProc(objPtr);
+            }
+	}
+    }
+    if (objPtr->typePtr != &tclByteCodeType) {
+	/*
+	 * First reset any error line number information.
+	 */
+	
+	iPtr->errorLine = 1;   /* no correct line # information yet */
+	result = tclByteCodeType.setFromAnyProc(interp, objPtr);
+	if (result != TCL_OK) {
+	    iPtr->numLevels--;
+	    return result;
+	}
+    }
+    codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
+
+    /*
+     * Extract then reset the compilation flags in the interpreter.
+     * Resetting the flags must be done after any compilation.
+     */
+
+    flags = iPtr->evalFlags;
+    iPtr->evalFlags = 0;
+
+    /*
+     * Execute the commands. If the code was compiled from an empty string,
+     * don't bother executing the code.
+     */
+
+    numSrcChars = codePtr->numSrcChars;
+    if ((numSrcChars > 0) || (codePtr->flags & TCL_BYTECODE_PRECOMPILED)) {
+	/*
+	 * Increment the code's ref count while it is being executed. If
+	 * afterwards no references to it remain, free the code.
+	 */
+	
+	codePtr->refCount++;
+	result = TclExecuteByteCode(interp, codePtr);
+	codePtr->refCount--;
+	if (codePtr->refCount <= 0) {
+	    TclCleanupByteCode(codePtr);
+	}
+    } else {
+	Tcl_ResetResult(interp);
+	result = TCL_OK;
+    }
+
+    /*
+     * If no commands at all were executed, check for asynchronous
+     * handlers so that they at least get one change to execute.
+     * This is needed to handle event loops written in Tcl with
+     * empty bodies.
+     */
+
+    if ((oldCount == iPtr->cmdCount) && (Tcl_AsyncReady())) {
+	result = Tcl_AsyncInvoke(interp, result);
+    }
+
+    /*
+     * Free up any extra resources that were allocated.
+     */
+
+    iPtr->numLevels--;
+    if (iPtr->numLevels == 0) {
+	if (result == TCL_RETURN) {
+	    result = TclUpdateReturnInfo(iPtr);
+	}
+	if ((result != TCL_OK) && (result != TCL_ERROR)
+		&& !(flags & TCL_ALLOW_EXCEPTIONS)) {
+	    Tcl_ResetResult(interp);
+	    if (result == TCL_BREAK) {
+		Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		        "invoked \"break\" outside of a loop", -1);
+	    } else if (result == TCL_CONTINUE) {
+		Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		        "invoked \"continue\" outside of a loop", -1);
+	    } else {
+		char buf[50];
+		sprintf(buf, "command returned bad code: %d", result);
+		Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
+	    }
+	    result = TCL_ERROR;
+	}
+    }
+
+    /*
+     * If an error occurred, record information about what was being
+     * executed when the error occurred.
+     */
+
+    if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
+	char buf[200];
+	char *ellipsis = "";
+	char *bytes;
+	int length;
+
+	/*
+	 * Figure out how much of the command to print in the error
+	 * message (up to a certain number of characters, or up to
+	 * the first new-line).
+	 * THIS FAILS IF THE OBJECT'S STRING REP CONTAINS A NULL.
+	 */
+
+	bytes = Tcl_GetStringFromObj(objPtr, &length);
+	length = TclMin(numSrcChars, length);
+	if (length > 150) {
+	    length = 150;
+	    ellipsis = " ...";
+	}
+
+	if (!(iPtr->flags & ERR_IN_PROGRESS)) {
+	    sprintf(buf, "\n    while executing\n\"%.*s%s\"",
+		    length, bytes, ellipsis);
+	} else {
+	    sprintf(buf, "\n    invoked from within\n\"%.*s%s\"",
+		    length, bytes, ellipsis);
+	}
+	Tcl_AddObjErrorInfo(interp, buf, -1);
+    }
+
+    /*
+     * Set the interpreter's termOffset member to the offset of the
+     * character just after the last one executed. We approximate the offset
+     * of the last character executed by using the number of characters
+     * compiled.
+     */
+
+    iPtr->termOffset = numSrcChars;
+    iPtr->flags &= ~ERR_ALREADY_LOGGED;
+    return result;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean --
+ *
+ *	Procedures to evaluate an expression and return its value in a
+ *	particular form.
+ *
+ * Results:
+ *	Each of the procedures below returns a standard Tcl result. If an
+ *	error occurs then an error message is left in interp->result.
+ *	Otherwise the value of the expression, in the appropriate form, is
+ *	stored at *ptr. If the expression had a result that was
+ *	incompatible with the desired form then an error is returned.
+ *
+ * Side effects:
+ *	None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tcl_ExprLong(interp, string, ptr)
+    Tcl_Interp *interp;		/* Context in which to evaluate the
+				 * expression. */
+    char *string;		/* Expression to evaluate. */
+    long *ptr;			/* Where to store result. */
+{
+    register Tcl_Obj *exprPtr;
+    Tcl_Obj *resultPtr;
+    int length = strlen(string);
+    int result = TCL_OK;
+
+    if (length > 0) {
+	exprPtr = Tcl_NewStringObj(string, length);
+	Tcl_IncrRefCount(exprPtr);
+	result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
+	if (result == TCL_OK) {
+	    /*
+	     * Store an integer based on the expression result.
+	     */
+	    
+	    if (resultPtr->typePtr == &tclIntType) {
+		*ptr = resultPtr->internalRep.longValue;
+	    } else if (resultPtr->typePtr == &tclDoubleType) {
+		*ptr = (long) resultPtr->internalRep.doubleValue;
+	    } else {
+		Tcl_SetResult(interp,
+		        "expression didn't have numeric value", TCL_STATIC);
+		result = TCL_ERROR;
+	    }
+	    Tcl_DecrRefCount(resultPtr);  /* discard the result object */
+	} else {
+	    /*
+	     * Move the interpreter's object result to the string result, 
+	     * then reset the object result.
+	     * FAILS IF OBJECT RESULT'S STRING REPRESENTATION HAS NULLS.
+	     */
+
+	    Tcl_SetResult(interp,
+	            TclGetStringFromObj(Tcl_GetObjResult(interp),
+		            (int *) NULL),
+	            TCL_VOLATILE);
+	}
+	Tcl_DecrRefCount(exprPtr);  /* discard the expression object */	
+    } else {
+	/*
+	 * An empty string. Just set the result integer to 0.
+	 */
+	
+	*ptr = 0;
+    }
+    return result;
+}
+
+int
+Tcl_ExprDouble(interp, string, ptr)
+    Tcl_Interp *interp;		/* Context in which to evaluate the
+				 * expression. */
+    char *string;		/* Expression to evaluate. */
+    double *ptr;		/* Where to store result. */
+{
+    register Tcl_Obj *exprPtr;
+    Tcl_Obj *resultPtr;
+    int length = strlen(string);
+    int result = TCL_OK;
+
+    if (length > 0) {
+	exprPtr = Tcl_NewStringObj(string, length);
+	Tcl_IncrRefCount(exprPtr);
+	result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
+	if (result == TCL_OK) {
+	    /*
+	     * Store a double  based on the expression result.
+	     */
+	    
+	    if (resultPtr->typePtr == &tclIntType) {
+		*ptr = (double) resultPtr->internalRep.longValue;
+	    } else if (resultPtr->typePtr == &tclDoubleType) {
+		*ptr = resultPtr->internalRep.doubleValue;
+	    } else {
+		Tcl_SetResult(interp,
+		        "expression didn't have numeric value", TCL_STATIC);
+		result = TCL_ERROR;
+	    }
+	    Tcl_DecrRefCount(resultPtr);  /* discard the result object */
+	} else {
+	    /*
+	     * Move the interpreter's object result to the string result, 
+	     * then reset the object result.
+	     * FAILS IF OBJECT RESULT'S STRING REPRESENTATION HAS NULLS.
+	     */
+
+	    Tcl_SetResult(interp,
+	            TclGetStringFromObj(Tcl_GetObjResult(interp),
+		            (int *) NULL),
+	            TCL_VOLATILE);
+	}
+	Tcl_DecrRefCount(exprPtr);  /* discard the expression object */
+    } else {
+	/*
+	 * An empty string. Just set the result double to 0.0.
+	 */
+	
+	*ptr = 0.0;
+    }
+    return result;
+}
+
+int
+Tcl_ExprBoolean(interp, string, ptr)
+    Tcl_Interp *interp;		/* Context in which to evaluate the
+			         * expression. */
+    char *string;		/* Expression to evaluate. */
+    int *ptr;			/* Where to store 0/1 result. */
+{
+    register Tcl_Obj *exprPtr;
+    Tcl_Obj *resultPtr;
+    int length = strlen(string);
+    int result = TCL_OK;
+
+    if (length > 0) {
+	exprPtr = Tcl_NewStringObj(string, length);
+	Tcl_IncrRefCount(exprPtr);
+	result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
+	if (result == TCL_OK) {
+	    /*
+	     * Store a boolean based on the expression result.
+	     */
+	    
+	    if (resultPtr->typePtr == &tclIntType) {
+		*ptr = (resultPtr->internalRep.longValue != 0);
+	    } else if (resultPtr->typePtr == &tclDoubleType) {
+		*ptr = (resultPtr->internalRep.doubleValue != 0.0);
+	    } else {
+		result = Tcl_GetBooleanFromObj(interp, resultPtr, ptr);
+	    }
+	    Tcl_DecrRefCount(resultPtr);  /* discard the result object */
+	}
+	if (result != TCL_OK) {
+	    /*
+	     * Move the interpreter's object result to the string result, 
+	     * then reset the object result.
+	     * FAILS IF OBJECT RESULT'S STRING REPRESENTATION HAS NULLS.
+	     */
+
+	    Tcl_SetResult(interp,
+	            TclGetStringFromObj(Tcl_GetObjResult(interp),
+		            (int *) NULL),
+	            TCL_VOLATILE);
+	}
+	Tcl_DecrRefCount(exprPtr); /* discard the expression object */
+    } else {
+	/*
+	 * An empty string. Just set the result boolean to 0 (false).
+	 */
+	
+	*ptr = 0;
+    }
+    return result;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tcl_ExprLongObj, Tcl_ExprDoubleObj, Tcl_ExprBooleanObj --
+ *
+ *	Procedures to evaluate an expression in an object and return its
+ *	value in a particular form.
+ *
+ * Results:
+ *	Each of the procedures below returns a standard Tcl result
+ *	object. If an error occurs then an error message is left in the
+ *	interpreter's result. Otherwise the value of the expression, in the
+ *	appropriate form, is stored at *ptr. If the expression had a result
+ *	that was incompatible with the desired form then an error is
+ *	returned.
+ *
+ * Side effects:
+ *	None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tcl_ExprLongObj(interp, objPtr, ptr)
+    Tcl_Interp *interp;			/* Context in which to evaluate the
+					 * expression. */
+    register Tcl_Obj *objPtr;		/* Expression to evaluate. */
+    long *ptr;				/* Where to store long result. */
+{
+    Tcl_Obj *resultPtr;
+    int result;
+
+    result = Tcl_ExprObj(interp, objPtr, &resultPtr);
+    if (result == TCL_OK) {
+	if (resultPtr->typePtr == &tclIntType) {
+	    *ptr = resultPtr->internalRep.longValue;
+	} else if (resultPtr->typePtr == &tclDoubleType) {
+	    *ptr = (long) resultPtr->internalRep.doubleValue;
+	} else {
+	    result = Tcl_GetLongFromObj(interp, resultPtr, ptr);
+	    if (result != TCL_OK) {
+		return result;
+	    }
+	}
+	Tcl_DecrRefCount(resultPtr);  /* discard the result object */
+    }
+    return result;
+}
+
+int
+Tcl_ExprDoubleObj(interp, objPtr, ptr)
+    Tcl_Interp *interp;			/* Context in which to evaluate the
+					 * expression. */
+    register Tcl_Obj *objPtr;		/* Expression to evaluate. */
+    double *ptr;			/* Where to store double result. */
+{
+    Tcl_Obj *resultPtr;
+    int result;
+
+    result = Tcl_ExprObj(interp, objPtr, &resultPtr);
+    if (result == TCL_OK) {
+	if (resultPtr->typePtr == &tclIntType) {
+	    *ptr = (double) resultPtr->internalRep.longValue;
+	} else if (resultPtr->typePtr == &tclDoubleType) {
+	    *ptr = resultPtr->internalRep.doubleValue;
+	} else {
+	    result = Tcl_GetDoubleFromObj(interp, resultPtr, ptr);
+	    if (result != TCL_OK) {
+		return result;
+	    }
+	}
+	Tcl_DecrRefCount(resultPtr);  /* discard the result object */
+    }
+    return result;
+}
+
+int
+Tcl_ExprBooleanObj(interp, objPtr, ptr)
+    Tcl_Interp *interp;			/* Context in which to evaluate the
+					 * expression. */
+    register Tcl_Obj *objPtr;		/* Expression to evaluate. */
+    int *ptr;				/* Where to store 0/1 result. */
+{
+    Tcl_Obj *resultPtr;
+    int result;
+
+    result = Tcl_ExprObj(interp, objPtr, &resultPtr);
+    if (result == TCL_OK) {
+	if (resultPtr->typePtr == &tclIntType) {
+	    *ptr = (resultPtr->internalRep.longValue != 0);
+	} else if (resultPtr->typePtr == &tclDoubleType) {
+	    *ptr = (resultPtr->internalRep.doubleValue != 0.0);
+	} else {
+	    result = Tcl_GetBooleanFromObj(interp, resultPtr, ptr);
+	    if (result != TCL_OK) {
+		return result;
+	    }
+	}
+	Tcl_DecrRefCount(resultPtr);  /* discard the result object */
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInvoke --
+ *
+ *	Invokes a Tcl command, given an argv/argc, from either the
+ *	exposed or the hidden sets of commands in the given interpreter.
+ *	NOTE: The command is invoked in the current stack frame of
+ *	the interpreter, thus it can modify local variables.
+ *
+ * Results:
+ *	A standard Tcl result.
+ *
+ * Side effects:
+ *	Whatever the command does.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclInvoke(interp, argc, argv, flags)
+    Tcl_Interp *interp;		/* Where to invoke the command. */
+    int argc;			/* Count of args. */
+    register char **argv;	/* The arg strings; argv[0] is the name of
+                                 * the command to invoke. */
+    int flags;			/* Combination of flags controlling the
+				 * call: TCL_INVOKE_HIDDEN and
+				 * TCL_INVOKE_NO_UNKNOWN. */
+{
+    register Tcl_Obj *objPtr;
+    register int i;
+    int length, result;
+
+    /*
+     * This procedure generates an objv array for object arguments that hold
+     * the argv strings. It starts out with stack-allocated space but uses
+     * dynamically-allocated storage if needed.
+     */
+
+#define NUM_ARGS 20
+    Tcl_Obj *(objStorage[NUM_ARGS]);
+    register Tcl_Obj **objv = objStorage;
+
+    /*
+     * Create the object argument array "objv". Make sure objv is large
+     * enough to hold the objc arguments plus 1 extra for the zero
+     * end-of-objv word.
+     */
+
+    if ((argc + 1) > NUM_ARGS) {
+	objv = (Tcl_Obj **)
+	    ckalloc((unsigned)(argc + 1) * sizeof(Tcl_Obj *));
+    }
+
+    for (i = 0;  i < argc;  i++) {
+	length = strlen(argv[i]);
+	objv[i] = Tcl_NewStringObj(argv[i], length);
+	Tcl_IncrRefCount(objv[i]);
+    }
+    objv[argc] = 0;
+
+    /*
+     * Use TclObjInterpProc to actually invoke the command.
+     */
+
+    result = TclObjInvoke(interp, argc, objv, flags);
+
+    /*
+     * Move the interpreter's object result to the string result, 
+     * then reset the object result.
+     * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS.
+     */
+    
+    Tcl_SetResult(interp,
+	    TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL),
+	    TCL_VOLATILE);
+
+    /*
+     * Decrement the ref counts on the objv elements since we are done
+     * with them.
+     */
+
+    for (i = 0;  i < argc;  i++) {
+	objPtr = objv[i];
+	Tcl_DecrRefCount(objPtr);
+    }
+    
+    /*
+     * Free the objv array if malloc'ed storage was used.
+     */
+
+    if (objv != objStorage) {
+	ckfree((char *) objv);
+    }
+    return result;
+#undef NUM_ARGS
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGlobalInvoke --
+ *
+ *	Invokes a Tcl command, given an argv/argc, from either the
+ *	exposed or hidden sets of commands in the given interpreter.
+ *	NOTE: The command is invoked in the global stack frame of
+ *	the interpreter, thus it cannot see any current state on
+ *	the stack for that interpreter.
+ *
+ * Results:
+ *	A standard Tcl result.
+ *
+ * Side effects:
+ *	Whatever the command does.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclGlobalInvoke(interp, argc, argv, flags)
+    Tcl_Interp *interp;		/* Where to invoke the command. */
+    int argc;			/* Count of args. */
+    register char **argv;	/* The arg strings; argv[0] is the name of
+                                 * the command to invoke. */
+    int flags;			/* Combination of flags controlling the
+				 * call: TCL_INVOKE_HIDDEN and
+				 * TCL_INVOKE_NO_UNKNOWN. */
+{
+    register Interp *iPtr = (Interp *) interp;
+    int result;
+    CallFrame *savedVarFramePtr;
+
+    savedVarFramePtr = iPtr->varFramePtr;
+    iPtr->varFramePtr = NULL;
+    result = TclInvoke(interp, argc, argv, flags);
+    iPtr->varFramePtr = savedVarFramePtr;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclObjInvokeGlobal --
+ *
+ *	Object version: Invokes a Tcl command, given an objv/objc, from
+ *	either the exposed or hidden set of commands in the given
+ *	interpreter.
+ *	NOTE: The command is invoked in the global stack frame of the
+ *	interpreter, thus it cannot see any current state on the
+ *	stack of that interpreter.
+ *
+ * Results:
+ *	A standard Tcl result.
+ *
+ * Side effects:
+ *	Whatever the command does.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclObjInvokeGlobal(interp, objc, objv, flags)
+    Tcl_Interp *interp;		/* Interpreter in which command is
+				 * to be invoked. */
+    int objc;			/* Count of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument value objects; objv[0]
+				 * points to the name of the
+				 * command to invoke. */
+    int flags;			/* Combination of flags controlling
+                                 * the call: TCL_INVOKE_HIDDEN and
+                                 * TCL_INVOKE_NO_UNKNOWN. */
+{
+    register Interp *iPtr = (Interp *) interp;
+    int result;
+    CallFrame *savedVarFramePtr;
+
+    savedVarFramePtr = iPtr->varFramePtr;
+    iPtr->varFramePtr = NULL;
+    result = TclObjInvoke(interp, objc, objv, flags);
+    iPtr->varFramePtr = savedVarFramePtr;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclObjInvoke --
+ *
+ *	Invokes a Tcl command, given an objv/objc, from either the
+ *	exposed or the hidden sets of commands in the given interpreter.
+ *
+ * Results:
+ *	A standard Tcl object result.
+ *
+ * Side effects:
+ *	Whatever the command does.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclObjInvoke(interp, objc, objv, flags)
+    Tcl_Interp *interp;		/* Interpreter in which command is
+				 * to be invoked. */
+    int objc;			/* Count of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument value objects; objv[0]
+				 * points to the name of the
+				 * command to invoke. */
+    int flags;			/* Combination of flags controlling
+                                 * the call: TCL_INVOKE_HIDDEN and
+                                 * TCL_INVOKE_NO_UNKNOWN. */
+{
+    register Interp *iPtr = (Interp *) interp;
+    Tcl_HashTable *hTblPtr;	/* Table of hidden commands. */
+    char *cmdName;		/* Name of the command from objv[0]. */
+    register Tcl_HashEntry *hPtr;
+    Tcl_Command cmd;
+    Command *cmdPtr;
+    int localObjc;		/* Used to invoke "unknown" if the */
+    Tcl_Obj **localObjv = NULL;	/* command is not found. */
+    register int i;
+    int length, result;
+    char *bytes;
+
+    if (interp == (Tcl_Interp *) NULL) {
+        return TCL_ERROR;
+    }
+
+    if ((objc < 1) || (objv == (Tcl_Obj **) NULL)) {
+        Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	        "illegal argument vector", -1);
+        return TCL_ERROR;
+    }
+
+    /*
+     * THE FOLLOWING CODE FAILS IF THE STRING REP CONTAINS NULLS.
+     */
+    
+    cmdName = Tcl_GetStringFromObj(objv[0], (int *) NULL);
+    if (flags & TCL_INVOKE_HIDDEN) {
+        /*
+         * Find the table of hidden commands; error out if none.
+         */
+
+        hTblPtr = (Tcl_HashTable *)
+	        Tcl_GetAssocData(interp, "tclHiddenCmds", NULL);
+        if (hTblPtr == (Tcl_HashTable *) NULL) {
+            badhiddenCmdToken:
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		     "invalid hidden command name \"", cmdName, "\"",
+		     (char *) NULL);
+            return TCL_ERROR;
+        }
+        hPtr = Tcl_FindHashEntry(hTblPtr, cmdName);
+
+        /*
+         * We never invoke "unknown" for hidden commands.
+         */
+        
+        if (hPtr == NULL) {
+            goto badhiddenCmdToken;
+        }
+	cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
+    } else {
+	cmdPtr = NULL;
+	cmd = Tcl_FindCommand(interp, cmdName,
+	        (Tcl_Namespace *) NULL, /*flags*/ TCL_GLOBAL_ONLY);
+        if (cmd != (Tcl_Command) NULL) {
+	    cmdPtr = (Command *) cmd;
+        }
+	if (cmdPtr == NULL) {
+            if (!(flags & TCL_INVOKE_NO_UNKNOWN)) {
+		cmd = Tcl_FindCommand(interp, "unknown",
+                        (Tcl_Namespace *) NULL, /*flags*/ TCL_GLOBAL_ONLY);
+		if (cmd != (Tcl_Command) NULL) {
+	            cmdPtr = (Command *) cmd;
+                }
+                if (cmdPtr != NULL) {
+                    localObjc = (objc + 1);
+                    localObjv = (Tcl_Obj **)
+			ckalloc((unsigned) (sizeof(Tcl_Obj *) * localObjc));
+		    localObjv[0] = Tcl_NewStringObj("unknown", -1);
+		    Tcl_IncrRefCount(localObjv[0]);
+                    for (i = 0;  i < objc;  i++) {
+                        localObjv[i+1] = objv[i];
+                    }
+                    objc = localObjc;
+                    objv = localObjv;
+                }
+            }
+
+            /*
+             * Check again if we found the command. If not, "unknown" is
+             * not present and we cannot help, or the caller said not to
+             * call "unknown" (they specified TCL_INVOKE_NO_UNKNOWN).
+             */
+
+            if (cmdPtr == NULL) {
+		Tcl_ResetResult(interp);
+		Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+			"invalid command name \"",  cmdName, "\"", 
+			 (char *) NULL);
+                return TCL_ERROR;
+            }
+        }
+    }
+
+    /*
+     * Invoke the command procedure. First reset the interpreter's string
+     * and object results to their default empty values since they could
+     * have gotten changed by earlier invocations.
+     */
+
+    Tcl_ResetResult(interp);
+    iPtr->cmdCount++;
+    result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, objc, objv);
+
+    /*
+     * If an error occurred, record information about what was being
+     * executed when the error occurred.
+     */
+
+    if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
+        Tcl_DString ds;
+        
+        Tcl_DStringInit(&ds);
+        if (!(iPtr->flags & ERR_IN_PROGRESS)) {
+            Tcl_DStringAppend(&ds, "\n    while invoking\n\"", -1);
+        } else {
+            Tcl_DStringAppend(&ds, "\n    invoked from within\n\"", -1);
+        }
+        for (i = 0;  i < objc;  i++) {
+	    bytes = Tcl_GetStringFromObj(objv[i], &length);
+            Tcl_DStringAppend(&ds, bytes, length);
+            if (i < (objc - 1)) {
+                Tcl_DStringAppend(&ds, " ", -1);
+            } else if (Tcl_DStringLength(&ds) > 100) {
+                Tcl_DStringSetLength(&ds, 100);
+                Tcl_DStringAppend(&ds, "...", -1);
+                break;
+            }
+        }
+        
+        Tcl_DStringAppend(&ds, "\"", -1);
+        Tcl_AddObjErrorInfo(interp, Tcl_DStringValue(&ds), -1);
+        Tcl_DStringFree(&ds);
+	iPtr->flags &= ~ERR_ALREADY_LOGGED;
+    }
+
+    /*
+     * Free any locally allocated storage used to call "unknown".
+     */
+
+    if (localObjv != (Tcl_Obj **) NULL) {
+        ckfree((char *) localObjv);
+    }
+    return result;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tcl_ExprString --
+ *
+ *	Evaluate an expression in a string and return its value in string
+ *	form.
+ *
+ * Results:
+ *	A standard Tcl result. If the result is TCL_OK, then the
+ *	interpreter's result is set to the string value of the
+ *	expression. If the result is TCL_OK, then interp->result
+ *	contains an error message.
+ *
+ * Side effects:
+ *	A Tcl object is allocated to hold a copy of the expression string.
+ *	This expression object is passed to Tcl_ExprObj and then
+ *	deallocated.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tcl_ExprString(interp, string)
+    Tcl_Interp *interp;		/* Context in which to evaluate the
+				 * expression. */
+    char *string;		/* Expression to evaluate. */
+{
+    register Tcl_Obj *exprPtr;
+    Tcl_Obj *resultPtr;
+    int length = strlen(string);
+    char buf[100];
+    int result = TCL_OK;
+
+    if (length > 0) {
+	TclNewObj(exprPtr);
+	TclInitStringRep(exprPtr, string, length);
+	Tcl_IncrRefCount(exprPtr);
+
+	result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
+	if (result == TCL_OK) {
+	    /*
+	     * Set the interpreter's string result from the result object.
+	     */
+	    
+	    if (resultPtr->typePtr == &tclIntType) {
+		sprintf(buf, "%ld", resultPtr->internalRep.longValue);
+		Tcl_SetResult(interp, buf, TCL_VOLATILE);
+	    } else if (resultPtr->typePtr == &tclDoubleType) {
+		Tcl_PrintDouble((Tcl_Interp *) NULL,
+		        resultPtr->internalRep.doubleValue, buf);
+		Tcl_SetResult(interp, buf, TCL_VOLATILE);
+	    } else {
+		/*
+		 * Set interpreter's string result from the result object.
+		 * FAILS IF OBJECT RESULT'S STRING REPRESENTATION HAS NULLS.
+		 */
+	    
+		Tcl_SetResult(interp,
+	                TclGetStringFromObj(resultPtr, (int *) NULL),
+	                TCL_VOLATILE);
+	    }
+	    Tcl_DecrRefCount(resultPtr);  /* discard the result object */
+	} else {
+	    /*
+	     * Move the interpreter's object result to the string result, 
+	     * then reset the object result.
+	     * FAILS IF OBJECT RESULT'S STRING REPRESENTATION HAS NULLS.
+	     */
+	    
+	    Tcl_SetResult(interp,
+	            TclGetStringFromObj(Tcl_GetObjResult(interp),
+			    (int *) NULL),
+	            TCL_VOLATILE);
+	}
+	Tcl_DecrRefCount(exprPtr); /* discard the expression object */
+    } else {
+	/*
+	 * An empty string. Just set the interpreter's result to 0.
+	 */
+	
+	Tcl_SetResult(interp, "0", TCL_VOLATILE);
+    }
+    return result;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tcl_ExprObj --
+ *
+ *	Evaluate an expression in a Tcl_Obj.
+ *
+ * Results:
+ *	A standard Tcl object result. If the result is other than TCL_OK,
+ *	then the interpreter's result contains an error message. If the
+ *	result is TCL_OK, then a pointer to the expression's result value
+ *	object is stored in resultPtrPtr. In that case, the object's ref
+ *	count is incremented to reflect the reference returned to the
+ *	caller; the caller is then responsible for the resulting object
+ *	and must, for example, decrement the ref count when it is finished
+ *	with the object.
+ *
+ * Side effects:
+ *	Any side effects caused by subcommands in the expression, if any.
+ *	The interpreter result is not modified unless there is an error.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tcl_ExprObj(interp, objPtr, resultPtrPtr)
+    Tcl_Interp *interp;		/* Context in which to evaluate the
+				 * expression. */
+    register Tcl_Obj *objPtr;	/* Points to Tcl object containing
+				 * expression to evaluate. */
+    Tcl_Obj **resultPtrPtr;	/* Where the Tcl_Obj* that is the expression
+				 * result is stored if no errors occur. */
+{
+    Interp *iPtr = (Interp *) interp;
+    CompileEnv compEnv;		/* Compilation environment structure
+				 * allocated in frame. */
+    register ByteCode *codePtr = NULL;
+    				/* Tcl Internal type of bytecode.
+				 * Initialized to avoid compiler warning. */
+    AuxData *auxDataPtr;
+    Interp dummy;
+    Tcl_Obj *saveObjPtr;
+    char *string;
+    int result;
+    int i;
+
+    /*
+     * Get the ByteCode from the object. If it exists, make sure it hasn't
+     * been invalidated by, e.g., someone redefining a command with a
+     * compile procedure (this might make the compiled code wrong). If
+     * necessary, convert the object to be a ByteCode object and compile it.
+     * Also, if the code was compiled in/for a different interpreter, we
+     * recompile it.
+     *
+     * Precompiled expressions, however, are immutable and therefore
+     * they are not recompiled, even if the epoch has changed.
+     *
+     * THIS FAILS IF THE OBJECT'S STRING REP HAS A NULL BYTE.
+     */
+
+    if (objPtr->typePtr == &tclByteCodeType) {
+	codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
+	if ((codePtr->iPtr != iPtr)
+	        || (codePtr->compileEpoch != iPtr->compileEpoch)) {
+            if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
+                if (codePtr->iPtr != iPtr) {
+                    panic("Tcl_ExprObj: compiled expression jumped interps");
+                }
+	        codePtr->compileEpoch = iPtr->compileEpoch;
+            } else {
+                tclByteCodeType.freeIntRepProc(objPtr);
+                objPtr->typePtr = (Tcl_ObjType *) NULL;
+            }
+	}
+    }
+    if (objPtr->typePtr != &tclByteCodeType) {
+	int length;
+	string = Tcl_GetStringFromObj(objPtr, &length);
+	TclInitCompileEnv(interp, &compEnv, string);
+	result = TclCompileExpr(interp, string, string + length,
+		/*flags*/ 0, &compEnv);
+	if (result == TCL_OK) {
+	    /*
+	     * If the expression yielded no instructions (e.g., was empty),
+	     * push an integer zero object as the expressions's result.
+	     */
+	    
+	    if (compEnv.codeNext == NULL) {
+		int objIndex = TclObjIndexForString("0", 0,
+			/*allocStrRep*/ 0, /*inHeap*/ 0, &compEnv);
+		Tcl_Obj *objPtr = compEnv.objArrayPtr[objIndex];
+
+		Tcl_InvalidateStringRep(objPtr);
+		objPtr->internalRep.longValue = 0;
+		objPtr->typePtr = &tclIntType;
+		
+		TclEmitPush(objIndex, &compEnv);
+	    }
+	    
+	    /*
+	     * Add done instruction at the end of the instruction sequence.
+	     */
+	    
+	    TclEmitOpcode(INST_DONE, &compEnv);
+	    
+	    TclInitByteCodeObj(objPtr, &compEnv);
+	    codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
+	    if (tclTraceCompile == 2) {
+		TclPrintByteCodeObj(interp, objPtr);
+	    }
+	    TclFreeCompileEnv(&compEnv);
+	} else {
+	    /*
+	     * Compilation errors. Decrement the ref counts on any objects
+	     * in the object array before freeing the compilation
+	     * environment.
+	     */
+	    
+	    for (i = 0;  i < compEnv.objArrayNext;  i++) {
+		Tcl_Obj *elemPtr = compEnv.objArrayPtr[i];
+		Tcl_DecrRefCount(elemPtr);
+	    }
+
+	    auxDataPtr = compEnv.auxDataArrayPtr;
+	    for (i = 0;  i < compEnv.auxDataArrayNext;  i++) {
+		if (auxDataPtr->type->freeProc != NULL) {
+		    auxDataPtr->type->freeProc(auxDataPtr->clientData);
+		}
+		auxDataPtr++;
+	    }
+	    TclFreeCompileEnv(&compEnv);
+	    return result;
+	}
+    }
+
+    /*
+     * Execute the expression after first saving the interpreter's result.
+     */
+    
+    dummy.objResultPtr = Tcl_NewObj();
+    Tcl_IncrRefCount(dummy.objResultPtr);
+    if (interp->freeProc == 0) {
+	dummy.freeProc = (Tcl_FreeProc *) 0;
+	dummy.result = "";
+	Tcl_SetResult((Tcl_Interp *) &dummy, interp->result,
+	        TCL_VOLATILE);
+    } else {
+	dummy.freeProc = interp->freeProc;
+	dummy.result = interp->result;
+	interp->freeProc = (Tcl_FreeProc *) 0;
+    }
+    
+    saveObjPtr = Tcl_GetObjResult(interp);
+    Tcl_IncrRefCount(saveObjPtr);
+    
+    /*
+     * Increment the code's ref count while it is being executed. If
+     * afterwards no references to it remain, free the code.
+     */
+    
+    codePtr->refCount++;
+    result = TclExecuteByteCode(interp, codePtr);
+    codePtr->refCount--;
+    if (codePtr->refCount <= 0) {
+	TclCleanupByteCode(codePtr);
+    }
+    
+    /*
+     * If the expression evaluated successfully, store a pointer to its
+     * value object in resultPtrPtr then restore the old interpreter result.
+     * We increment the object's ref count to reflect the reference that we
+     * are returning to the caller. We also decrement the ref count of the
+     * interpreter's result object after calling Tcl_SetResult since we
+     * next store into that field directly.
+     */
+    
+    if (result == TCL_OK) {
+	*resultPtrPtr = iPtr->objResultPtr;
+	Tcl_IncrRefCount(iPtr->objResultPtr);
+	
+	Tcl_SetResult(interp, dummy.result,
+	        ((dummy.freeProc == 0) ? TCL_VOLATILE : dummy.freeProc));
+	Tcl_DecrRefCount(iPtr->objResultPtr);
+	iPtr->objResultPtr = saveObjPtr;
+    } else {
+	Tcl_DecrRefCount(saveObjPtr);
+	Tcl_FreeResult((Tcl_Interp *) &dummy);
+    }
+
+    Tcl_DecrRefCount(dummy.objResultPtr);
+    dummy.objResultPtr = NULL;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CreateTrace --
+ *
+ *	Arrange for a procedure to be called to trace command execution.
+ *
+ * Results:
+ *	The return value is a token for the trace, which may be passed
+ *	to Tcl_DeleteTrace to eliminate the trace.
+ *
+ * Side effects:
+ *	From now on, proc will be called just before a command procedure
+ *	is called to execute a Tcl command.  Calls to proc will have the
+ *	following form:
+ *
+ *	void
+ *	proc(clientData, interp, level, command, cmdProc, cmdClientData,
+ *		argc, argv)
+ *	    ClientData clientData;
+ *	    Tcl_Interp *interp;
+ *	    int level;
+ *	    char *command;
+ *	    int (*cmdProc)();
+ *	    ClientData cmdClientData;
+ *	    int argc;
+ *	    char **argv;
+ *	{
+ *	}
+ *
+ *	The clientData and interp arguments to proc will be the same
+ *	as the corresponding arguments to this procedure.  Level gives
+ *	the nesting level of command interpretation for this interpreter
+ *	(0 corresponds to top level).  Command gives the ASCII text of
+ *	the raw command, cmdProc and cmdClientData give the procedure that
+ *	will be called to process the command and the ClientData value it
+ *	will receive, and argc and argv give the arguments to the
+ *	command, after any argument parsing and substitution.  Proc
+ *	does not return a value.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Trace
+Tcl_CreateTrace(interp, level, proc, clientData)
+    Tcl_Interp *interp;		/* Interpreter in which to create trace. */
+    int level;			/* Only call proc for commands at nesting
+				 * level<=argument level (1=>top level). */
+    Tcl_CmdTraceProc *proc;	/* Procedure to call before executing each
+				 * command. */
+    ClientData clientData;	/* Arbitrary value word to pass to proc. */
+{
+    register Trace *tracePtr;
+    register Interp *iPtr = (Interp *) interp;
+
+    /*
+     * Invalidate existing compiled code for this interpreter and arrange
+     * (by setting the DONT_COMPILE_CMDS_INLINE flag) that when compiling
+     * new code, no commands will be compiled inline (i.e., into an inline
+     * sequence of instructions). We do this because commands that were
+     * compiled inline will never result in a command trace being called.
+     */
+
+    iPtr->compileEpoch++;
+    iPtr->flags |= DONT_COMPILE_CMDS_INLINE;
+
+    tracePtr = (Trace *) ckalloc(sizeof(Trace));
+    tracePtr->level = level;
+    tracePtr->proc = proc;
+    tracePtr->clientData = clientData;
+    tracePtr->nextPtr = iPtr->tracePtr;
+    iPtr->tracePtr = tracePtr;
+
+    return (Tcl_Trace) tracePtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DeleteTrace --
+ *
+ *	Remove a trace.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	From now on there will be no more calls to the procedure given
+ *	in trace.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DeleteTrace(interp, trace)
+    Tcl_Interp *interp;		/* Interpreter that contains trace. */
+    Tcl_Trace trace;		/* Token for trace (returned previously by
+				 * Tcl_CreateTrace). */
+{
+    register Interp *iPtr = (Interp *) interp;
+    register Trace *tracePtr = (Trace *) trace;
+    register Trace *tracePtr2;
+
+    if (iPtr->tracePtr == tracePtr) {
+	iPtr->tracePtr = tracePtr->nextPtr;
+	ckfree((char *) tracePtr);
+    } else {
+	for (tracePtr2 = iPtr->tracePtr; tracePtr2 != NULL;
+		tracePtr2 = tracePtr2->nextPtr) {
+	    if (tracePtr2->nextPtr == tracePtr) {
+		tracePtr2->nextPtr = tracePtr->nextPtr;
+		ckfree((char *) tracePtr);
+		break;
+	    }
+	}
+    }
+
+    if (iPtr->tracePtr == NULL) {
+	/*
+	 * When compiling new code, allow commands to be compiled inline.
+	 */
+
+	iPtr->flags &= ~DONT_COMPILE_CMDS_INLINE;
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AddErrorInfo --
+ *
+ *	Add information to the "errorInfo" variable that describes the
+ *	current error.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The contents of message are added to the "errorInfo" variable.
+ *	If Tcl_Eval has been called since the current value of errorInfo
+ *	was set, errorInfo is cleared before adding the new message.
+ *	If we are just starting to log an error, errorInfo is initialized
+ *	from the error message in the interpreter's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_AddErrorInfo(interp, message)
+    Tcl_Interp *interp;		/* Interpreter to which error information
+				 * pertains. */
+    char *message;		/* Message to record. */
+{
+    Tcl_AddObjErrorInfo(interp, message, -1);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AddObjErrorInfo --
+ *
+ *	Add information to the "errorInfo" variable that describes the
+ *	current error. This routine differs from Tcl_AddErrorInfo by
+ *	taking a byte pointer and length.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	"length" bytes from "message" are added to the "errorInfo" variable.
+ *	If "length" is negative, use bytes up to the first NULL byte.
+ *	If Tcl_EvalObj has been called since the current value of errorInfo
+ *	was set, errorInfo is cleared before adding the new message.
+ *	If we are just starting to log an error, errorInfo is initialized
+ *	from the error message in the interpreter's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_AddObjErrorInfo(interp, message, length)
+    Tcl_Interp *interp;		/* Interpreter to which error information
+				 * pertains. */
+    char *message;		/* Points to the first byte of an array of
+				 * bytes of the message. */
+    register int length;	/* The number of bytes in the message.
+				 * If < 0, then append all bytes up to a
+				 * NULL byte. */
+{
+    register Interp *iPtr = (Interp *) interp;
+    Tcl_Obj *namePtr, *messagePtr;
+    
+    /*
+     * If we are just starting to log an error, errorInfo is initialized
+     * from the error message in the interpreter's result.
+     */
+
+    namePtr = Tcl_NewStringObj("errorInfo", -1);
+    Tcl_IncrRefCount(namePtr);
+    
+    if (!(iPtr->flags & ERR_IN_PROGRESS)) { /* just starting to log error */
+	iPtr->flags |= ERR_IN_PROGRESS;
+
+	if (iPtr->result[0] == 0) {
+	    (void) Tcl_ObjSetVar2(interp, namePtr, (Tcl_Obj *) NULL,
+	            iPtr->objResultPtr, TCL_GLOBAL_ONLY);
+	} else {		/* use the string result */
+	    Tcl_SetVar2(interp, "errorInfo", (char *) NULL, interp->result,
+		    TCL_GLOBAL_ONLY);
+	}
+
+	/*
+	 * If the errorCode variable wasn't set by the code that generated
+	 * the error, set it to "NONE".
+	 */
+
+	if (!(iPtr->flags & ERROR_CODE_SET)) {
+	    (void) Tcl_SetVar2(interp, "errorCode", (char *) NULL, "NONE",
+		    TCL_GLOBAL_ONLY);
+	}
+    }
+
+    /*
+     * Now append "message" to the end of errorInfo.
+     */
+
+    if (length != 0) {
+	messagePtr = Tcl_NewStringObj(message, length);
+	Tcl_IncrRefCount(messagePtr);
+	Tcl_ObjSetVar2(interp, namePtr, (Tcl_Obj *) NULL, messagePtr,
+		(TCL_GLOBAL_ONLY | TCL_APPEND_VALUE));
+	Tcl_DecrRefCount(messagePtr); /* free msg object appended above */
+    }
+
+    Tcl_DecrRefCount(namePtr);    /* free the name object */
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_VarEval --
+ *
+ *	Given a variable number of string arguments, concatenate them
+ *	all together and execute the result as a Tcl command.
+ *
+ * Results:
+ *	A standard Tcl return result.  An error message or other
+ *	result may be left in interp->result.
+ *
+ * Side effects:
+ *	Depends on what was done by the command.
+ *
+ *----------------------------------------------------------------------
+ */
+	/* VARARGS2 */ /* ARGSUSED */
+int
+Tcl_VarEval TCL_VARARGS_DEF(Tcl_Interp *,arg1)
+{
+    va_list argList;
+    Tcl_DString buf;
+    char *string;
+    Tcl_Interp *interp;
+    int result;
+
+    /*
+     * Copy the strings one after the other into a single larger
+     * string.  Use stack-allocated space for small commands, but if
+     * the command gets too large than call ckalloc to create the
+     * space.
+     */
+
+    interp = TCL_VARARGS_START(Tcl_Interp *,arg1,argList);
+    Tcl_DStringInit(&buf);
+    while (1) {
+	string = va_arg(argList, char *);
+	if (string == NULL) {
+	    break;
+	}
+	Tcl_DStringAppend(&buf, string, -1);
+    }
+    va_end(argList);
+
+    result = Tcl_Eval(interp, Tcl_DStringValue(&buf));
+    Tcl_DStringFree(&buf);
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GlobalEval --
+ *
+ *	Evaluate a command at global level in an interpreter.
+ *
+ * Results:
+ *	A standard Tcl result is returned, and interp->result is
+ *	modified accordingly.
+ *
+ * Side effects:
+ *	The command string is executed in interp, and the execution
+ *	is carried out in the variable context of global level (no
+ *	procedures active), just as if an "uplevel #0" command were
+ *	being executed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GlobalEval(interp, command)
+    Tcl_Interp *interp;		/* Interpreter in which to evaluate command. */
+    char *command;		/* Command to evaluate. */
+{
+    register Interp *iPtr = (Interp *) interp;
+    int result;
+    CallFrame *savedVarFramePtr;
+
+    savedVarFramePtr = iPtr->varFramePtr;
+    iPtr->varFramePtr = NULL;
+    result = Tcl_Eval(interp, command);
+    iPtr->varFramePtr = savedVarFramePtr;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GlobalEvalObj --
+ *
+ *	Execute Tcl commands stored in a Tcl object at global level in
+ *	an interpreter. These commands are compiled into bytecodes if
+ *	necessary.
+ *
+ * Results:
+ *	A standard Tcl result is returned, and the interpreter's result
+ *	contains a Tcl object value to supplement the return code.
+ *
+ * Side effects:
+ *	The object is converted, if necessary, to a ByteCode object that
+ *	holds the bytecode instructions for the commands. Executing the
+ *	commands will almost certainly have side effects that depend on
+ *	those commands.
+ *
+ *	The commands are executed in interp, and the execution
+ *	is carried out in the variable context of global level (no
+ *	procedures active), just as if an "uplevel #0" command were
+ *	being executed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GlobalEvalObj(interp, objPtr)
+    Tcl_Interp *interp;		/* Interpreter in which to evaluate
+				 * commands. */
+    Tcl_Obj *objPtr;		/* Pointer to object containing commands
+				 * to execute. */
+{
+    register Interp *iPtr = (Interp *) interp;
+    int result;
+    CallFrame *savedVarFramePtr;
+
+    savedVarFramePtr = iPtr->varFramePtr;
+    iPtr->varFramePtr = NULL;
+    result = Tcl_EvalObj(interp, objPtr);
+    iPtr->varFramePtr = savedVarFramePtr;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetRecursionLimit --
+ *
+ *	Set the maximum number of recursive calls that may be active
+ *	for an interpreter at once.
+ *
+ * Results:
+ *	The return value is the old limit on nesting for interp.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_SetRecursionLimit(interp, depth)
+    Tcl_Interp *interp;			/* Interpreter whose nesting limit
+					 * is to be set. */
+    int depth;				/* New value for maximimum depth. */
+{
+    Interp *iPtr = (Interp *) interp;
+    int old;
+
+    old = iPtr->maxNestingDepth;
+    if (depth > 0) {
+	iPtr->maxNestingDepth = depth;
+    }
+    return old;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AllowExceptions --
+ *
+ *	Sets a flag in an interpreter so that exceptions can occur
+ *	in the next call to Tcl_Eval without them being turned into
+ *	errors.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The TCL_ALLOW_EXCEPTIONS flag gets set in the interpreter's
+ *	evalFlags structure.  See the reference documentation for
+ *	more details.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_AllowExceptions(interp)
+    Tcl_Interp *interp;		/* Interpreter in which to set flag. */
+{
+    Interp *iPtr = (Interp *) interp;
+
+    iPtr->evalFlags |= TCL_ALLOW_EXCEPTIONS;
+}
+
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclCkalloc.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclCkalloc.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclCkalloc.c	(revision 5)
@@ -0,0 +1,829 @@
+/* 
+ * tclCkalloc.c --
+ *
+ *    Interface to malloc and free that provides support for debugging problems
+ *    involving overwritten, double freeing memory and loss of memory.
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * This code contributed by Karl Lehenbauer and Mark Diekhans
+ *
+ * RCS: @(#) $Id: tclCkalloc.c,v 1.1 2008-06-04 13:58:04 demin Exp $
+ */
+
+#include "tclInt.h"
+#include "tclPort.h"
+
+#define FALSE	0
+#define TRUE	1
+
+#ifdef TCL_MEM_DEBUG
+
+/*
+ * One of the following structures is allocated each time the
+ * "memory tag" command is invoked, to hold the current tag.
+ */
+
+typedef struct MemTag {
+    int refCount;		/* Number of mem_headers referencing
+				 * this tag. */
+    char string[4];		/* Actual size of string will be as
+				 * large as needed for actual tag.  This
+				 * must be the last field in the structure. */
+} MemTag;
+
+#define TAG_SIZE(bytesInString) ((unsigned) sizeof(MemTag) + bytesInString - 3)
+
+static MemTag *curTagPtr = NULL;/* Tag to use in all future mem_headers
+				 * (set by "memory tag" command). */
+
+/*
+ * One of the following structures is allocated just before each
+ * dynamically allocated chunk of memory, both to record information
+ * about the chunk and to help detect chunk under-runs.
+ */
+
+#define LOW_GUARD_SIZE (8 + (32 - (sizeof(long) + sizeof(int)))%8)
+struct mem_header {
+    struct mem_header *flink;
+    struct mem_header *blink;
+    MemTag *tagPtr;		/* Tag from "memory tag" command;  may be
+				 * NULL. */
+    char *file;
+    long length;
+    int line;
+    unsigned char low_guard[LOW_GUARD_SIZE];
+				/* Aligns body on 8-byte boundary, plus
+				 * provides at least 8 additional guard bytes
+				 * to detect underruns. */
+    char body[1];		/* First byte of client's space.  Actual
+				 * size of this field will be larger than
+				 * one. */
+};
+
+static struct mem_header *allocHead = NULL;  /* List of allocated structures */
+
+#define GUARD_VALUE  0141
+
+/*
+ * The following macro determines the amount of guard space *above* each
+ * chunk of memory.
+ */
+
+#define HIGH_GUARD_SIZE 8
+
+/*
+ * The following macro computes the offset of the "body" field within
+ * mem_header.  It is used to get back to the header pointer from the
+ * body pointer that's used by clients.
+ */
+
+#define BODY_OFFSET \
+	((unsigned long) (&((struct mem_header *) 0)->body))
+
+static int total_mallocs = 0;
+static int total_frees = 0;
+static int current_bytes_malloced = 0;
+static int maximum_bytes_malloced = 0;
+static int current_malloc_packets = 0;
+static int maximum_malloc_packets = 0;
+static int break_on_malloc = 0;
+static int trace_on_at_malloc = 0;
+static int  alloc_tracing = FALSE;
+static int  init_malloced_bodies = TRUE;
+#ifdef MEM_VALIDATE
+    static int  validate_memory = TRUE;
+#else
+    static int  validate_memory = FALSE;
+#endif
+
+/*
+ * Prototypes for procedures defined in this file:
+ */
+
+static int		MemoryCmd _ANSI_ARGS_((ClientData clientData,
+			    Tcl_Interp *interp, int argc, char **argv));
+static void		ValidateMemory _ANSI_ARGS_((
+			    struct mem_header *memHeaderP, char *file,
+			    int line, int nukeGuards));
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclDumpMemoryInfo --
+ *     Display the global memory management statistics.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TclDumpMemoryInfo(outFile) 
+    FILE *outFile;
+{
+        fprintf(outFile,"total mallocs             %10d\n", 
+                total_mallocs);
+        fprintf(outFile,"total frees               %10d\n", 
+                total_frees);
+        fprintf(outFile,"current packets allocated %10d\n", 
+                current_malloc_packets);
+        fprintf(outFile,"current bytes allocated   %10d\n", 
+                current_bytes_malloced);
+        fprintf(outFile,"maximum packets allocated %10d\n", 
+                maximum_malloc_packets);
+        fprintf(outFile,"maximum bytes allocated   %10d\n", 
+                maximum_bytes_malloced);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ValidateMemory --
+ *     Procedure to validate allocted memory guard zones.
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+ValidateMemory(memHeaderP, file, line, nukeGuards)
+    struct mem_header *memHeaderP;
+    char              *file;
+    int                line;
+    int                nukeGuards;
+{
+    unsigned char *hiPtr;
+    int   idx;
+    int   guard_failed = FALSE;
+    int byte;
+    
+    for (idx = 0; idx < LOW_GUARD_SIZE; idx++) {
+        byte = *(memHeaderP->low_guard + idx);
+        if (byte != GUARD_VALUE) {
+            guard_failed = TRUE;
+            fflush(stdout);
+	    byte &= 0xff;
+            fprintf(stderr, "low guard byte %d is 0x%x  \t%c\n", idx, byte,
+		    (isprint(UCHAR(byte)) ? byte : ' '));
+        }
+    }
+    if (guard_failed) {
+        TclDumpMemoryInfo (stderr);
+        fprintf(stderr, "low guard failed at %lx, %s %d\n",
+                 (long unsigned int) memHeaderP->body, file, line);
+        fflush(stderr);  /* In case name pointer is bad. */
+        fprintf(stderr, "%ld bytes allocated at (%s %d)\n", memHeaderP->length,
+		memHeaderP->file, memHeaderP->line);
+        panic ("Memory validation failure");
+    }
+
+    hiPtr = (unsigned char *)memHeaderP->body + memHeaderP->length;
+    for (idx = 0; idx < HIGH_GUARD_SIZE; idx++) {
+        byte = *(hiPtr + idx);
+        if (byte != GUARD_VALUE) {
+            guard_failed = TRUE;
+            fflush (stdout);
+	    byte &= 0xff;
+            fprintf(stderr, "hi guard byte %d is 0x%x  \t%c\n", idx, byte,
+		    (isprint(UCHAR(byte)) ? byte : ' '));
+        }
+    }
+
+    if (guard_failed) {
+        TclDumpMemoryInfo (stderr);
+        fprintf(stderr, "high guard failed at %lx, %s %d\n",
+                 (long unsigned int) memHeaderP->body, file, line);
+        fflush(stderr);  /* In case name pointer is bad. */
+        fprintf(stderr, "%ld bytes allocated at (%s %d)\n",
+		memHeaderP->length, memHeaderP->file,
+		memHeaderP->line);
+        panic("Memory validation failure");
+    }
+
+    if (nukeGuards) {
+        memset ((char *) memHeaderP->low_guard, 0, LOW_GUARD_SIZE); 
+        memset ((char *) hiPtr, 0, HIGH_GUARD_SIZE); 
+    }
+
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ValidateAllMemory --
+ *     Validates guard regions for all allocated memory.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+Tcl_ValidateAllMemory (file, line)
+    char  *file;
+    int    line;
+{
+    struct mem_header *memScanP;
+
+    for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink)
+        ValidateMemory(memScanP, file, line, FALSE);
+
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DumpActiveMemory --
+ *     Displays all allocated memory to stderr.
+ *
+ * Results:
+ *     Return TCL_ERROR if an error accessing the file occures, `errno' 
+ *     will have the file error number left in it.
+ *----------------------------------------------------------------------
+ */
+int
+Tcl_DumpActiveMemory (fileName)
+    char *fileName;
+{
+    FILE              *fileP;
+    struct mem_header *memScanP;
+    char              *address;
+
+    fileP = fopen(fileName, "w");
+    if (fileP == NULL)
+        return TCL_ERROR;
+
+    for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink) {
+        address = &memScanP->body [0];
+        fprintf(fileP, "%8lx - %8lx  %7ld @ %s %d %s",
+		(long unsigned int) address,
+                 (long unsigned int) address + memScanP->length - 1,
+		 memScanP->length, memScanP->file, memScanP->line,
+		 (memScanP->tagPtr == NULL) ? "" : memScanP->tagPtr->string);
+	(void) fputc('\n', fileP);
+    }
+    fclose (fileP);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DbCkalloc - debugging ckalloc
+ *
+ *        Allocate the requested amount of space plus some extra for
+ *        guard bands at both ends of the request, plus a size, panicing 
+ *        if there isn't enough space, then write in the guard bands
+ *        and return the address of the space in the middle that the
+ *        user asked for.
+ *
+ *        The second and third arguments are file and line, these contain
+ *        the filename and line number corresponding to the caller.
+ *        These are sent by the ckalloc macro; it uses the preprocessor
+ *        autodefines __FILE__ and __LINE__.
+ *
+ *----------------------------------------------------------------------
+ */
+char *
+Tcl_DbCkalloc(size, file, line)
+    unsigned int size;
+    char        *file;
+    int          line;
+{
+    struct mem_header *result;
+
+    if (validate_memory)
+        Tcl_ValidateAllMemory (file, line);
+
+    result = (struct mem_header *) TclpAlloc((unsigned)size + 
+                              sizeof(struct mem_header) + HIGH_GUARD_SIZE);
+    if (result == NULL) {
+        fflush(stdout);
+        TclDumpMemoryInfo(stderr);
+        panic("unable to alloc %d bytes, %s line %d", size, file, 
+              line);
+    }
+
+    /*
+     * Fill in guard zones and size.  Also initialize the contents of
+     * the block with bogus bytes to detect uses of initialized data.
+     * Link into allocated list.
+     */
+    if (init_malloced_bodies) {
+        memset ((VOID *) result, GUARD_VALUE,
+		size + sizeof(struct mem_header) + HIGH_GUARD_SIZE);
+    } else {
+	memset ((char *) result->low_guard, GUARD_VALUE, LOW_GUARD_SIZE);
+	memset (result->body + size, GUARD_VALUE, HIGH_GUARD_SIZE);
+    }
+    result->length = size;
+    result->tagPtr = curTagPtr;
+    if (curTagPtr != NULL) {
+	curTagPtr->refCount++;
+    }
+    result->file = file;
+    result->line = line;
+    result->flink = allocHead;
+    result->blink = NULL;
+    if (allocHead != NULL)
+        allocHead->blink = result;
+    allocHead = result;
+
+    total_mallocs++;
+    if (trace_on_at_malloc && (total_mallocs >= trace_on_at_malloc)) {
+        (void) fflush(stdout);
+        fprintf(stderr, "reached malloc trace enable point (%d)\n",
+                total_mallocs);
+        fflush(stderr);
+        alloc_tracing = TRUE;
+        trace_on_at_malloc = 0;
+    }
+
+    if (alloc_tracing)
+        fprintf(stderr,"ckalloc %lx %d %s %d\n",
+		(long unsigned int) result->body, size, file, line);
+
+    if (break_on_malloc && (total_mallocs >= break_on_malloc)) {
+        break_on_malloc = 0;
+        (void) fflush(stdout);
+        fprintf(stderr,"reached malloc break limit (%d)\n", 
+                total_mallocs);
+        fprintf(stderr, "program will now enter C debugger\n");
+        (void) fflush(stderr);
+	abort();
+    }
+
+    current_malloc_packets++;
+    if (current_malloc_packets > maximum_malloc_packets)
+        maximum_malloc_packets = current_malloc_packets;
+    current_bytes_malloced += size;
+    if (current_bytes_malloced > maximum_bytes_malloced)
+        maximum_bytes_malloced = current_bytes_malloced;
+
+    return result->body;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DbCkfree - debugging ckfree
+ *
+ *        Verify that the low and high guards are intact, and if so
+ *        then free the buffer else panic.
+ *
+ *        The guards are erased after being checked to catch duplicate
+ *        frees.
+ *
+ *        The second and third arguments are file and line, these contain
+ *        the filename and line number corresponding to the caller.
+ *        These are sent by the ckfree macro; it uses the preprocessor
+ *        autodefines __FILE__ and __LINE__.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_DbCkfree(ptr, file, line)
+    char *  ptr;
+    char     *file;
+    int       line;
+{
+    /*
+     * The following cast is *very* tricky.  Must convert the pointer
+     * to an integer before doing arithmetic on it, because otherwise
+     * the arithmetic will be done differently (and incorrectly) on
+     * word-addressed machines such as Crays (will subtract only bytes,
+     * even though BODY_OFFSET is in words on these machines).
+     */
+
+    struct mem_header *memp = (struct mem_header *)
+	    (((unsigned long) ptr) - BODY_OFFSET);
+
+    if (alloc_tracing)
+        fprintf(stderr, "ckfree %lx %ld %s %d\n",
+		(long unsigned int) memp->body, memp->length, file, line);
+
+    if (validate_memory)
+        Tcl_ValidateAllMemory(file, line);
+
+    ValidateMemory(memp, file, line, TRUE);
+    if (init_malloced_bodies) {
+	memset((VOID *) ptr, GUARD_VALUE, (size_t) memp->length);
+    }
+
+    total_frees++;
+    current_malloc_packets--;
+    current_bytes_malloced -= memp->length;
+
+    if (memp->tagPtr != NULL) {
+	memp->tagPtr->refCount--;
+	if ((memp->tagPtr->refCount == 0) && (curTagPtr != memp->tagPtr)) {
+	    TclpFree((char *) memp->tagPtr);
+	}
+    }
+
+    /*
+     * Delink from allocated list
+     */
+    if (memp->flink != NULL)
+        memp->flink->blink = memp->blink;
+    if (memp->blink != NULL)
+        memp->blink->flink = memp->flink;
+    if (allocHead == memp)
+        allocHead = memp->flink;
+    TclpFree((char *) memp);
+    return 0;
+}
+
+
+/*
+ *--------------------------------------------------------------------
+ *
+ * Tcl_DbCkrealloc - debugging ckrealloc
+ *
+ *	Reallocate a chunk of memory by allocating a new one of the
+ *	right size, copying the old data to the new location, and then
+ *	freeing the old memory space, using all the memory checking
+ *	features of this package.
+ *
+ *--------------------------------------------------------------------
+ */
+char *
+Tcl_DbCkrealloc(ptr, size, file, line)
+    char *ptr;
+    unsigned int size;
+    char *file;
+    int line;
+{
+    char *new;
+    unsigned int copySize;
+
+    /*
+     * See comment from Tcl_DbCkfree before you change the following
+     * line.
+     */
+
+    struct mem_header *memp = (struct mem_header *)
+	    (((unsigned long) ptr) - BODY_OFFSET);
+
+    copySize = size;
+    if (copySize > (unsigned int) memp->length) {
+	copySize = memp->length;
+    }
+    new = Tcl_DbCkalloc(size, file, line);
+    memcpy((VOID *) new, (VOID *) ptr, (size_t) copySize);
+    Tcl_DbCkfree(ptr, file, line);
+    return(new);
+}
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_Alloc, et al. --
+ *
+ *	These functions are defined in terms of the debugging versions
+ *	when TCL_MEM_DEBUG is set.
+ *
+ * Results:
+ *	Same as the debug versions.
+ *
+ * Side effects:
+ *	Same as the debug versions.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#undef Tcl_Alloc
+#undef Tcl_Free
+#undef Tcl_Realloc
+
+char *
+Tcl_Alloc(size)
+    unsigned int size;
+{
+    return Tcl_DbCkalloc(size, "unknown", 0);
+}
+
+void
+Tcl_Free(ptr)
+    char *ptr;
+{
+    Tcl_DbCkfree(ptr, "unknown", 0);
+}
+
+char *
+Tcl_Realloc(ptr, size)
+    char *ptr;
+    unsigned int size;
+{
+    return Tcl_DbCkrealloc(ptr, size, "unknown", 0);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MemoryCmd --
+ *     Implements the TCL memory command:
+ *       memory info
+ *       memory display
+ *       break_on_malloc count
+ *       trace_on_at_malloc count
+ *       trace on|off
+ *       validate on|off
+ *
+ * Results:
+ *     Standard TCL results.
+ *
+ *----------------------------------------------------------------------
+ */
+	/* ARGSUSED */
+static int
+MemoryCmd (clientData, interp, argc, argv)
+    ClientData  clientData;
+    Tcl_Interp *interp;
+    int         argc;
+    char      **argv;
+{
+    char *fileName;
+    Tcl_DString buffer;
+    int result;
+
+    if (argc < 2) {
+	Tcl_AppendResult(interp, "wrong # args: should be \"",
+		argv[0], " option [args..]\"", (char *) NULL);
+	return TCL_ERROR;
+    }
+
+    if (strcmp(argv[1],"active") == 0) {
+        if (argc != 3) {
+	    Tcl_AppendResult(interp, "wrong # args: should be \"",
+		    argv[0], " active file\"", (char *) NULL);
+	    return TCL_ERROR;
+	}
+	fileName = Tcl_TranslateFileName(interp, argv[2], &buffer);
+	if (fileName == NULL) {
+	    return TCL_ERROR;
+	}
+	result = Tcl_DumpActiveMemory (fileName);
+	Tcl_DStringFree(&buffer);
+	if (result != TCL_OK) {
+	    Tcl_AppendResult(interp, "error accessing ", argv[2], 
+		    (char *) NULL);
+	    return TCL_ERROR;
+	}
+	return TCL_OK;
+    }
+    if (strcmp(argv[1],"break_on_malloc") == 0) {
+        if (argc != 3) {
+            goto argError;
+	}
+        if (Tcl_GetInt(interp, argv[2], &break_on_malloc) != TCL_OK) {
+	    return TCL_ERROR;
+	}
+        return TCL_OK;
+    }
+    if (strcmp(argv[1],"info") == 0) {
+        TclDumpMemoryInfo(stdout);
+        return TCL_OK;
+    }
+    if (strcmp(argv[1],"init") == 0) {
+        if (argc != 3) {
+            goto bad_suboption;
+	}
+        init_malloced_bodies = (strcmp(argv[2],"on") == 0);
+        return TCL_OK;
+    }
+    if (strcmp(argv[1],"tag") == 0) {
+	if (argc != 3) {
+	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+		    " tag string\"", (char *) NULL);
+	    return TCL_ERROR;
+	}
+	if ((curTagPtr != NULL) && (curTagPtr->refCount == 0)) {
+	    TclpFree((char *) curTagPtr);
+	}
+	curTagPtr = (MemTag *) TclpAlloc(TAG_SIZE(strlen(argv[2])));
+	curTagPtr->refCount = 0;
+	strcpy(curTagPtr->string, argv[2]);
+	return TCL_OK;
+    }
+    if (strcmp(argv[1],"trace") == 0) {
+        if (argc != 3) {
+            goto bad_suboption;
+	}
+        alloc_tracing = (strcmp(argv[2],"on") == 0);
+        return TCL_OK;
+    }
+
+    if (strcmp(argv[1],"trace_on_at_malloc") == 0) {
+        if (argc != 3) {
+            goto argError;
+	}
+        if (Tcl_GetInt(interp, argv[2], &trace_on_at_malloc) != TCL_OK) {
+	    return TCL_ERROR;
+	}
+	return TCL_OK;
+    }
+    if (strcmp(argv[1],"validate") == 0) {
+        if (argc != 3) {
+	    goto bad_suboption;
+	}
+        validate_memory = (strcmp(argv[2],"on") == 0);
+        return TCL_OK;
+    }
+
+    Tcl_AppendResult(interp, "bad option \"", argv[1],
+	    "\": should be active, break_on_malloc, info, init, ",
+	    "tag, trace, trace_on_at_malloc, or validate", (char *) NULL);
+    return TCL_ERROR;
+
+argError:
+    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+	    " ", argv[1], " count\"", (char *) NULL);
+    return TCL_ERROR;
+
+bad_suboption:
+    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+	    " ", argv[1], " on|off\"", (char *) NULL);
+    return TCL_ERROR;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_InitMemory --
+ *     Initialize the memory command.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+Tcl_InitMemory(interp)
+    Tcl_Interp *interp;
+{
+    Tcl_CreateCommand (interp, "memory", MemoryCmd, (ClientData) NULL, 
+	    (Tcl_CmdDeleteProc *) NULL);
+}
+
+#else
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_Alloc --
+ *     Interface to TclpAlloc when TCL_MEM_DEBUG is disabled.  It does check
+ *     that memory was actually allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_Alloc (size)
+    unsigned int size;
+{
+        char *result;
+
+        result = TclpAlloc(size);
+        if (result == NULL) 
+                panic("unable to alloc %d bytes", size);
+        return result;
+}
+
+char *
+Tcl_DbCkalloc(size, file, line)
+    unsigned int size;
+    char        *file;
+    int          line;
+{
+    char *result;
+
+    result = (char *) TclpAlloc(size);
+
+    if (result == NULL) {
+        fflush(stdout);
+        panic("unable to alloc %d bytes, %s line %d", size, file, 
+              line);
+    }
+    return result;
+}
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_Realloc --
+ *     Interface to TclpRealloc when TCL_MEM_DEBUG is disabled.  It does 
+ *     check that memory was actually allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_Realloc(ptr, size)
+    char *ptr;
+    unsigned int size;
+{
+    char *result;
+
+    result = TclpRealloc(ptr, size);
+    if (result == NULL) 
+	panic("unable to realloc %d bytes", size);
+    return result;
+}
+
+char *
+Tcl_DbCkrealloc(ptr, size, file, line)
+    char *ptr;
+    unsigned int size;
+    char *file;
+    int line;
+{
+    char *result;
+
+    result = (char *) TclpRealloc(ptr, size);
+
+    if (result == NULL) {
+        fflush(stdout);
+        panic("unable to realloc %d bytes, %s line %d", size, file, 
+              line);
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_Free --
+ *     Interface to TclpFree when TCL_MEM_DEBUG is disabled.  Done here
+ *     rather in the macro to keep some modules from being compiled with 
+ *     TCL_MEM_DEBUG enabled and some with it disabled.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_Free (ptr)
+    char *ptr;
+{
+        TclpFree(ptr);
+}
+
+int
+Tcl_DbCkfree(ptr, file, line)
+    char *  ptr;
+    char     *file;
+    int       line;
+{
+    TclpFree(ptr);
+    return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_InitMemory --
+ *     Dummy initialization for memory command, which is only available 
+ *     if TCL_MEM_DEBUG is on.
+ *
+ *----------------------------------------------------------------------
+ */
+	/* ARGSUSED */
+void
+Tcl_InitMemory(interp)
+    Tcl_Interp *interp;
+{
+}
+
+#undef Tcl_DumpActiveMemory
+#undef Tcl_ValidateAllMemory
+
+extern int		Tcl_DumpActiveMemory _ANSI_ARGS_((char *fileName));
+extern void		Tcl_ValidateAllMemory _ANSI_ARGS_((char *file,
+			    int line));
+
+int
+Tcl_DumpActiveMemory(fileName)
+    char *fileName;
+{
+    return TCL_OK;
+}
+
+void
+Tcl_ValidateAllMemory(file, line)
+    char  *file;
+    int    line;
+{
+}
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclCmdAH.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclCmdAH.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclCmdAH.c	(revision 5)
@@ -0,0 +1,1202 @@
+/* 
+ * tclCmdAH.c --
+ *
+ *	This file contains the top-level command routines for most of
+ *	the Tcl built-in commands whose names begin with the letters
+ *	A to H.
+ *
+ * Copyright (c) 1987-1993 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclCmdAH.c,v 1.1 2008-06-04 13:58:04 demin Exp $
+ */
+
+#include "tclInt.h"
+#include "tclPort.h"
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_BreakCmd --
+ *
+ *	This procedure is invoked to process the "break" Tcl command.
+ *	See the user documentation for details on what it does.
+ *
+ *	With the bytecode compiler, this procedure is only called when
+ *	a command name is computed at runtime, and is "break" or the name
+ *	to which "break" was renamed: e.g., "set z break; $z"
+ *
+ * Results:
+ *	A standard Tcl result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_BreakCmd(dummy, interp, argc, argv)
+    ClientData dummy;			/* Not used. */
+    Tcl_Interp *interp;			/* Current interpreter. */
+    int argc;				/* Number of arguments. */
+    char **argv;			/* Argument strings. */
+{
+    if (argc != 1) {
+	Tcl_AppendResult(interp, "wrong # args: should be \"",
+		argv[0], "\"", (char *) NULL);
+	return TCL_ERROR;
+    }
+    return TCL_BREAK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CaseObjCmd --
+ *
+ *	This procedure is invoked to process the "case" Tcl command.
+ *	See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_CaseObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    register int i;
+    int body, result;
+    char *string, *arg;
+    int argLen, caseObjc;
+    Tcl_Obj *CONST *caseObjv;
+    Tcl_Obj *armPtr;
+
+    if (objc < 3) {
+	Tcl_WrongNumArgs(interp, 1, objv,
+		"string ?in? patList body ... ?default body?");
+	return TCL_ERROR;
+    }
+
+    /*
+     * THIS FAILS IF AN OBJECT'S STRING REP HAS A NULL BYTE.
+     */
+    
+    string = Tcl_GetStringFromObj(objv[1], &argLen);
+    body = -1;
+
+    arg = Tcl_GetStringFromObj(objv[2], &argLen);
+    if (strcmp(arg, "in") == 0) {
+	i = 3;
+    } else {
+	i = 2;
+    }
+    caseObjc = objc - i;
+    caseObjv = objv + i;
+
+    /*
+     * If all of the pattern/command pairs are lumped into a single
+     * argument, split them out again.
+     * THIS FAILS IF THE ARG'S STRING REP CONTAINS A NULL
+     */
+
+    if (caseObjc == 1) {
+	Tcl_Obj **newObjv;
+	
+	Tcl_ListObjGetElements(interp, caseObjv[0], &caseObjc, &newObjv);
+	caseObjv = newObjv;
+    }
+
+    for (i = 0;  i < caseObjc;  i += 2) {
+	int patObjc, j;
+	char **patObjv;
+	char *pat;
+	register char *p;
+
+	if (i == (caseObjc-1)) {
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	            "extra case pattern with no body", -1);
+	    return TCL_ERROR;
+	}
+
+	/*
+	 * Check for special case of single pattern (no list) with
+	 * no backslash sequences.
+	 */
+
+	pat = Tcl_GetStringFromObj(caseObjv[i], &argLen);
+	for (p = pat;  *p != 0;  p++) {	/* FAILS IF NULL BYTE */
+	    if (isspace(UCHAR(*p)) || (*p == '\\')) {
+		break;
+	    }
+	}
+	if (*p == 0) {
+	    if ((*pat == 'd') && (strcmp(pat, "default") == 0)) {
+		body = i+1;
+	    }
+	    if (Tcl_StringMatch(string, pat)) {
+		body = i+1;
+		goto match;
+	    }
+	    continue;
+	}
+
+
+	/*
+	 * Break up pattern lists, then check each of the patterns
+	 * in the list.
+	 */
+
+	result = Tcl_SplitList(interp, pat, &patObjc, &patObjv);
+	if (result != TCL_OK) {
+	    return result;
+	}
+	for (j = 0; j < patObjc; j++) {
+	    if (Tcl_StringMatch(string, patObjv[j])) {
+		body = i+1;
+		break;
+	    }
+	}
+	ckfree((char *) patObjv);
+	if (j < patObjc) {
+	    break;
+	}
+    }
+
+    match:
+    if (body != -1) {
+	armPtr = caseObjv[body-1];
+	result = Tcl_EvalObj(interp, caseObjv[body]);
+	if (result == TCL_ERROR) {
+	    char msg[100];
+	    
+	    arg = Tcl_GetStringFromObj(armPtr, &argLen);
+	    sprintf(msg, "\n    (\"%.*s\" arm line %d)", argLen, arg,
+	            interp->errorLine);
+	    Tcl_AddObjErrorInfo(interp, msg, -1);
+	}
+	return result;
+    }
+
+    /*
+     * Nothing matched: return nothing.
+     */
+
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CatchObjCmd --
+ *
+ *	This object-based procedure is invoked to process the "catch" Tcl 
+ *	command. See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_CatchObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Tcl_Obj *varNamePtr = NULL;
+    int result;
+
+    if ((objc != 2) && (objc != 3)) {
+	Tcl_WrongNumArgs(interp, 1, objv, "command ?varName?");
+	return TCL_ERROR;
+    }
+
+    /*
+     * Save a pointer to the variable name object, if any, in case the
+     * Tcl_EvalObj reallocates the bytecode interpreter's evaluation
+     * stack rendering objv invalid.
+     */
+    
+    if (objc == 3) {
+	varNamePtr = objv[2];
+    }
+    
+    result = Tcl_EvalObj(interp, objv[1]);
+    
+    if (objc == 3) {
+	if (Tcl_ObjSetVar2(interp, varNamePtr, NULL,
+		    Tcl_GetObjResult(interp), TCL_PARSE_PART1) == NULL) {
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp),  
+	            "couldn't save command result in variable", -1);
+	    return TCL_ERROR;
+	}
+    }
+
+    /*
+     * Set the interpreter's object result to an integer object holding the
+     * integer Tcl_EvalObj result. Note that we don't bother generating a
+     * string representation. We reset the interpreter's object result
+     * to an unshared empty object and then set it to be an integer object.
+     */
+
+    Tcl_ResetResult(interp);
+    Tcl_SetIntObj(Tcl_GetObjResult(interp), result);
+    return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ConcatObjCmd --
+ *
+ *	This object-based procedure is invoked to process the "concat" Tcl
+ *	command. See the user documentation for details on what it does/
+ *
+ * Results:
+ *	A standard Tcl object result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_ConcatObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    if (objc >= 2) {
+	Tcl_SetObjResult(interp, Tcl_ConcatObj(objc-1, objv+1));
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ContinueCmd -
+ *
+ *	This procedure is invoked to process the "continue" Tcl command.
+ *	See the user documentation for details on what it does.
+ *
+ *	With the bytecode compiler, this procedure is only called when
+ *	a command name is computed at runtime, and is "continue" or the name
+ *	to which "continue" was renamed: e.g., "set z continue; $z"
+ *
+ * Results:
+ *	A standard Tcl result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_ContinueCmd(dummy, interp, argc, argv)
+    ClientData dummy;			/* Not used. */
+    Tcl_Interp *interp;			/* Current interpreter. */
+    int argc;				/* Number of arguments. */
+    char **argv;			/* Argument strings. */
+{
+    if (argc != 1) {
+	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+		"\"", (char *) NULL);
+	return TCL_ERROR;
+    }
+    return TCL_CONTINUE;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ErrorObjCmd --
+ *
+ *	This procedure is invoked to process the "error" Tcl command.
+ *	See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_ErrorObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Interp *iPtr = (Interp *) interp;
+    register Tcl_Obj *namePtr;
+    char *info;
+    int infoLen;
+
+    if ((objc < 2) || (objc > 4)) {
+	Tcl_WrongNumArgs(interp, 1, objv, "message ?errorInfo? ?errorCode?");
+	return TCL_ERROR;
+    }
+    
+    if (objc >= 3) {		/* process the optional info argument */
+	info = Tcl_GetStringFromObj(objv[2], &infoLen);
+	if (*info != 0) {
+	    Tcl_AddObjErrorInfo(interp, info, infoLen);
+	    iPtr->flags |= ERR_ALREADY_LOGGED;
+	}
+    }
+    
+    if (objc == 4) {
+	namePtr = Tcl_NewStringObj("errorCode", -1);
+	Tcl_ObjSetVar2(interp, namePtr, (Tcl_Obj *) NULL, objv[3],
+		TCL_GLOBAL_ONLY);
+	iPtr->flags |= ERROR_CODE_SET;
+	Tcl_DecrRefCount(namePtr); /* we're done with name object */
+    }
+    
+    Tcl_SetObjResult(interp, objv[1]);
+    return TCL_ERROR;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_EvalObjCmd --
+ *
+ *	This object-based procedure is invoked to process the "eval" Tcl 
+ *	command. See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_EvalObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    int result;
+    register Tcl_Obj *objPtr;
+
+    if (objc < 2) {
+	Tcl_WrongNumArgs(interp, 1, objv, "arg ?arg ...?");
+	return TCL_ERROR;
+    }
+    
+    if (objc == 2) {
+	result = Tcl_EvalObj(interp, objv[1]);
+    } else {
+	/*
+	 * More than one argument: concatenate them together with spaces
+	 * between, then evaluate the result.
+	 */
+    
+	objPtr = Tcl_ConcatObj(objc-1, objv+1);
+	result = Tcl_EvalObj(interp, objPtr);
+	Tcl_DecrRefCount(objPtr);  /* we're done with the object */
+    }
+    if (result == TCL_ERROR) {
+	char msg[60];
+	sprintf(msg, "\n    (\"eval\" body line %d)", interp->errorLine);
+	Tcl_AddObjErrorInfo(interp, msg, -1);
+    }
+    return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ExprObjCmd --
+ *
+ *	This object-based procedure is invoked to process the "expr" Tcl
+ *	command. See the user documentation for details on what it does.
+ *
+ *	With the bytecode compiler, this procedure is called in two
+ *	circumstances: 1) to execute expr commands that are too complicated
+ *	or too unsafe to try compiling directly into an inline sequence of
+ *	instructions, and 2) to execute commands where the command name is
+ *	computed at runtime and is "expr" or the name to which "expr" was
+ *	renamed (e.g., "set z expr; $z 2+3")
+ *
+ * Results:
+ *	A standard Tcl object result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_ExprObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    register Tcl_Obj *objPtr;
+    Tcl_Obj *resultPtr;
+    register char *bytes;
+    int length, i, result;
+
+    if (objc < 2) {
+	Tcl_WrongNumArgs(interp, 1, objv, "arg ?arg ...?");
+	return TCL_ERROR;
+    }
+
+    if (objc == 2) {
+	result = Tcl_ExprObj(interp, objv[1], &resultPtr);
+	if (result == TCL_OK) {
+	    Tcl_SetObjResult(interp, resultPtr);
+	    Tcl_DecrRefCount(resultPtr);  /* done with the result object */
+	}
+	return result;
+    }
+
+    /*
+     * Create a new object holding the concatenated argument strings.
+     * THIS FAILS IF AN OBJECT'S STRING REP HAS A NULL BYTE.
+     */
+
+    bytes = Tcl_GetStringFromObj(objv[1], &length);
+    objPtr = Tcl_NewStringObj(bytes, length);
+    Tcl_IncrRefCount(objPtr);
+    for (i = 2;  i < objc;  i++) {
+	Tcl_AppendToObj(objPtr, " ", 1);
+	bytes = Tcl_GetStringFromObj(objv[i], &length);
+	Tcl_AppendToObj(objPtr, bytes, length);
+    }
+
+    /*
+     * Evaluate the concatenated string object.
+     */
+
+    result = Tcl_ExprObj(interp, objPtr, &resultPtr);
+    if (result == TCL_OK) {
+	Tcl_SetObjResult(interp, resultPtr);
+	Tcl_DecrRefCount(resultPtr);  /* done with the result object */
+    }
+
+    /*
+     * Free allocated resources.
+     */
+    
+    Tcl_DecrRefCount(objPtr);
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ForCmd --
+ *
+ *      This procedure is invoked to process the "for" Tcl command.
+ *      See the user documentation for details on what it does.
+ *
+ *	With the bytecode compiler, this procedure is only called when
+ *	a command name is computed at runtime, and is "for" or the name
+ *	to which "for" was renamed: e.g.,
+ *	"set z for; $z {set i 0} {$i<100} {incr i} {puts $i}"
+ *
+ * Results:
+ *      A standard Tcl result.
+ *
+ * Side effects:
+ *      See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+        /* ARGSUSED */
+int
+Tcl_ForCmd(dummy, interp, argc, argv)
+    ClientData dummy;                   /* Not used. */
+    Tcl_Interp *interp;                 /* Current interpreter. */
+    int argc;                           /* Number of arguments. */
+    char **argv;                        /* Argument strings. */
+{
+    int result, value;
+
+    if (argc != 5) {
+        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+                " start test next command\"", (char *) NULL);
+        return TCL_ERROR;
+    }
+
+    result = Tcl_Eval(interp, argv[1]);
+    if (result != TCL_OK) {
+        if (result == TCL_ERROR) {
+            Tcl_AddErrorInfo(interp, "\n    (\"for\" initial command)");
+        }
+        return result;
+    }
+    while (1) {
+        result = Tcl_ExprBoolean(interp, argv[2], &value);
+        if (result != TCL_OK) {
+            return result;
+        }
+        if (!value) {
+            break;
+        }
+        result = Tcl_Eval(interp, argv[4]);
+        if ((result != TCL_OK) && (result != TCL_CONTINUE)) {
+            if (result == TCL_ERROR) {
+                char msg[60];
+                sprintf(msg, "\n    (\"for\" body line %d)",interp->errorLine);
+                Tcl_AddErrorInfo(interp, msg);
+            }
+            break;
+        }
+        result = Tcl_Eval(interp, argv[3]);
+	if (result == TCL_BREAK) {
+            break;
+        } else if (result != TCL_OK) {
+            if (result == TCL_ERROR) {
+                Tcl_AddErrorInfo(interp, "\n    (\"for\" loop-end command)");
+            }
+            return result;
+        }
+    }
+    if (result == TCL_BREAK) {
+        result = TCL_OK;
+    }
+    if (result == TCL_OK) {
+        Tcl_ResetResult(interp);
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ForeachObjCmd --
+ *
+ *	This object-based procedure is invoked to process the "foreach" Tcl
+ *	command.  See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_ForeachObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    int result = TCL_OK;
+    int i;			/* i selects a value list */
+    int j, maxj;		/* Number of loop iterations */
+    int v;			/* v selects a loop variable */
+    int numLists;		/* Count of value lists */
+    Tcl_Obj *bodyPtr;
+
+    /*
+     * We copy the argument object pointers into a local array to avoid
+     * the problem that "objv" might become invalid. It is a pointer into
+     * the evaluation stack and that stack might be grown and reallocated
+     * if the loop body requires a large amount of stack space.
+     */
+    
+#define NUM_ARGS 9
+    Tcl_Obj *(argObjStorage[NUM_ARGS]);
+    Tcl_Obj **argObjv = argObjStorage;
+    
+#define STATIC_LIST_SIZE 4
+    int indexArray[STATIC_LIST_SIZE];	  /* Array of value list indices */
+    int varcListArray[STATIC_LIST_SIZE];  /* # loop variables per list */
+    Tcl_Obj **varvListArray[STATIC_LIST_SIZE]; /* Array of var name lists */
+    int argcListArray[STATIC_LIST_SIZE];  /* Array of value list sizes */
+    Tcl_Obj **argvListArray[STATIC_LIST_SIZE]; /* Array of value lists */
+
+    int *index = indexArray;
+    int *varcList = varcListArray;
+    Tcl_Obj ***varvList = varvListArray;
+    int *argcList = argcListArray;
+    Tcl_Obj ***argvList = argvListArray;
+
+    if (objc < 4 || (objc%2 != 0)) {
+	Tcl_WrongNumArgs(interp, 1, objv,
+		"varList list ?varList list ...? command");
+	return TCL_ERROR;
+    }
+
+    /*
+     * Create the object argument array "argObjv". Make sure argObjv is
+     * large enough to hold the objc arguments.
+     */
+
+    if (objc > NUM_ARGS) {
+	argObjv = (Tcl_Obj **) ckalloc(objc * sizeof(Tcl_Obj *));
+    }
+    for (i = 0;  i < objc;  i++) {
+	argObjv[i] = objv[i];
+    }
+
+    /*
+     * Manage numList parallel value lists.
+     * argvList[i] is a value list counted by argcList[i]
+     * varvList[i] is the list of variables associated with the value list
+     * varcList[i] is the number of variables associated with the value list
+     * index[i] is the current pointer into the value list argvList[i]
+     */
+
+    numLists = (objc-2)/2;
+    if (numLists > STATIC_LIST_SIZE) {
+	index = (int *) ckalloc(numLists * sizeof(int));
+	varcList = (int *) ckalloc(numLists * sizeof(int));
+	varvList = (Tcl_Obj ***) ckalloc(numLists * sizeof(Tcl_Obj **));
+	argcList = (int *) ckalloc(numLists * sizeof(int));
+	argvList = (Tcl_Obj ***) ckalloc(numLists * sizeof(Tcl_Obj **));
+    }
+    for (i = 0;  i < numLists;  i++) {
+	index[i] = 0;
+	varcList[i] = 0;
+	varvList[i] = (Tcl_Obj **) NULL;
+	argcList[i] = 0;
+	argvList[i] = (Tcl_Obj **) NULL;
+    }
+
+    /*
+     * Break up the value lists and variable lists into elements
+     * THIS FAILS IF THE OBJECT'S STRING REP HAS A NULL BYTE.
+     */
+
+    maxj = 0;
+    for (i = 0;  i < numLists;  i++) {
+	result = Tcl_ListObjGetElements(interp, argObjv[1+i*2],
+	        &varcList[i], &varvList[i]);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	if (varcList[i] < 1) {
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	            "foreach varlist is empty", -1);
+	    result = TCL_ERROR;
+	    goto done;
+	}
+	
+	result = Tcl_ListObjGetElements(interp, argObjv[2+i*2],
+	        &argcList[i], &argvList[i]);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	
+	j = argcList[i] / varcList[i];
+	if ((argcList[i] % varcList[i]) != 0) {
+	    j++;
+	}
+	if (j > maxj) {
+	    maxj = j;
+	}
+    }
+
+    /*
+     * Iterate maxj times through the lists in parallel
+     * If some value lists run out of values, set loop vars to ""
+     */
+    
+    bodyPtr = argObjv[objc-1];
+    for (j = 0;  j < maxj;  j++) {
+	for (i = 0;  i < numLists;  i++) {
+	    /*
+	     * If a variable or value list object has been converted to
+	     * another kind of Tcl object, convert it back to a list object
+	     * and refetch the pointer to its element array.
+	     */
+
+	    if (argObjv[1+i*2]->typePtr != &tclListType) {
+		result = Tcl_ListObjGetElements(interp, argObjv[1+i*2],
+		        &varcList[i], &varvList[i]);
+		if (result != TCL_OK) {
+		    panic("Tcl_ForeachObjCmd: could not reconvert variable list %d to a list object\n", i);
+		}
+	    }
+	    if (argObjv[2+i*2]->typePtr != &tclListType) {
+		result = Tcl_ListObjGetElements(interp, argObjv[2+i*2],
+	                &argcList[i], &argvList[i]);
+		if (result != TCL_OK) {
+		    panic("Tcl_ForeachObjCmd: could not reconvert value list %d to a list object\n", i);
+		}
+	    }
+	    
+	    for (v = 0;  v < varcList[i];  v++) {
+		int k = index[i]++;
+		Tcl_Obj *valuePtr, *varValuePtr;
+		int isEmptyObj = 0;
+		
+		if (k < argcList[i]) {
+		    valuePtr = argvList[i][k];
+		} else {
+		    valuePtr = Tcl_NewObj(); /* empty string */
+		    isEmptyObj = 1;
+		}
+		varValuePtr = Tcl_ObjSetVar2(interp, varvList[i][v], NULL,
+			valuePtr, TCL_PARSE_PART1);
+		if (varValuePtr == NULL) {
+		    if (isEmptyObj) {
+			Tcl_DecrRefCount(valuePtr);
+		    }
+		    Tcl_ResetResult(interp);
+		    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+			"couldn't set loop variable: \"",
+			Tcl_GetStringFromObj(varvList[i][v], (int *) NULL),
+			"\"", (char *) NULL);
+		    result = TCL_ERROR;
+		    goto done;
+		}
+
+	    }
+	}
+
+	result = Tcl_EvalObj(interp, bodyPtr);
+	if (result != TCL_OK) {
+	    if (result == TCL_CONTINUE) {
+		result = TCL_OK;
+	    } else if (result == TCL_BREAK) {
+		result = TCL_OK;
+		break;
+	    } else if (result == TCL_ERROR) {
+		char msg[100];
+		sprintf(msg, "\n    (\"foreach\" body line %d)",
+			interp->errorLine);
+		Tcl_AddObjErrorInfo(interp, msg, -1);
+		break;
+	    } else {
+		break;
+	    }
+	}
+    }
+    if (result == TCL_OK) {
+	Tcl_ResetResult(interp);
+    }
+
+    done:
+    if (numLists > STATIC_LIST_SIZE) {
+	ckfree((char *) index);
+	ckfree((char *) varcList);
+	ckfree((char *) argcList);
+	ckfree((char *) varvList);
+	ckfree((char *) argvList);
+    }
+    if (argObjv != argObjStorage) {
+	ckfree((char *) argObjv);
+    }
+    return result;
+#undef STATIC_LIST_SIZE
+#undef NUM_ARGS
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_FormatObjCmd --
+ *
+ *	This procedure is invoked to process the "format" Tcl command.
+ *	See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_FormatObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;    	/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    register char *format;	/* Used to read characters from the format
+				 * string. */
+    int formatLen;              /* The length of the format string */
+    char *endPtr;               /* Points to the last char in format array */
+    char newFormat[40];		/* A new format specifier is generated here. */
+    int width;			/* Field width from field specifier, or 0 if
+				 * no width given. */
+    int precision;		/* Field precision from field specifier, or 0
+				 * if no precision given. */
+    int size;			/* Number of bytes needed for result of
+				 * conversion, based on type of conversion
+				 * ("e", "s", etc.), width, and precision. */
+    int intValue;		/* Used to hold value to pass to sprintf, if
+				 * it's a one-word integer or char value */
+    char *ptrValue = NULL;	/* Used to hold value to pass to sprintf, if
+				 * it's a one-word value. */
+    double doubleValue;		/* Used to hold value to pass to sprintf if
+				 * it's a double value. */
+    int whichValue;		/* Indicates which of intValue, ptrValue,
+				 * or doubleValue has the value to pass to
+				 * sprintf, according to the following
+				 * definitions: */
+#   define INT_VALUE 0
+#   define PTR_VALUE 1
+#   define DOUBLE_VALUE 2
+#   define MAX_FLOAT_SIZE 320
+    
+    Tcl_Obj *resultPtr;  	/* Where result is stored finally. */
+    char staticBuf[MAX_FLOAT_SIZE + 1];
+                                /* A static buffer to copy the format results 
+				 * into */
+    char *dst = staticBuf;      /* The buffer that sprintf writes into each
+				 * time the format processes a specifier */
+    int dstSize = MAX_FLOAT_SIZE;
+                                /* The size of the dst buffer */
+    int noPercent;		/* Special case for speed:  indicates there's
+				 * no field specifier, just a string to copy.*/
+    int objIndex;		/* Index of argument to substitute next. */
+    int gotXpg = 0;		/* Non-zero means that an XPG3 %n$-style
+				 * specifier has been seen. */
+    int gotSequential = 0;	/* Non-zero means that a regular sequential
+				 * (non-XPG3) conversion specifier has been
+				 * seen. */
+    int useShort;		/* Value to be printed is short (half word). */
+    char *end;			/* Used to locate end of numerical fields. */
+
+    /*
+     * This procedure is a bit nasty.  The goal is to use sprintf to
+     * do most of the dirty work.  There are several problems:
+     * 1. this procedure can't trust its arguments.
+     * 2. we must be able to provide a large enough result area to hold
+     *    whatever's generated.  This is hard to estimate.
+     * 2. there's no way to move the arguments from objv to the call
+     *    to sprintf in a reasonable way.  This is particularly nasty
+     *    because some of the arguments may be two-word values (doubles).
+     * So, what happens here is to scan the format string one % group
+     * at a time, making many individual calls to sprintf.
+     */
+
+    if (objc < 2) {
+        Tcl_WrongNumArgs(interp, 1, objv,
+		"formatString ?arg arg ...?");
+	return TCL_ERROR;
+    }
+
+    format = Tcl_GetStringFromObj(objv[1], &formatLen);
+    endPtr = format + formatLen;
+    resultPtr = Tcl_NewObj();
+    objIndex = 2;
+
+    while (format < endPtr) {
+	register char *newPtr = newFormat;
+
+	width = precision = noPercent = useShort = 0;
+	whichValue = PTR_VALUE;
+
+	/*
+	 * Get rid of any characters before the next field specifier.
+	 */
+	if (*format != '%') {
+	    ptrValue = format;
+	    while ((*format != '%') && (format < endPtr)) {
+		format++;
+	    }
+	    size = format - ptrValue;
+	    noPercent = 1;
+	    goto doField;
+	}
+
+	if (format[1] == '%') {
+	    ptrValue = format;
+	    size = 1;
+	    noPercent = 1;
+	    format += 2;
+	    goto doField;
+	}
+
+	/*
+	 * Parse off a field specifier, compute how many characters
+	 * will be needed to store the result, and substitute for
+	 * "*" size specifiers.
+	 */
+	*newPtr = '%';
+	newPtr++;
+	format++;
+	if (isdigit(UCHAR(*format))) {
+	    int tmp;
+
+	    /*
+	     * Check for an XPG3-style %n$ specification.  Note: there
+	     * must not be a mixture of XPG3 specs and non-XPG3 specs
+	     * in the same format string.
+	     */
+
+	    tmp = strtoul(format, &end, 10);
+	    if (*end != '$') {
+		goto notXpg;
+	    }
+	    format = end+1;
+	    gotXpg = 1;
+	    if (gotSequential) {
+		goto mixedXPG;
+	    }
+	    objIndex = tmp+1;
+	    if ((objIndex < 2) || (objIndex >= objc)) {
+		goto badIndex;
+	    }
+	    goto xpgCheckDone;
+	}
+
+	notXpg:
+	gotSequential = 1;
+	if (gotXpg) {
+	    goto mixedXPG;
+	}
+
+	xpgCheckDone:
+	while ((*format == '-') || (*format == '#') || (*format == '0')
+		|| (*format == ' ') || (*format == '+')) {
+	    *newPtr = *format;
+	    newPtr++;
+	    format++;
+	}
+	if (isdigit(UCHAR(*format))) {
+	    width = strtoul(format, &end, 10);
+	    format = end;
+	} else if (*format == '*') {
+	    if (objIndex >= objc) {
+		goto badIndex;
+	    }
+	    if (Tcl_GetIntFromObj(interp, objv[objIndex], 
+                    &width) != TCL_OK) {
+		goto fmtError;
+	    }
+	    objIndex++;
+	    format++;
+	}
+	if (width > 100000) {
+	    /*
+	     * Don't allow arbitrarily large widths:  could cause core
+	     * dump when we try to allocate a zillion bytes of memory
+	     * below.
+	     */
+
+	    width = 100000;
+	} else if (width < 0) {
+	    width = 0;
+	}
+	if (width != 0) {
+	    TclFormatInt(newPtr, width);
+	    while (*newPtr != 0) {
+		newPtr++;
+	    }
+	}
+	if (*format == '.') {
+	    *newPtr = '.';
+	    newPtr++;
+	    format++;
+	}
+	if (isdigit(UCHAR(*format))) {
+	    precision = strtoul(format, &end, 10);
+	    format = end;
+	} else if (*format == '*') {
+	    if (objIndex >= objc) {
+		goto badIndex;
+	    }
+	    if (Tcl_GetIntFromObj(interp, objv[objIndex], 
+                    &precision) != TCL_OK) {
+		goto fmtError;
+	    }
+	    objIndex++;
+	    format++;
+	}
+	if (precision != 0) {
+	    TclFormatInt(newPtr, precision);
+	    while (*newPtr != 0) {
+		newPtr++;
+	    }
+	}
+	if (*format == 'l') {
+	    format++;
+	} else if (*format == 'h') {
+	    useShort = 1;
+	    *newPtr = 'h';
+	    newPtr++;
+	    format++;
+	}
+	*newPtr = *format;
+	newPtr++;
+	*newPtr = 0;
+	if (objIndex >= objc) {
+	    goto badIndex;
+	}
+	switch (*format) {
+	    case 'i':
+		newPtr[-1] = 'd';
+	    case 'd':
+	    case 'o':
+	    case 'u':
+	    case 'x':
+	    case 'X':
+		if (Tcl_GetIntFromObj(interp, objv[objIndex], 
+		        (int *) &intValue) != TCL_OK) {
+		    goto fmtError;
+		}
+		whichValue = INT_VALUE;
+		size = 40 + precision;
+		break;
+	    case 's':
+		ptrValue = Tcl_GetStringFromObj(objv[objIndex], &size);
+		break;
+	    case 'c':
+		if (Tcl_GetIntFromObj(interp, objv[objIndex], 
+                        (int *) &intValue) != TCL_OK) {
+		    goto fmtError;
+		}
+		whichValue = INT_VALUE;
+		size = 1;
+		break;
+	    case 'e':
+	    case 'E':
+	    case 'f':
+	    case 'g':
+	    case 'G':
+		if (Tcl_GetDoubleFromObj(interp, objv[objIndex], 
+			&doubleValue) != TCL_OK) {
+		    goto fmtError;
+		}
+		whichValue = DOUBLE_VALUE;
+		size = MAX_FLOAT_SIZE;
+		if (precision > 10) {
+		    size += precision;
+		}
+		break;
+	    case 0:
+		Tcl_SetResult(interp,
+		        "format string ended in middle of field specifier",
+			TCL_STATIC);
+		goto fmtError;
+	    default:
+		{
+		    char buf[40];
+		    sprintf(buf, "bad field specifier \"%c\"", *format);
+		    Tcl_SetResult(interp, buf, TCL_VOLATILE);
+		    goto fmtError;
+		}
+	}
+	objIndex++;
+	format++;
+
+	/*
+	 * Make sure that there's enough space to hold the formatted
+	 * result, then format it.
+	 */
+
+	doField:
+	if (width > size) {
+	    size = width;
+	}
+	if (noPercent) {
+	    Tcl_AppendToObj(resultPtr, ptrValue, size);
+	} else {
+	    if (size > dstSize) {
+	        if (dst != staticBuf) {
+		    ckfree(dst);
+		}
+		dst = (char *) ckalloc((unsigned) (size + 1));
+		dstSize = size;
+	    }
+
+	    if (whichValue == DOUBLE_VALUE) {
+	        sprintf(dst, newFormat, doubleValue);
+	    } else if (whichValue == INT_VALUE) {
+		if (useShort) {
+		    sprintf(dst, newFormat, (short) intValue);
+		} else {
+		    sprintf(dst, newFormat, intValue);
+		}
+	    } else {
+	        sprintf(dst, newFormat, ptrValue);
+	    }
+	    Tcl_AppendToObj(resultPtr, dst, -1);
+	}
+    }
+
+    Tcl_SetObjResult(interp, resultPtr);
+    if(dst != staticBuf) {
+        ckfree(dst);
+    }
+    return TCL_OK;
+
+    mixedXPG:
+    Tcl_SetResult(interp, 
+            "cannot mix \"%\" and \"%n$\" conversion specifiers", TCL_STATIC);
+    goto fmtError;
+
+    badIndex:
+    if (gotXpg) {
+        Tcl_SetResult(interp, 
+                "\"%n$\" argument index out of range", TCL_STATIC);
+    } else {
+        Tcl_SetResult(interp, 
+                "not enough arguments for all format specifiers", TCL_STATIC);
+    }
+
+    fmtError:
+    if(dst != staticBuf) {
+        ckfree(dst);
+    }
+    Tcl_DecrRefCount(resultPtr);
+    return TCL_ERROR;
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclCmdIL.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclCmdIL.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclCmdIL.c	(revision 5)
@@ -0,0 +1,2771 @@
+/* 
+ * tclCmdIL.c --
+ *
+ *	This file contains the top-level command routines for most of
+ *	the Tcl built-in commands whose names begin with the letters
+ *	I through L.  It contains only commands in the generic core
+ *	(i.e. those that don't depend much upon UNIX facilities).
+ *
+ * Copyright (c) 1987-1993 The Regents of the University of California.
+ * Copyright (c) 1993-1997 Lucent Technologies.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclCmdIL.c,v 1.1 2008-06-04 13:58:04 demin Exp $
+ */
+
+#include "tclInt.h"
+#include "tclPort.h"
+#include "tclCompile.h"
+
+/*
+ * During execution of the "lsort" command, structures of the following
+ * type are used to arrange the objects being sorted into a collection
+ * of linked lists.
+ */
+
+typedef struct SortElement {
+    Tcl_Obj *objPtr;			/* Object being sorted. */
+    struct SortElement *nextPtr;        /* Next element in the list, or
+					 * NULL for end of list. */
+} SortElement;
+
+/*
+ * The "lsort" command needs to pass certain information down to the
+ * function that compares two list elements, and the comparison function
+ * needs to pass success or failure information back up to the top-level
+ * "lsort" command.  The following structure is used to pass this
+ * information.
+ */
+
+typedef struct SortInfo {
+    int isIncreasing;		/* Nonzero means sort in increasing order. */
+    int sortMode;		/* The sort mode.  One of SORTMODE_*
+				 * values defined below */
+    Tcl_DString compareCmd;	/* The Tcl comparison command when sortMode
+				 * is SORTMODE_COMMAND.  Pre-initialized to
+				 * hold base of command.*/
+    int index;			/* If the -index option was specified, this
+				 * holds the index of the list element
+				 * to extract for comparison.  If -index
+				 * wasn't specified, this is -1. */
+    Tcl_Interp *interp;		/* The interpreter in which the sortis
+				 * being done. */
+    int resultCode;		/* Completion code for the lsort command.
+				 * If an error occurs during the sort this
+				 * is changed from TCL_OK to  TCL_ERROR. */
+} SortInfo;
+
+/*
+ * The "sortMode" field of the SortInfo structure can take on any of the
+ * following values.
+ */
+
+#define SORTMODE_ASCII      0
+#define SORTMODE_INTEGER    1
+#define SORTMODE_REAL       2
+#define SORTMODE_COMMAND    3
+#define SORTMODE_DICTIONARY 4
+
+/*
+ * Forward declarations for procedures defined in this file:
+ */
+
+static void		AppendLocals _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *listPtr, char *pattern,
+			    int includeLinks));
+static int		DictionaryCompare _ANSI_ARGS_((char *left,
+			    char *right));
+static int		InfoArgsCmd _ANSI_ARGS_((ClientData dummy,
+			    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static int		InfoBodyCmd _ANSI_ARGS_((ClientData dummy,
+			    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static int		InfoCmdCountCmd _ANSI_ARGS_((ClientData dummy,
+			    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static int		InfoCommandsCmd _ANSI_ARGS_((ClientData dummy,
+			    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static int		InfoCompleteCmd _ANSI_ARGS_((ClientData dummy,
+			    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static int		InfoDefaultCmd _ANSI_ARGS_((ClientData dummy,
+			    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static int		InfoExistsCmd _ANSI_ARGS_((ClientData dummy,
+			    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static int		InfoGlobalsCmd _ANSI_ARGS_((ClientData dummy,
+			    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static int		InfoLevelCmd _ANSI_ARGS_((ClientData dummy,
+			    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static int		InfoLibraryCmd _ANSI_ARGS_((ClientData dummy,
+			    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static int		InfoLocalsCmd _ANSI_ARGS_((ClientData dummy,
+			    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static int		InfoNameOfExecutableCmd _ANSI_ARGS_((
+			    ClientData dummy, Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static int		InfoPatchLevelCmd _ANSI_ARGS_((ClientData dummy,
+			    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static int		InfoProcsCmd _ANSI_ARGS_((ClientData dummy,
+			    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static int		InfoScriptCmd _ANSI_ARGS_((ClientData dummy,
+			    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static int		InfoSharedlibCmd _ANSI_ARGS_((ClientData dummy,
+			    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static int		InfoTclVersionCmd _ANSI_ARGS_((ClientData dummy,
+			    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static int		InfoVarsCmd _ANSI_ARGS_((ClientData dummy,
+			    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+static SortElement *    MergeSort _ANSI_ARGS_((SortElement *headPt,
+			    SortInfo *infoPtr));
+static SortElement *    MergeLists _ANSI_ARGS_((SortElement *leftPtr,
+			    SortElement *rightPtr, SortInfo *infoPtr));
+static int		SortCompare _ANSI_ARGS_((Tcl_Obj *firstPtr,
+			    Tcl_Obj *second, SortInfo *infoPtr));
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_IfCmd --
+ *
+ *	This procedure is invoked to process the "if" Tcl command.
+ *	See the user documentation for details on what it does.
+ *
+ *	With the bytecode compiler, this procedure is only called when
+ *	a command name is computed at runtime, and is "if" or the name
+ *	to which "if" was renamed: e.g., "set z if; $z 1 {puts foo}"
+ *
+ * Results:
+ *	A standard Tcl result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_IfCmd(dummy, interp, argc, argv)
+    ClientData dummy;			/* Not used. */
+    Tcl_Interp *interp;			/* Current interpreter. */
+    int argc;				/* Number of arguments. */
+    char **argv;			/* Argument strings. */
+{
+    int i, result, value;
+
+    i = 1;
+    while (1) {
+	/*
+	 * At this point in the loop, argv and argc refer to an expression
+	 * to test, either for the main expression or an expression
+	 * following an "elseif".  The arguments after the expression must
+	 * be "then" (optional) and a script to execute if the expression is
+	 * true.
+	 */
+
+	if (i >= argc) {
+	    Tcl_AppendResult(interp, "wrong # args: no expression after \"",
+		    argv[i-1], "\" argument", (char *) NULL);
+	    return TCL_ERROR;
+	}
+	result = Tcl_ExprBoolean(interp, argv[i], &value);
+	if (result != TCL_OK) {
+	    return result;
+	}
+	i++;
+	if ((i < argc) && (strcmp(argv[i], "then") == 0)) {
+	    i++;
+	}
+	if (i >= argc) {
+	    Tcl_AppendResult(interp, "wrong # args: no script following \"",
+		    argv[i-1], "\" argument", (char *) NULL);
+	    return TCL_ERROR;
+	}
+	if (value) {
+	    return Tcl_Eval(interp, argv[i]);
+	}
+	
+	/*
+	 * The expression evaluated to false.  Skip the command, then
+	 * see if there is an "else" or "elseif" clause.
+	 */
+
+	i++;
+	if (i >= argc) {
+	    return TCL_OK;
+	}
+	if ((argv[i][0] == 'e') && (strcmp(argv[i], "elseif") == 0)) {
+	    i++;
+	    continue;
+	}
+	break;
+    }
+
+    /*
+     * Couldn't find a "then" or "elseif" clause to execute.  Check now
+     * for an "else" clause.  We know that there's at least one more
+     * argument when we get here.
+     */
+
+    if (strcmp(argv[i], "else") == 0) {
+	i++;
+	if (i >= argc) {
+	    Tcl_AppendResult(interp,
+		    "wrong # args: no script following \"else\" argument",
+		    (char *) NULL);
+	    return TCL_ERROR;
+	}
+    }
+    return Tcl_Eval(interp, argv[i]);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_IncrCmd --
+ *
+ *	This procedure is invoked to process the "incr" Tcl command.
+ *	See the user documentation for details on what it does.
+ *
+ *	With the bytecode compiler, this procedure is only called when
+ *	a command name is computed at runtime, and is "incr" or the name
+ *	to which "incr" was renamed: e.g., "set z incr; $z i -1"
+ *
+ * Results:
+ *	A standard Tcl result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+    /* ARGSUSED */
+int
+Tcl_IncrCmd(dummy, interp, argc, argv)
+    ClientData dummy;			/* Not used. */
+    Tcl_Interp *interp;			/* Current interpreter. */
+    int argc;				/* Number of arguments. */
+    char **argv;			/* Argument strings. */
+{
+    int value;
+    char *oldString, *result;
+    char newString[30];
+
+    if ((argc != 2) && (argc != 3)) {
+	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+		" varName ?increment?\"", (char *) NULL);
+	return TCL_ERROR;
+    }
+
+    oldString = Tcl_GetVar(interp, argv[1], TCL_LEAVE_ERR_MSG);
+    if (oldString == NULL) {
+	return TCL_ERROR;
+    }
+    if (Tcl_GetInt(interp, oldString, &value) != TCL_OK) {
+	Tcl_AddErrorInfo(interp,
+		"\n    (reading value of variable to increment)");
+	return TCL_ERROR;
+    }
+    if (argc == 2) {
+	value += 1;
+    } else {
+	int increment;
+
+	if (Tcl_GetInt(interp, argv[2], &increment) != TCL_OK) {
+	    Tcl_AddErrorInfo(interp,
+		    "\n    (reading increment)");
+	    return TCL_ERROR;
+	}
+	value += increment;
+    }
+    TclFormatInt(newString, value);
+    result = Tcl_SetVar(interp, argv[1], newString, TCL_LEAVE_ERR_MSG);
+    if (result == NULL) {
+	return TCL_ERROR;
+    }
+
+    /*
+     * Copy the result since the variable's value might change.
+     */
+    
+    Tcl_SetResult(interp, result, TCL_VOLATILE);
+    return TCL_OK; 
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_InfoObjCmd --
+ *
+ *	This procedure is invoked to process the "info" Tcl command.
+ *	See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_InfoObjCmd(clientData, interp, objc, objv)
+    ClientData clientData;	/* Arbitrary value passed to the command. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    static char *subCmds[] = {
+       "args", "body", "cmdcount", "commands",
+	     "complete", "default", "exists", "globals",
+	     "level", "library",
+	     "locals", "nameofexecutable", "patchlevel", "procs",
+	     "script", "sharedlibextension", "tclversion", "vars",
+	     (char *) NULL};
+    enum ISubCmdIdx {
+	    IArgsIdx, IBodyIdx, ICmdCountIdx, ICommandsIdx,
+	    ICompleteIdx, IDefaultIdx, IExistsIdx, IGlobalsIdx,
+      ILevelIdx, ILibraryIdx,
+	    ILocalsIdx, INameOfExecutableIdx, IPatchLevelIdx, IProcsIdx,
+	    IScriptIdx, ISharedLibExtensionIdx, ITclVersionIdx, IVarsIdx
+    } index;
+    int result;
+
+    if (objc < 2) {
+        Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
+        return TCL_ERROR;
+    }
+    
+    result = Tcl_GetIndexFromObj(interp, objv[1], subCmds, "option", 0,
+	    (int *) &index);
+    if (result != TCL_OK) {
+	return result;
+    }
+
+    switch (index) {
+        case IArgsIdx:
+	    result = InfoArgsCmd(clientData, interp, objc, objv);
+            break;
+	case IBodyIdx:
+	    result = InfoBodyCmd(clientData, interp, objc, objv);
+	    break;
+	case ICmdCountIdx:
+	    result = InfoCmdCountCmd(clientData, interp, objc, objv);
+	    break;
+        case ICommandsIdx:
+	    result = InfoCommandsCmd(clientData, interp, objc, objv);
+	    break;
+        case ICompleteIdx:
+	    result = InfoCompleteCmd(clientData, interp, objc, objv);
+	    break;
+	case IDefaultIdx:
+	    result = InfoDefaultCmd(clientData, interp, objc, objv);
+	    break;
+	case IExistsIdx:
+	    result = InfoExistsCmd(clientData, interp, objc, objv);
+	    break;
+	case IGlobalsIdx:
+	    result = InfoGlobalsCmd(clientData, interp, objc, objv);
+	    break;
+	case ILevelIdx:
+	    result = InfoLevelCmd(clientData, interp, objc, objv);
+	    break;
+	case ILibraryIdx:
+	    result = InfoLibraryCmd(clientData, interp, objc, objv);
+	    break;
+	case ILocalsIdx:
+	    result = InfoLocalsCmd(clientData, interp, objc, objv);
+	    break;
+	case INameOfExecutableIdx:
+	    result = InfoNameOfExecutableCmd(clientData, interp, objc, objv);
+	    break;
+	case IPatchLevelIdx:
+	    result = InfoPatchLevelCmd(clientData, interp, objc, objv);
+	    break;
+        case IProcsIdx:
+	    result = InfoProcsCmd(clientData, interp, objc, objv);
+	    break;
+        case IScriptIdx:
+	    result = InfoScriptCmd(clientData, interp, objc, objv);
+	    break;
+	case ISharedLibExtensionIdx:
+	    result = InfoSharedlibCmd(clientData, interp, objc, objv);
+	    break;
+	case ITclVersionIdx:
+	    result = InfoTclVersionCmd(clientData, interp, objc, objv);
+	    break;
+	case IVarsIdx:
+	    result = InfoVarsCmd(clientData, interp, objc, objv);
+	    break;
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoArgsCmd --
+ *
+ *      Called to implement the "info args" command that returns the
+ *      argument list for a procedure. Handles the following syntax:
+ *
+ *          info args procName
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoArgsCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    register Interp *iPtr = (Interp *) interp;
+    char *name;
+    Proc *procPtr;
+    CompiledLocal *localPtr;
+    Tcl_Obj *listObjPtr;
+
+    if (objc != 3) {
+        Tcl_WrongNumArgs(interp, 2, objv, "procname");
+        return TCL_ERROR;
+    }
+
+    name = Tcl_GetStringFromObj(objv[2], (int *) NULL);
+    procPtr = TclFindProc(iPtr, name);
+    if (procPtr == NULL) {
+        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                "\"", name, "\" isn't a procedure", (char *) NULL);
+        return TCL_ERROR;
+    }
+
+    /*
+     * Build a return list containing the arguments.
+     */
+    
+    listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+    for (localPtr = procPtr->firstLocalPtr;  localPtr != NULL;
+            localPtr = localPtr->nextPtr) {
+        if (TclIsVarArgument(localPtr)) {
+            Tcl_ListObjAppendElement(interp, listObjPtr,
+		    Tcl_NewStringObj(localPtr->name, -1));
+        }
+    }
+    Tcl_SetObjResult(interp, listObjPtr);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoBodyCmd --
+ *
+ *      Called to implement the "info body" command that returns the body
+ *      for a procedure. Handles the following syntax:
+ *
+ *          info body procName
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoBodyCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    register Interp *iPtr = (Interp *) interp;
+    char *name;
+    Proc *procPtr;
+    Tcl_Obj *bodyPtr, *resultPtr;
+    
+    if (objc != 3) {
+        Tcl_WrongNumArgs(interp, 2, objv, "procname");
+        return TCL_ERROR;
+    }
+
+    name = Tcl_GetStringFromObj(objv[2], (int *) NULL);
+    procPtr = TclFindProc(iPtr, name);
+    if (procPtr == NULL) {
+        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		"\"", name, "\" isn't a procedure", (char *) NULL);
+        return TCL_ERROR;
+    }
+
+    /*
+     * we need to check if the body from this procedure had been generated
+     * from a precompiled body. If that is the case, then the bodyPtr's
+     * string representation is bogus, since sources are not available.
+     * In order to make sure that later manipulations of the object do not
+     * invalidate the internal representation, we make a copy of the string
+     * representation and return that one, instead.
+     */
+
+    bodyPtr = procPtr->bodyPtr;
+    resultPtr = bodyPtr;
+    if (bodyPtr->typePtr == &tclByteCodeType) {
+        ByteCode *codePtr = (ByteCode *) bodyPtr->internalRep.otherValuePtr;
+
+        if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
+            resultPtr = Tcl_NewStringObj(bodyPtr->bytes, bodyPtr->length);
+        }
+    }
+    
+    Tcl_SetObjResult(interp, resultPtr);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoCmdCountCmd --
+ *
+ *      Called to implement the "info cmdcount" command that returns the
+ *      number of commands that have been executed. Handles the following
+ *      syntax:
+ *
+ *          info cmdcount
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoCmdCountCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Interp *iPtr = (Interp *) interp;
+    
+    if (objc != 2) {
+        Tcl_WrongNumArgs(interp, 2, objv, NULL);
+        return TCL_ERROR;
+    }
+
+    Tcl_SetIntObj(Tcl_GetObjResult(interp), iPtr->cmdCount);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoCommandsCmd --
+ *
+ *	Called to implement the "info commands" command that returns the
+ *	list of commands in the interpreter that match an optional pattern.
+ *	The pattern, if any, consists of an optional sequence of namespace
+ *	names separated by "::" qualifiers, which is followed by a
+ *	glob-style pattern that restricts which commands are returned.
+ *	Handles the following syntax:
+ *
+ *          info commands ?pattern?
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoCommandsCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    char *cmdName, *pattern, *simplePattern;
+    register Tcl_HashEntry *entryPtr;
+    Tcl_HashSearch search;
+    Namespace *nsPtr;
+    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
+    Namespace *currNsPtr   = (Namespace *) Tcl_GetCurrentNamespace(interp);
+    Tcl_Obj *listPtr, *elemObjPtr;
+    int specificNsInPattern = 0;  /* Init. to avoid compiler warning. */
+    Tcl_Command cmd;
+
+    /*
+     * Get the pattern and find the "effective namespace" in which to
+     * list commands.
+     */
+
+    if (objc == 2) {
+        simplePattern = NULL;
+	nsPtr = currNsPtr;
+	specificNsInPattern = 0;
+    } else if (objc == 3) {
+	/*
+	 * From the pattern, get the effective namespace and the simple
+	 * pattern (no namespace qualifiers or ::'s) at the end. If an
+	 * error was found while parsing the pattern, return it. Otherwise,
+	 * if the namespace wasn't found, just leave nsPtr NULL: we will
+	 * return an empty list since no commands there can be found.
+	 */
+
+	Namespace *dummy1NsPtr, *dummy2NsPtr;
+	
+        pattern = Tcl_GetStringFromObj(objv[2], (int *) NULL);
+       TclGetNamespaceForQualName(interp, pattern, (Namespace *) NULL,
+           /*flags*/ 0, &nsPtr, &dummy1NsPtr, &dummy2NsPtr, &simplePattern);
+
+	if (nsPtr != NULL) {	/* we successfully found the pattern's ns */
+	    specificNsInPattern = (strcmp(simplePattern, pattern) != 0);
+	}
+    } else {
+        Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
+        return TCL_ERROR;
+    }
+
+    /*
+     * Scan through the effective namespace's command table and create a
+     * list with all commands that match the pattern. If a specific
+     * namespace was requested in the pattern, qualify the command names
+     * with the namespace name.
+     */
+
+    listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+
+    if (nsPtr != NULL) {
+	entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
+	while (entryPtr != NULL) {
+	    cmdName = Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr);
+	    if ((simplePattern == NULL)
+	            || Tcl_StringMatch(cmdName, simplePattern)) {
+		if (specificNsInPattern) {
+		    cmd = (Tcl_Command) Tcl_GetHashValue(entryPtr);
+		    elemObjPtr = Tcl_NewObj();
+		    Tcl_GetCommandFullName(interp, cmd, elemObjPtr);
+		} else {
+		    elemObjPtr = Tcl_NewStringObj(cmdName, -1);
+		}
+		Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
+	    }
+	    entryPtr = Tcl_NextHashEntry(&search);
+	}
+
+	/*
+	 * If the effective namespace isn't the global :: namespace, and a
+	 * specific namespace wasn't requested in the pattern, then add in
+	 * all global :: commands that match the simple pattern. Of course,
+	 * we add in only those commands that aren't hidden by a command in
+	 * the effective namespace.
+	 */
+	
+	if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
+	    entryPtr = Tcl_FirstHashEntry(&globalNsPtr->cmdTable, &search);
+	    while (entryPtr != NULL) {
+		cmdName = Tcl_GetHashKey(&globalNsPtr->cmdTable, entryPtr);
+		if ((simplePattern == NULL)
+	                || Tcl_StringMatch(cmdName, simplePattern)) {
+		    if (Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName) == NULL) {
+			Tcl_ListObjAppendElement(interp, listPtr,
+				Tcl_NewStringObj(cmdName, -1));
+		    }
+		}
+		entryPtr = Tcl_NextHashEntry(&search);
+	    }
+	}
+    }
+    
+    Tcl_SetObjResult(interp, listPtr);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoCompleteCmd --
+ *
+ *      Called to implement the "info complete" command that determines
+ *      whether a string is a complete Tcl command. Handles the following
+ *      syntax:
+ *
+ *          info complete command
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoCompleteCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    if (objc != 3) {
+        Tcl_WrongNumArgs(interp, 2, objv, "command");
+        return TCL_ERROR;
+    }
+
+    if (TclObjCommandComplete(objv[2])) {
+	Tcl_SetIntObj(Tcl_GetObjResult(interp), 1);
+    } else {
+	Tcl_SetIntObj(Tcl_GetObjResult(interp), 0);
+    }
+
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoDefaultCmd --
+ *
+ *      Called to implement the "info default" command that returns the
+ *      default value for a procedure argument. Handles the following
+ *      syntax:
+ *
+ *          info default procName arg varName
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoDefaultCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Interp *iPtr = (Interp *) interp;
+    char *procName, *argName, *varName;
+    Proc *procPtr;
+    CompiledLocal *localPtr;
+    Tcl_Obj *valueObjPtr;
+
+    if (objc != 5) {
+        Tcl_WrongNumArgs(interp, 2, objv, "procname arg varname");
+        return TCL_ERROR;
+    }
+
+    procName = Tcl_GetStringFromObj(objv[2], (int *) NULL);
+    argName = Tcl_GetStringFromObj(objv[3], (int *) NULL);
+
+    procPtr = TclFindProc(iPtr, procName);
+    if (procPtr == NULL) {
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		"\"", procName, "\" isn't a procedure", (char *) NULL);
+        return TCL_ERROR;
+    }
+
+    for (localPtr = procPtr->firstLocalPtr;  localPtr != NULL;
+            localPtr = localPtr->nextPtr) {
+        if (TclIsVarArgument(localPtr)
+		&& (strcmp(argName, localPtr->name) == 0)) {
+            if (localPtr->defValuePtr != NULL) {
+		valueObjPtr = Tcl_ObjSetVar2(interp, objv[4], NULL,
+                        localPtr->defValuePtr, 0);
+                if (valueObjPtr == NULL) {
+                    defStoreError:
+		    varName = Tcl_GetStringFromObj(objv[4], (int *) NULL);
+		    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+	                    "couldn't store default value in variable \"",
+			    varName, "\"", (char *) NULL);
+                    return TCL_ERROR;
+                }
+		Tcl_SetIntObj(Tcl_GetObjResult(interp), 1);
+            } else {
+                Tcl_Obj *nullObjPtr = Tcl_NewObj();
+                valueObjPtr = Tcl_ObjSetVar2(interp, objv[4], NULL,
+                    nullObjPtr, 0);
+                if (valueObjPtr == NULL) {
+                    Tcl_DecrRefCount(nullObjPtr); /* free unneeded obj */
+                    goto defStoreError;
+                }
+		Tcl_SetIntObj(Tcl_GetObjResult(interp), 0);
+            }
+            return TCL_OK;
+        }
+    }
+
+    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+	    "procedure \"", procName, "\" doesn't have an argument \"",
+	    argName, "\"", (char *) NULL);
+    return TCL_ERROR;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoExistsCmd --
+ *
+ *      Called to implement the "info exists" command that determines
+ *      whether a variable exists. Handles the following syntax:
+ *
+ *          info exists varName
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoExistsCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    char *varName;
+    Var *varPtr, *arrayPtr;
+
+    if (objc != 3) {
+        Tcl_WrongNumArgs(interp, 2, objv, "varName");
+        return TCL_ERROR;
+    }
+
+    varName = Tcl_GetStringFromObj(objv[2], (int *) NULL);
+    varPtr = TclLookupVar(interp, varName, (char *) NULL,
+            TCL_PARSE_PART1, "access",
+            /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
+    if ((varPtr != NULL) && !TclIsVarUndefined(varPtr)) {
+        Tcl_SetIntObj(Tcl_GetObjResult(interp), 1);
+    } else {
+        Tcl_SetIntObj(Tcl_GetObjResult(interp), 0);
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoGlobalsCmd --
+ *
+ *      Called to implement the "info globals" command that returns the list
+ *      of global variables matching an optional pattern. Handles the
+ *      following syntax:
+ *
+ *          info globals ?pattern?
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoGlobalsCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    char *varName, *pattern;
+    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
+    register Tcl_HashEntry *entryPtr;
+    Tcl_HashSearch search;
+    Var *varPtr;
+    Tcl_Obj *listPtr;
+
+    if (objc == 2) {
+        pattern = NULL;
+    } else if (objc == 3) {
+        pattern = Tcl_GetStringFromObj(objv[2], (int *) NULL);
+    } else {
+        Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
+        return TCL_ERROR;
+    }
+
+    /*
+     * Scan through the global :: namespace's variable table and create a
+     * list of all global variables that match the pattern.
+     */
+    
+    listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+    for (entryPtr = Tcl_FirstHashEntry(&globalNsPtr->varTable, &search);
+            entryPtr != NULL;
+            entryPtr = Tcl_NextHashEntry(&search)) {
+        varPtr = (Var *) Tcl_GetHashValue(entryPtr);
+        if (TclIsVarUndefined(varPtr)) {
+            continue;
+        }
+        varName = Tcl_GetHashKey(&globalNsPtr->varTable, entryPtr);
+        if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) {
+            Tcl_ListObjAppendElement(interp, listPtr,
+		    Tcl_NewStringObj(varName, -1));
+        }
+    }
+    Tcl_SetObjResult(interp, listPtr);
+    return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoLevelCmd --
+ *
+ *      Called to implement the "info level" command that returns
+ *      information about the call stack. Handles the following syntax:
+ *
+ *          info level ?number?
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoLevelCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Interp *iPtr = (Interp *) interp;
+    int level;
+    CallFrame *framePtr;
+    Tcl_Obj *listPtr;
+
+    if (objc == 2) {		/* just "info level" */
+        if (iPtr->varFramePtr == NULL) {
+            Tcl_SetIntObj(Tcl_GetObjResult(interp), 0);
+        } else {
+            Tcl_SetIntObj(Tcl_GetObjResult(interp), iPtr->varFramePtr->level);
+        }
+        return TCL_OK;
+    } else if (objc == 3) {
+        if (Tcl_GetIntFromObj(interp, objv[2], &level) != TCL_OK) {
+            return TCL_ERROR;
+        }
+        if (level <= 0) {
+            if (iPtr->varFramePtr == NULL) {
+                levelError:
+		Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+			"bad level \"",
+			Tcl_GetStringFromObj(objv[2], (int *) NULL),
+			"\"", (char *) NULL);
+                return TCL_ERROR;
+            }
+            level += iPtr->varFramePtr->level;
+        }
+        for (framePtr = iPtr->varFramePtr;  framePtr != NULL;
+                framePtr = framePtr->callerVarPtr) {
+            if (framePtr->level == level) {
+                break;
+            }
+        }
+        if (framePtr == NULL) {
+            goto levelError;
+        }
+
+        listPtr = Tcl_NewListObj(framePtr->objc, framePtr->objv);
+        Tcl_SetObjResult(interp, listPtr);
+        return TCL_OK;
+    }
+
+    Tcl_WrongNumArgs(interp, 2, objv, "?number?");
+    return TCL_ERROR;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoLibraryCmd --
+ *
+ *      Called to implement the "info library" command that returns the
+ *      library directory for the Tcl installation. Handles the following
+ *      syntax:
+ *
+ *          info library
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoLibraryCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    char *libDirName;
+
+    if (objc != 2) {
+        Tcl_WrongNumArgs(interp, 2, objv, NULL);
+        return TCL_ERROR;
+    }
+
+    libDirName = Tcl_GetVar(interp, "tcl_library", TCL_GLOBAL_ONLY);
+    if (libDirName != NULL) {
+        Tcl_SetStringObj(Tcl_GetObjResult(interp), libDirName, -1);
+        return TCL_OK;
+    }
+    Tcl_SetStringObj(Tcl_GetObjResult(interp), 
+            "no library has been specified for Tcl", -1);
+    return TCL_ERROR;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoLocalsCmd --
+ *
+ *      Called to implement the "info locals" command to return a list of
+ *      local variables that match an optional pattern. Handles the
+ *      following syntax:
+ *
+ *          info locals ?pattern?
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoLocalsCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Interp *iPtr = (Interp *) interp;
+    char *pattern;
+    Tcl_Obj *listPtr;
+
+    if (objc == 2) {
+        pattern = NULL;
+    } else if (objc == 3) {
+        pattern = Tcl_GetStringFromObj(objv[2], (int *) NULL);
+    } else {
+        Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
+        return TCL_ERROR;
+    }
+    
+    if (iPtr->varFramePtr == NULL || !iPtr->varFramePtr->isProcCallFrame) {
+        return TCL_OK;
+    }
+
+    /*
+     * Return a list containing names of first the compiled locals (i.e. the
+     * ones stored in the call frame), then the variables in the local hash
+     * table (if one exists).
+     */
+    
+    listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+    AppendLocals(interp, listPtr, pattern, 0);
+    Tcl_SetObjResult(interp, listPtr);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AppendLocals --
+ *
+ *	Append the local variables for the current frame to the
+ *	specified list object.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AppendLocals(interp, listPtr, pattern, includeLinks)
+    Tcl_Interp *interp;		/* Current interpreter. */
+    Tcl_Obj *listPtr;		/* List object to append names to. */
+    char *pattern;		/* Pattern to match against. */
+    int includeLinks;		/* 1 if upvars should be included, else 0. */
+{
+    Interp *iPtr = (Interp *) interp;
+    CompiledLocal *localPtr;
+    Var *varPtr;
+    int i, localVarCt;
+    char *varName;
+    Tcl_HashTable *localVarTablePtr;
+    register Tcl_HashEntry *entryPtr;
+    Tcl_HashSearch search;
+
+    localPtr = iPtr->varFramePtr->procPtr->firstLocalPtr;
+    localVarCt = iPtr->varFramePtr->numCompiledLocals;
+    varPtr = iPtr->varFramePtr->compiledLocals;
+    localVarTablePtr = iPtr->varFramePtr->varTablePtr;
+
+    for (i = 0; i < localVarCt; i++) {
+	/*
+	 * Skip nameless (temporary) variables and undefined variables
+	 */
+
+	if (!TclIsVarTemporary(localPtr) && !TclIsVarUndefined(varPtr)) {
+	    varName = varPtr->name;
+	    if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) {
+		Tcl_ListObjAppendElement(interp, listPtr,
+		        Tcl_NewStringObj(varName, -1));
+	    }
+        }
+	varPtr++;
+	localPtr = localPtr->nextPtr;
+    }
+    
+    if (localVarTablePtr != NULL) {
+	for (entryPtr = Tcl_FirstHashEntry(localVarTablePtr, &search);
+	        entryPtr != NULL;
+                entryPtr = Tcl_NextHashEntry(&search)) {
+	    varPtr = (Var *) Tcl_GetHashValue(entryPtr);
+	    if (!TclIsVarUndefined(varPtr)
+		    && (includeLinks || !TclIsVarLink(varPtr))) {
+		varName = Tcl_GetHashKey(localVarTablePtr, entryPtr);
+		if ((pattern == NULL)
+		        || Tcl_StringMatch(varName, pattern)) {
+		    Tcl_ListObjAppendElement(interp, listPtr,
+			    Tcl_NewStringObj(varName, -1));
+		}
+	    }
+	}
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoNameOfExecutableCmd --
+ *
+ *      Called to implement the "info nameofexecutable" command that returns
+ *      the name of the binary file running this application. Handles the
+ *      following syntax:
+ *
+ *          info nameofexecutable
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoNameOfExecutableCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    CONST char *nameOfExecutable;
+
+    if (objc != 2) {
+        Tcl_WrongNumArgs(interp, 2, objv, NULL);
+        return TCL_ERROR;
+    }
+
+    nameOfExecutable = Tcl_GetNameOfExecutable();
+    
+    if (nameOfExecutable != NULL) {
+	Tcl_SetStringObj(Tcl_GetObjResult(interp), (char *)nameOfExecutable, -1);
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoPatchLevelCmd --
+ *
+ *      Called to implement the "info patchlevel" command that returns the
+ *      default value for an argument to a procedure. Handles the following
+ *      syntax:
+ *
+ *          info patchlevel
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoPatchLevelCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    char *patchlevel;
+
+    if (objc != 2) {
+        Tcl_WrongNumArgs(interp, 2, objv, NULL);
+        return TCL_ERROR;
+    }
+
+    patchlevel = Tcl_GetVar(interp, "tcl_patchLevel",
+            (TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
+    if (patchlevel != NULL) {
+        Tcl_SetStringObj(Tcl_GetObjResult(interp), patchlevel, -1);
+        return TCL_OK;
+    }
+    return TCL_ERROR;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoProcsCmd --
+ *
+ *      Called to implement the "info procs" command that returns the
+ *      procedures in the current namespace that match an optional pattern.
+ *      Handles the following syntax:
+ *
+ *          info procs ?pattern?
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoProcsCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    char *cmdName, *pattern;
+    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+    register Tcl_HashEntry *entryPtr;
+    Tcl_HashSearch search;
+    Command *cmdPtr;
+    Tcl_Obj *listPtr;
+
+    if (objc == 2) {
+        pattern = NULL;
+    } else if (objc == 3) {
+        pattern = Tcl_GetStringFromObj(objv[2], (int *) NULL);
+    } else {
+        Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
+        return TCL_ERROR;
+    }
+
+    /*
+     * Scan through the current namespace's command table and return a list
+     * of all procs that match the pattern.
+     */
+    
+    listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+    for (entryPtr = Tcl_FirstHashEntry(&currNsPtr->cmdTable, &search);
+            entryPtr != NULL;
+            entryPtr = Tcl_NextHashEntry(&search)) {
+        cmdName = Tcl_GetHashKey(&currNsPtr->cmdTable, entryPtr);
+        cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
+        if (TclIsProc(cmdPtr)) {
+            if ((pattern == NULL) || Tcl_StringMatch(cmdName, pattern)) {
+                Tcl_ListObjAppendElement(interp, listPtr,
+		        Tcl_NewStringObj(cmdName, -1));
+            }
+        }
+    }
+    Tcl_SetObjResult(interp, listPtr);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoScriptCmd --
+ *
+ *      Called to implement the "info script" command that returns the
+ *      script file that is currently being evaluated. Handles the
+ *      following syntax:
+ *
+ *          info script
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoScriptCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Interp *iPtr = (Interp *) interp;
+    if (objc != 2) {
+        Tcl_WrongNumArgs(interp, 2, objv, NULL);
+        return TCL_ERROR;
+    }
+
+    if (iPtr->scriptFile != NULL) {
+        Tcl_SetStringObj(Tcl_GetObjResult(interp), iPtr->scriptFile, -1);
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoSharedlibCmd --
+ *
+ *      Called to implement the "info sharedlibextension" command that
+ *      returns the file extension used for shared libraries. Handles the
+ *      following syntax:
+ *
+ *          info sharedlibextension
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoSharedlibCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    if (objc != 2) {
+        Tcl_WrongNumArgs(interp, 2, objv, NULL);
+        return TCL_ERROR;
+    }
+    
+#ifdef TCL_SHLIB_EXT
+    Tcl_SetStringObj(Tcl_GetObjResult(interp), TCL_SHLIB_EXT, -1);
+#endif
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoTclVersionCmd --
+ *
+ *      Called to implement the "info tclversion" command that returns the
+ *      version number for this Tcl library. Handles the following syntax:
+ *
+ *          info tclversion
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoTclVersionCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    char *version;
+
+    if (objc != 2) {
+        Tcl_WrongNumArgs(interp, 2, objv, NULL);
+        return TCL_ERROR;
+    }
+
+    version = Tcl_GetVar(interp, "tcl_version",
+        (TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
+    if (version != NULL) {
+        Tcl_SetStringObj(Tcl_GetObjResult(interp), version, -1);
+        return TCL_OK;
+    }
+    return TCL_ERROR;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoVarsCmd --
+ *
+ *	Called to implement the "info vars" command that returns the
+ *	list of variables in the interpreter that match an optional pattern.
+ *	The pattern, if any, consists of an optional sequence of namespace
+ *	names separated by "::" qualifiers, which is followed by a
+ *	glob-style pattern that restricts which variables are returned.
+ *	Handles the following syntax:
+ *
+ *          info vars ?pattern?
+ *
+ * Results:
+ *      Returns TCL_OK is successful and TCL_ERROR is there is an error.
+ *
+ * Side effects:
+ *      Returns a result in the interpreter's result object. If there is
+ *	an error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoVarsCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Interp *iPtr = (Interp *) interp;
+    char *varName, *pattern, *simplePattern;
+    register Tcl_HashEntry *entryPtr;
+    Tcl_HashSearch search;
+    Var *varPtr;
+    Namespace *nsPtr;
+    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
+    Namespace *currNsPtr   = (Namespace *) Tcl_GetCurrentNamespace(interp);
+    Tcl_Obj *listPtr, *elemObjPtr;
+    int specificNsInPattern = 0;  /* Init. to avoid compiler warning. */
+
+    /*
+     * Get the pattern and find the "effective namespace" in which to
+     * list variables. We only use this effective namespace if there's
+     * no active Tcl procedure frame.
+     */
+
+    if (objc == 2) {
+        simplePattern = NULL;
+	nsPtr = currNsPtr;
+	specificNsInPattern = 0;
+    } else if (objc == 3) {
+	/*
+	 * From the pattern, get the effective namespace and the simple
+	 * pattern (no namespace qualifiers or ::'s) at the end. If an
+	 * error was found while parsing the pattern, return it. Otherwise,
+	 * if the namespace wasn't found, just leave nsPtr NULL: we will
+	 * return an empty list since no variables there can be found.
+	 */
+
+	Namespace *dummy1NsPtr, *dummy2NsPtr;
+
+        pattern = Tcl_GetStringFromObj(objv[2], (int *) NULL);
+       TclGetNamespaceForQualName(interp, pattern, (Namespace *) NULL,
+           /*flags*/ 0, &nsPtr, &dummy1NsPtr, &dummy2NsPtr, &simplePattern);
+
+	if (nsPtr != NULL) {	/* we successfully found the pattern's ns */
+	    specificNsInPattern = (strcmp(simplePattern, pattern) != 0);
+	}
+    } else {
+        Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
+        return TCL_ERROR;
+    }
+
+    /*
+     * If the namespace specified in the pattern wasn't found, just return.
+     */
+
+    if (nsPtr == NULL) {
+	return TCL_OK;
+    }
+    
+    listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+    
+    if ((iPtr->varFramePtr == NULL)
+	    || !iPtr->varFramePtr->isProcCallFrame
+	    || specificNsInPattern) {
+	/*
+	 * There is no frame pointer, the frame pointer was pushed only
+	 * to activate a namespace, or we are in a procedure call frame
+	 * but a specific namespace was specified. Create a list containing
+	 * only the variables in the effective namespace's variable table.
+	 */
+	
+	entryPtr = Tcl_FirstHashEntry(&nsPtr->varTable, &search);
+	while (entryPtr != NULL) {
+	    varPtr = (Var *) Tcl_GetHashValue(entryPtr);
+	    if (!TclIsVarUndefined(varPtr)
+		    || (varPtr->flags & VAR_NAMESPACE_VAR)) {
+		varName = Tcl_GetHashKey(&nsPtr->varTable, entryPtr);
+		if ((simplePattern == NULL)
+	                || Tcl_StringMatch(varName, simplePattern)) {
+		    if (specificNsInPattern) {
+			elemObjPtr = Tcl_NewObj();
+			Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr,
+			        elemObjPtr);
+		    } else {
+			elemObjPtr = Tcl_NewStringObj(varName, -1);
+		    }
+		    Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
+		}
+	    }
+	    entryPtr = Tcl_NextHashEntry(&search);
+	}
+
+	/*
+	 * If the effective namespace isn't the global :: namespace, and a
+	 * specific namespace wasn't requested in the pattern (i.e., the
+	 * pattern only specifies variable names), then add in all global ::
+	 * variables that match the simple pattern. Of course, add in only
+	 * those variables that aren't hidden by a variable in the effective
+	 * namespace.
+	 */
+
+	if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
+	    entryPtr = Tcl_FirstHashEntry(&globalNsPtr->varTable, &search);
+	    while (entryPtr != NULL) {
+		varPtr = (Var *) Tcl_GetHashValue(entryPtr);
+		if (!TclIsVarUndefined(varPtr)
+		        || (varPtr->flags & VAR_NAMESPACE_VAR)) {
+		    varName = Tcl_GetHashKey(&globalNsPtr->varTable,
+			    entryPtr);
+		    if ((simplePattern == NULL)
+	                    || Tcl_StringMatch(varName, simplePattern)) {
+			if (Tcl_FindHashEntry(&nsPtr->varTable, varName) == NULL) {
+			    Tcl_ListObjAppendElement(interp, listPtr,
+			            Tcl_NewStringObj(varName, -1));
+			}
+		    }
+		}
+		entryPtr = Tcl_NextHashEntry(&search);
+	    }
+	}
+    } else {
+	AppendLocals(interp, listPtr, simplePattern, 1);
+    }
+    
+    Tcl_SetObjResult(interp, listPtr);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_JoinObjCmd --
+ *
+ *	This procedure is invoked to process the "join" Tcl command.
+ *	See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_JoinObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* The argument objects. */
+{
+    char *joinString, *bytes;
+    int joinLength, listLen, length, i, result;
+    Tcl_Obj **elemPtrs;
+    Tcl_Obj *resObjPtr;
+
+    if (objc == 2) {
+	joinString = " ";
+	joinLength = 1;
+    } else if (objc == 3) {
+	joinString = Tcl_GetStringFromObj(objv[2], &joinLength);
+    } else {
+	Tcl_WrongNumArgs(interp, 1, objv, "list ?joinString?");
+	return TCL_ERROR;
+    }
+
+    /*
+     * Make sure the list argument is a list object and get its length and
+     * a pointer to its array of element pointers.
+     */
+
+    result = Tcl_ListObjGetElements(interp, objv[1], &listLen, &elemPtrs);
+    if (result != TCL_OK) {
+	return result;
+    }
+
+    /*
+     * Now concatenate strings to form the "joined" result. We append
+     * directly into the interpreter's result object.
+     */
+
+    resObjPtr = Tcl_GetObjResult(interp);
+
+    for (i = 0;  i < listLen;  i++) {
+	bytes = Tcl_GetStringFromObj(elemPtrs[i], &length);
+	if (i > 0) {
+	    Tcl_AppendToObj(resObjPtr, joinString, joinLength);
+	}
+	Tcl_AppendToObj(resObjPtr, bytes, length);
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LindexObjCmd --
+ *
+ *	This object-based procedure is invoked to process the "lindex" Tcl
+ *	command. See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+    /* ARGSUSED */
+int
+Tcl_LindexObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Tcl_Obj *listPtr;
+    Tcl_Obj **elemPtrs;
+    int listLen, index, result;
+
+    if (objc != 3) {
+	Tcl_WrongNumArgs(interp, 1, objv, "list index");
+	return TCL_ERROR;
+    }
+
+    /*
+     * Convert the first argument to a list if necessary.
+     */
+
+    listPtr = objv[1];
+    result = Tcl_ListObjGetElements(interp, listPtr, &listLen, &elemPtrs);
+    if (result != TCL_OK) {
+	return result;
+    }
+
+    /*
+     * Get the index from objv[2].
+     */
+
+    result = TclGetIntForIndex(interp, objv[2], /*endValue*/ (listLen - 1),
+	    &index);
+    if (result != TCL_OK) {
+	return result;
+    }
+    if ((index < 0) || (index >= listLen)) {
+	/*
+	 * The index is out of range: the result is an empty string object.
+	 */
+	
+	return TCL_OK;
+    }
+
+    /*
+     * Make sure listPtr still refers to a list object. It might have been
+     * converted to an int above if the argument objects were shared.
+     */
+
+    if (listPtr->typePtr != &tclListType) {
+	result = Tcl_ListObjGetElements(interp, listPtr, &listLen,
+	        &elemPtrs);
+	if (result != TCL_OK) {
+	    return result;
+	}
+    }
+
+    /*
+     * Set the interpreter's object result to the index-th list element.
+     */
+
+    Tcl_SetObjResult(interp, elemPtrs[index]);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LinsertObjCmd --
+ *
+ *	This object-based procedure is invoked to process the "linsert" Tcl
+ *	command. See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A new Tcl list object formed by inserting zero or more elements 
+ *	into a list.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_LinsertObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    register int objc;		/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Tcl_Obj *listPtr, *resultPtr;
+    Tcl_ObjType *typePtr;
+    int index, isDuplicate, len, result;
+
+    if (objc < 4) {
+	Tcl_WrongNumArgs(interp, 1, objv, "list index element ?element ...?");
+	return TCL_ERROR;
+    }
+
+    /*
+     * Get the index first since, if a conversion to int is needed, it
+     * will invalidate the list's internal representation.
+     */
+
+    result = TclGetIntForIndex(interp, objv[2], /*endValue*/ INT_MAX,
+	    &index);
+    if (result != TCL_OK) {
+	return result;
+    }
+
+    /*
+     * If the list object is unshared we can modify it directly. Otherwise
+     * we create a copy to modify: this is "copy on write". We create the
+     * duplicate directly in the interpreter's object result.
+     */
+    
+    listPtr = objv[1];
+    isDuplicate = 0;
+    if (Tcl_IsShared(listPtr)) {
+	/*
+	 * The following code must reflect the logic in Tcl_DuplicateObj()
+	 * except that it must duplicate the list object directly into the
+	 * interpreter's result.
+	 */
+	
+	Tcl_ResetResult(interp);
+	resultPtr = Tcl_GetObjResult(interp);
+	typePtr = listPtr->typePtr;
+	if (listPtr->bytes == NULL) {
+	    resultPtr->bytes = NULL;
+	} else if (listPtr->bytes != tclEmptyStringRep) {
+	    len = listPtr->length;
+	    TclInitStringRep(resultPtr, listPtr->bytes, len);
+	}
+	if (typePtr != NULL) {
+	    if (typePtr->dupIntRepProc == NULL) {
+		resultPtr->internalRep = listPtr->internalRep;
+		resultPtr->typePtr = typePtr;
+	    } else {
+		(*typePtr->dupIntRepProc)(listPtr, resultPtr);
+	    }
+	}
+	listPtr = resultPtr;
+	isDuplicate = 1;
+    }
+    
+    if ((objc == 4) && (index == INT_MAX)) {
+	/*
+	 * Special case: insert one element at the end of the list.
+	 */
+
+	result = Tcl_ListObjAppendElement(interp, listPtr, objv[3]);
+    } else if (objc > 3) {
+	result = Tcl_ListObjReplace(interp, listPtr, index, 0,
+				    (objc-3), &(objv[3]));
+    }
+    if (result != TCL_OK) {
+	return result;
+    }
+    
+    /*
+     * Set the interpreter's object result.
+     */
+
+    if (!isDuplicate) {
+	Tcl_SetObjResult(interp, listPtr);
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ListObjCmd --
+ *
+ *	This procedure is invoked to process the "list" Tcl command.
+ *	See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_ListObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;			/* Not used. */
+    Tcl_Interp *interp;			/* Current interpreter. */
+    register int objc;			/* Number of arguments. */
+    register Tcl_Obj *CONST objv[];	/* The argument objects. */
+{
+    /*
+     * If there are no list elements, the result is an empty object.
+     * Otherwise modify the interpreter's result object to be a list object.
+     */
+    
+    if (objc > 1) {
+	Tcl_SetListObj(Tcl_GetObjResult(interp), (objc-1), &(objv[1]));
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LlengthObjCmd --
+ *
+ *	This object-based procedure is invoked to process the "llength" Tcl
+ *	command.  See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_LlengthObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;			/* Not used. */
+    Tcl_Interp *interp;			/* Current interpreter. */
+    int objc;				/* Number of arguments. */
+    register Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    int listLen, result;
+
+    if (objc != 2) {
+	Tcl_WrongNumArgs(interp, 1, objv, "list");
+	return TCL_ERROR;
+    }
+
+    result = Tcl_ListObjLength(interp, objv[1], &listLen);
+    if (result != TCL_OK) {
+	return result;
+    }
+
+    /*
+     * Set the interpreter's object result to an integer object holding the
+     * length. 
+     */
+
+    Tcl_SetIntObj(Tcl_GetObjResult(interp), listLen);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LrangeObjCmd --
+ *
+ *	This procedure is invoked to process the "lrange" Tcl command.
+ *	See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_LrangeObjCmd(notUsed, interp, objc, objv)
+    ClientData notUsed;			/* Not used. */
+    Tcl_Interp *interp;			/* Current interpreter. */
+    int objc;				/* Number of arguments. */
+    register Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Tcl_Obj *listPtr;
+    Tcl_Obj **elemPtrs;
+    int listLen, first, last, numElems, result;
+
+    if (objc != 4) {
+	Tcl_WrongNumArgs(interp, 1, objv, "list first last");
+	return TCL_ERROR;
+    }
+
+    /*
+     * Make sure the list argument is a list object and get its length and
+     * a pointer to its array of element pointers.
+     */
+
+    listPtr = objv[1];
+    result = Tcl_ListObjGetElements(interp, listPtr, &listLen, &elemPtrs);
+    if (result != TCL_OK) {
+	return result;
+    }
+
+    /*
+     * Get the first and last indexes.
+     */
+
+    result = TclGetIntForIndex(interp, objv[2], /*endValue*/ (listLen - 1),
+	    &first);
+    if (result != TCL_OK) {
+	return result;
+    }
+    if (first < 0) {
+	first = 0;
+    }
+
+    result = TclGetIntForIndex(interp, objv[3], /*endValue*/ (listLen - 1),
+	    &last);
+    if (result != TCL_OK) {
+	return result;
+    }
+    if (last >= listLen) {
+	last = (listLen - 1);
+    }
+    
+    if (first > last) {
+	return TCL_OK;		/* the result is an empty object */
+    }
+
+    /*
+     * Make sure listPtr still refers to a list object. It might have been
+     * converted to an int above if the argument objects were shared.
+     */  
+
+    if (listPtr->typePtr != &tclListType) {
+        result = Tcl_ListObjGetElements(interp, listPtr, &listLen,
+                &elemPtrs);
+        if (result != TCL_OK) {
+            return result;
+        }
+    }
+
+    /*
+     * Extract a range of fields. We modify the interpreter's result object
+     * to be a list object containing the specified elements.
+     */
+
+    numElems = (last - first + 1);
+    Tcl_SetListObj(Tcl_GetObjResult(interp), numElems, &(elemPtrs[first]));
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LreplaceObjCmd --
+ *
+ *	This object-based procedure is invoked to process the "lreplace" 
+ *	Tcl command. See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A new Tcl list object formed by replacing zero or more elements of
+ *	a list.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_LreplaceObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    register Tcl_Obj *listPtr;
+    int createdNewObj, first, last, listLen, numToDelete;
+    int firstArgLen, result;
+    char *firstArg;
+
+    if (objc < 4) {
+	Tcl_WrongNumArgs(interp, 1, objv,
+		"list first last ?element element ...?");
+	return TCL_ERROR;
+    }
+
+    /*
+     * If the list object is unshared we can modify it directly, otherwise
+     * we create a copy to modify: this is "copy on write".
+     */
+    
+    listPtr = objv[1];
+    createdNewObj = 0;
+    if (Tcl_IsShared(listPtr)) {
+	listPtr = Tcl_DuplicateObj(listPtr);
+	createdNewObj = 1;
+    }
+    result = Tcl_ListObjLength(interp, listPtr, &listLen);
+    if (result != TCL_OK) {
+        errorReturn:
+	if (createdNewObj) {
+	    Tcl_DecrRefCount(listPtr); /* free unneeded obj */
+	}
+	return result;
+    }
+
+    /*
+     * Get the first and last indexes.
+     */
+
+    result = TclGetIntForIndex(interp, objv[2], /*endValue*/ (listLen - 1),
+	    &first);
+    if (result != TCL_OK) {
+	goto errorReturn;
+    }
+    firstArg = Tcl_GetStringFromObj(objv[2], &firstArgLen);
+
+    result = TclGetIntForIndex(interp, objv[3], /*endValue*/ (listLen - 1),
+	    &last);
+    if (result != TCL_OK) {
+	goto errorReturn;
+    }
+
+    if (first < 0)  {
+    	first = 0;
+    }
+    if ((first >= listLen) && (listLen > 0)
+	    && (strncmp(firstArg, "end", (unsigned) firstArgLen) != 0)) {
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		"list doesn't contain element ",
+		Tcl_GetStringFromObj(objv[2], (int *) NULL), (int *) NULL);
+	result = TCL_ERROR;
+	goto errorReturn;
+    }
+    if (last >= listLen) {
+    	last = (listLen - 1);
+    }
+    if (first <= last) {
+	numToDelete = (last - first + 1);
+    } else {
+	numToDelete = 0;
+    }
+
+    if (objc > 4) {
+	result = Tcl_ListObjReplace(interp, listPtr, first, numToDelete,
+	        (objc-4), &(objv[4]));
+    } else {
+	result = Tcl_ListObjReplace(interp, listPtr, first, numToDelete,
+		0, NULL);
+    }
+    if (result != TCL_OK) {
+	goto errorReturn;
+    }
+
+    /*
+     * Set the interpreter's object result. 
+     */
+
+    Tcl_SetObjResult(interp, listPtr);
+    return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LsortObjCmd --
+ *
+ *	This procedure is invoked to process the "lsort" Tcl command.
+ *	See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_LsortObjCmd(clientData, interp, objc, objv)
+    ClientData clientData;	/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument values. */
+{
+    int i, index, dummy;
+    Tcl_Obj *resultPtr;
+    int length;
+    Tcl_Obj *cmdPtr, **listObjPtrs;
+    SortElement *elementArray;
+    SortElement *elementPtr;        
+    SortInfo sortInfo;                  /* Information about this sort that
+                                         * needs to be passed to the 
+                                         * comparison function */
+    static char *switches[] =
+	    {"-ascii", "-command", "-decreasing", "-dictionary",
+	    "-increasing", "-index", "-integer", "-real", (char *) NULL};
+
+    resultPtr = Tcl_GetObjResult(interp);
+    if (objc < 2) {
+	Tcl_WrongNumArgs(interp, 1, objv, "?options? list");
+	return TCL_ERROR;
+    }
+
+    /*
+     * Parse arguments to set up the mode for the sort.
+     */
+
+    sortInfo.isIncreasing = 1;
+    sortInfo.sortMode = SORTMODE_ASCII;
+    sortInfo.index = -1;
+    sortInfo.interp = interp;
+    sortInfo.resultCode = TCL_OK;
+    cmdPtr = NULL;
+    for (i = 1; i < objc-1; i++) {
+	if (Tcl_GetIndexFromObj(interp, objv[i], switches, "option", 0, &index)
+		!= TCL_OK) {
+	    return TCL_ERROR;
+	}
+	switch (index) {
+	    case 0:			/* -ascii */
+		sortInfo.sortMode = SORTMODE_ASCII;
+		break;
+	    case 1:			/* -command */
+		if (i == (objc-2)) {
+		    Tcl_AppendToObj(resultPtr,
+			    "\"-command\" option must be followed by comparison command",
+			    -1);
+		    return TCL_ERROR;
+		}
+		sortInfo.sortMode = SORTMODE_COMMAND;
+		cmdPtr = objv[i+1];
+		i++;
+		break;
+	    case 2:			/* -decreasing */
+		sortInfo.isIncreasing = 0;
+		break;
+	    case 3:			/* -dictionary */
+		sortInfo.sortMode = SORTMODE_DICTIONARY;
+		break;
+	    case 4:			/* -increasing */
+		sortInfo.isIncreasing = 1;
+		break;
+	    case 5:			/* -index */
+		if (i == (objc-2)) {
+		    Tcl_AppendToObj(resultPtr,
+			    "\"-index\" option must be followed by list index",
+			    -1);
+		    return TCL_ERROR;
+		}
+		if (TclGetIntForIndex(interp, objv[i+1], -2, &sortInfo.index)
+			!= TCL_OK) {
+		    return TCL_ERROR;
+		}
+		cmdPtr = objv[i+1];
+		i++;
+		break;
+	    case 6:			/* -integer */
+		sortInfo.sortMode = SORTMODE_INTEGER;
+		break;
+	    case 7:			/* -real */
+		sortInfo.sortMode = SORTMODE_REAL;
+		break;
+	}
+    }
+    if (sortInfo.sortMode == SORTMODE_COMMAND) {
+	Tcl_DStringInit(&sortInfo.compareCmd);
+	Tcl_DStringAppend(&sortInfo.compareCmd,
+		Tcl_GetStringFromObj(cmdPtr, &dummy), -1);
+    }
+
+    sortInfo.resultCode = Tcl_ListObjGetElements(interp, objv[objc-1],
+	    &length, &listObjPtrs);
+    if (sortInfo.resultCode != TCL_OK) {
+	goto done;
+    }
+    if (length <= 0) {
+        return TCL_OK;
+    }
+    elementArray = (SortElement *) ckalloc(length * sizeof(SortElement));
+    for (i=0; i < length; i++){
+	elementArray[i].objPtr = listObjPtrs[i];
+	elementArray[i].nextPtr = &elementArray[i+1];
+    }
+    elementArray[length-1].nextPtr = NULL;
+    elementPtr = MergeSort(elementArray, &sortInfo);
+    if (sortInfo.resultCode == TCL_OK) {
+	/*
+	 * Note: must clear the interpreter's result object: it could
+	 * have been set by the -command script.
+	 */
+
+	Tcl_ResetResult(interp);
+	resultPtr = Tcl_GetObjResult(interp);
+	for (; elementPtr != NULL; elementPtr = elementPtr->nextPtr){
+	    Tcl_ListObjAppendElement(interp, resultPtr, elementPtr->objPtr);
+	}
+    }
+    ckfree((char*) elementArray);
+
+    done:
+    if (sortInfo.sortMode == SORTMODE_COMMAND) {
+	Tcl_DStringFree(&sortInfo.compareCmd);
+    }
+    return sortInfo.resultCode;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MergeSort -
+ *
+ *	This procedure sorts a linked list of SortElement structures
+ *	use the merge-sort algorithm.
+ *
+ * Results:
+ *      A pointer to the head of the list after sorting is returned.
+ *
+ * Side effects:
+ *	None, unless a user-defined comparison command does something
+ *	weird.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static SortElement *
+MergeSort(headPtr, infoPtr)
+    SortElement *headPtr;               /* First element on the list */
+    SortInfo *infoPtr;                  /* Information needed by the
+                                         * comparison operator */
+{
+    /*
+     * The subList array below holds pointers to temporary lists built
+     * during the merge sort.  Element i of the array holds a list of
+     * length 2**i.
+     */
+
+#   define NUM_LISTS 30
+    SortElement *subList[NUM_LISTS];
+    SortElement *elementPtr;
+    int i;
+
+    for(i = 0; i < NUM_LISTS; i++){
+        subList[i] = NULL;
+    }
+    while (headPtr != NULL) {
+	elementPtr = headPtr;
+	headPtr = headPtr->nextPtr;
+	elementPtr->nextPtr = 0;
+	for (i = 0; (i < NUM_LISTS) && (subList[i] != NULL); i++){
+	    elementPtr = MergeLists(subList[i], elementPtr, infoPtr);
+	    subList[i] = NULL;
+	}
+	if (i >= NUM_LISTS) {
+	    i = NUM_LISTS-1;
+	}
+	subList[i] = elementPtr;
+    }
+    elementPtr = NULL;
+    for (i = 0; i < NUM_LISTS; i++){
+        elementPtr = MergeLists(subList[i], elementPtr, infoPtr);
+    }
+    return elementPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MergeLists -
+ *
+ *	This procedure combines two sorted lists of SortElement structures
+ *	into a single sorted list.
+ *
+ * Results:
+ *      The unified list of SortElement structures.
+ *
+ * Side effects:
+ *	None, unless a user-defined comparison command does something
+ *	weird.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static SortElement *
+MergeLists(leftPtr, rightPtr, infoPtr)
+    SortElement *leftPtr;               /* First list to be merged; may be
+					 * NULL. */
+    SortElement *rightPtr;              /* Second list to be merged; may be
+					 * NULL. */
+    SortInfo *infoPtr;                  /* Information needed by the
+                                         * comparison operator. */
+{
+    SortElement *headPtr;
+    SortElement *tailPtr;
+
+    if (leftPtr == NULL) {
+        return rightPtr;
+    }
+    if (rightPtr == NULL) {
+        return leftPtr;
+    }
+    if (SortCompare(leftPtr->objPtr, rightPtr->objPtr, infoPtr) > 0) {
+	tailPtr = rightPtr;
+	rightPtr = rightPtr->nextPtr;
+    } else {
+	tailPtr = leftPtr;
+	leftPtr = leftPtr->nextPtr;
+    }
+    headPtr = tailPtr;
+    while ((leftPtr != NULL) && (rightPtr != NULL)) {
+	if (SortCompare(leftPtr->objPtr, rightPtr->objPtr, infoPtr) > 0) {
+	    tailPtr->nextPtr = rightPtr;
+	    tailPtr = rightPtr;
+	    rightPtr = rightPtr->nextPtr;
+	} else {
+	    tailPtr->nextPtr = leftPtr;
+	    tailPtr = leftPtr;
+	    leftPtr = leftPtr->nextPtr;
+	}
+    }
+    if (leftPtr != NULL) {
+       tailPtr->nextPtr = leftPtr;
+    } else {
+       tailPtr->nextPtr = rightPtr;
+    }
+    return headPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SortCompare --
+ *
+ *	This procedure is invoked by MergeLists to determine the proper
+ *	ordering between two elements.
+ *
+ * Results:
+ *      A negative results means the the first element comes before the
+ *      second, and a positive results means that the second element
+ *      should come first.  A result of zero means the two elements
+ *      are equal and it doesn't matter which comes first.
+ *
+ * Side effects:
+ *	None, unless a user-defined comparison command does something
+ *	weird.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SortCompare(objPtr1, objPtr2, infoPtr)
+    Tcl_Obj *objPtr1, *objPtr2;		/* Values to be compared. */
+    SortInfo *infoPtr;                  /* Information passed from the
+                                         * top-level "lsort" command */
+{
+    int order, dummy, listLen, index;
+    Tcl_Obj *objPtr;
+    char buffer[30];
+
+    order = 0;
+    if (infoPtr->resultCode != TCL_OK) {
+	/*
+	 * Once an error has occurred, skip any future comparisons
+	 * so as to preserve the error message in sortInterp->result.
+	 */
+
+	return order;
+    }
+    if (infoPtr->index != -1) {
+	/*
+	 * The "-index" option was specified.  Treat each object as a
+	 * list, extract the requested element from each list, and
+	 * compare the elements, not the lists.  The special index "end"
+	 * is signaled here with a large negative index.
+	 */
+
+	if (Tcl_ListObjLength(infoPtr->interp, objPtr1, &listLen) != TCL_OK) {
+	    infoPtr->resultCode = TCL_ERROR;
+	    return order;
+	}
+	if (infoPtr->index < -1) {
+	    index = listLen - 1;
+	} else {
+	    index = infoPtr->index;
+	}
+
+	if (Tcl_ListObjIndex(infoPtr->interp, objPtr1, index, &objPtr)
+		!= TCL_OK) {
+	    infoPtr->resultCode = TCL_ERROR;
+	    return order;
+	}
+	if (objPtr == NULL) {
+	    objPtr = objPtr1;
+	    missingElement:
+	    sprintf(buffer, "%d", infoPtr->index);
+	    Tcl_AppendStringsToObj(Tcl_GetObjResult(infoPtr->interp),
+			"element ", buffer, " missing from sublist \"",
+			Tcl_GetStringFromObj(objPtr, (int *) NULL),
+			"\"", (char *) NULL);
+	    infoPtr->resultCode = TCL_ERROR;
+	    return order;
+	}
+	objPtr1 = objPtr;
+
+	if (Tcl_ListObjLength(infoPtr->interp, objPtr2, &listLen) != TCL_OK) {
+	    infoPtr->resultCode = TCL_ERROR;
+	    return order;
+	}
+	if (infoPtr->index < -1) {
+	    index = listLen - 1;
+	} else {
+	    index = infoPtr->index;
+	}
+
+	if (Tcl_ListObjIndex(infoPtr->interp, objPtr2, index, &objPtr)
+		!= TCL_OK) {
+	    infoPtr->resultCode = TCL_ERROR;
+	    return order;
+	}
+	if (objPtr == NULL) {
+	    objPtr = objPtr2;
+	    goto missingElement;
+	}
+	objPtr2 = objPtr;
+    }
+    if (infoPtr->sortMode == SORTMODE_ASCII) {
+	order = strcmp(Tcl_GetStringFromObj(objPtr1, &dummy),
+		Tcl_GetStringFromObj(objPtr2, &dummy));
+    } else if (infoPtr->sortMode == SORTMODE_DICTIONARY) {
+	order = DictionaryCompare(
+		Tcl_GetStringFromObj(objPtr1, &dummy),
+		Tcl_GetStringFromObj(objPtr2, &dummy));
+    } else if (infoPtr->sortMode == SORTMODE_INTEGER) {
+	int a, b;
+
+	if ((Tcl_GetIntFromObj(infoPtr->interp, objPtr1, &a) != TCL_OK)
+		|| (Tcl_GetIntFromObj(infoPtr->interp, objPtr2, &b)
+		!= TCL_OK)) {
+	    infoPtr->resultCode = TCL_ERROR;
+	    return order;
+	}
+	if (a > b) {
+	    order = 1;
+	} else if (b > a) {
+	    order = -1;
+	}
+    } else if (infoPtr->sortMode == SORTMODE_REAL) {
+	double a, b;
+
+	if ((Tcl_GetDoubleFromObj(infoPtr->interp, objPtr1, &a) != TCL_OK)
+	      || (Tcl_GetDoubleFromObj(infoPtr->interp, objPtr2, &b)
+		      != TCL_OK)) {
+	    infoPtr->resultCode = TCL_ERROR;
+	    return order;
+	}
+	if (a > b) {
+	    order = 1;
+	} else if (b > a) {
+	    order = -1;
+	}
+    } else {
+	int oldLength;
+
+	/*
+	 * Generate and evaluate a command to determine which string comes
+	 * first.
+	 */
+
+	oldLength = Tcl_DStringLength(&infoPtr->compareCmd);
+	Tcl_DStringAppendElement(&infoPtr->compareCmd,
+		Tcl_GetStringFromObj(objPtr1, &dummy));
+	Tcl_DStringAppendElement(&infoPtr->compareCmd,
+		Tcl_GetStringFromObj(objPtr2, &dummy));
+	infoPtr->resultCode = Tcl_Eval(infoPtr->interp, 
+		Tcl_DStringValue(&infoPtr->compareCmd));
+	Tcl_DStringTrunc(&infoPtr->compareCmd, oldLength);
+	if (infoPtr->resultCode != TCL_OK) {
+	    Tcl_AddErrorInfo(infoPtr->interp,
+		    "\n    (-compare command)");
+	    return order;
+	}
+
+	/*
+	 * Parse the result of the command.
+	 */
+
+	if (Tcl_GetIntFromObj(infoPtr->interp,
+		Tcl_GetObjResult(infoPtr->interp), &order) != TCL_OK) {
+	    Tcl_ResetResult(infoPtr->interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(infoPtr->interp),
+		    "-compare command returned non-numeric result", -1);
+	    infoPtr->resultCode = TCL_ERROR;
+	    return order;
+	}
+    }
+    if (!infoPtr->isIncreasing) {
+	order = -order;
+    }
+    return order;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictionaryCompare
+ *
+ *	This function compares two strings as if they were being used in
+ *	an index or card catalog.  The case of alphabetic characters is
+ *	ignored, except to break ties.  Thus "B" comes before "b" but
+ *	after "a".  Also, integers embedded in the strings compare in
+ *	numerical order.  In other words, "x10y" comes after "x9y", not
+ *      before it as it would when using strcmp().
+ *
+ * Results:
+ *      A negative result means that the first element comes before the
+ *      second, and a positive result means that the second element
+ *      should come first.  A result of zero means the two elements
+ *      are equal and it doesn't matter which comes first.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictionaryCompare(left, right)
+    char *left, *right;          /* The strings to compare */
+{
+    int diff, zeros;
+    int secondaryDiff = 0;
+
+    while (1) {
+	if (isdigit(UCHAR(*right)) && isdigit(UCHAR(*left))) {
+	    /*
+	     * There are decimal numbers embedded in the two
+	     * strings.  Compare them as numbers, rather than
+	     * strings.  If one number has more leading zeros than
+	     * the other, the number with more leading zeros sorts
+	     * later, but only as a secondary choice.
+	     */
+
+	    zeros = 0;
+	    while ((*right == '0') && (isdigit(UCHAR(right[1])))) {
+		right++;
+		zeros--;
+	    }
+	    while ((*left == '0') && (isdigit(UCHAR(left[1])))) {
+		left++;
+		zeros++;
+	    }
+	    if (secondaryDiff == 0) {
+		secondaryDiff = zeros;
+	    }
+
+	    /*
+	     * The code below compares the numbers in the two
+	     * strings without ever converting them to integers.  It
+	     * does this by first comparing the lengths of the
+	     * numbers and then comparing the digit values.
+	     */
+
+	    diff = 0;
+	    while (1) {
+		if (diff == 0) {
+		    diff = UCHAR(*left) - UCHAR(*right);
+		}
+		right++;
+		left++;
+		if (!isdigit(UCHAR(*right))) {
+		    if (isdigit(UCHAR(*left))) {
+			return 1;
+		    } else {
+			/*
+			 * The two numbers have the same length. See
+			 * if their values are different.
+			 */
+
+			if (diff != 0) {
+			    return diff;
+			}
+			break;
+		    }
+		} else if (!isdigit(UCHAR(*left))) {
+		    return -1;
+		}
+	    }
+	    continue;
+	}
+        diff = UCHAR(*left) - UCHAR(*right);
+        if (diff) {
+            if (isupper(UCHAR(*left)) && islower(UCHAR(*right))) {
+                diff = UCHAR(tolower(*left)) - UCHAR(*right);
+                if (diff) {
+		    return diff;
+                } else if (secondaryDiff == 0) {
+		    secondaryDiff = -1;
+                }
+            } else if (isupper(UCHAR(*right)) && islower(UCHAR(*left))) {
+                diff = UCHAR(*left) - UCHAR(tolower(UCHAR(*right)));
+                if (diff) {
+		    return diff;
+                } else if (secondaryDiff == 0) {
+		    secondaryDiff = 1;
+                }
+            } else {
+                return diff;
+            }
+        }
+        if (*left == 0) {
+	    break;
+	}
+        left++;
+        right++;
+    }
+    if (diff == 0) {
+	diff = secondaryDiff;
+    }
+    return diff;
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclCmdMZ.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclCmdMZ.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclCmdMZ.c	(revision 5)
@@ -0,0 +1,1428 @@
+/* 
+ * tclCmdMZ.c --
+ *
+ *	This file contains the top-level command routines for most of
+ *	the Tcl built-in commands whose names begin with the letters
+ *	M to Z.  It contains only commands in the generic core (i.e.
+ *	those that don't depend much upon UNIX facilities).
+ *
+ * Copyright (c) 1987-1993 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclCmdMZ.c,v 1.1 2008-06-04 13:58:04 demin Exp $
+ */
+
+#include "tclInt.h"
+#include "tclPort.h"
+#include "tclCompile.h"
+
+/*
+ * Structure used to hold information about variable traces:
+ */
+
+typedef struct {
+    int flags;			/* Operations for which Tcl command is
+				 * to be invoked. */
+    char *errMsg;		/* Error message returned from Tcl command,
+				 * or NULL.  Malloc'ed. */
+    int length;			/* Number of non-NULL chars. in command. */
+    char command[4];		/* Space for Tcl command to invoke.  Actual
+				 * size will be as large as necessary to
+				 * hold command.  This field must be the
+				 * last in the structure, so that it can
+				 * be larger than 4 bytes. */
+} TraceVarInfo;
+
+/*
+ * Forward declarations for procedures defined in this file:
+ */
+
+static char *		TraceVarProc _ANSI_ARGS_((ClientData clientData,
+			    Tcl_Interp *interp, char *name1, char *name2,
+			    int flags));
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ReturnObjCmd --
+ *
+ *	This object-based procedure is invoked to process the "return" Tcl
+ *	command. See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_ReturnObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Interp *iPtr = (Interp *) interp;
+    int optionLen, argLen, code, result;
+
+    if (iPtr->errorInfo != NULL) {
+	ckfree(iPtr->errorInfo);
+	iPtr->errorInfo = NULL;
+    }
+    if (iPtr->errorCode != NULL) {
+	ckfree(iPtr->errorCode);
+	iPtr->errorCode = NULL;
+    }
+    code = TCL_OK;
+
+   /*
+    * THIS FAILS IF AN OBJECT CONTAINS AN EMBEDDED NULL.
+    */
+    
+    for (objv++, objc--;  objc > 1;  objv += 2, objc -= 2) {
+	char *option = Tcl_GetStringFromObj(objv[0], &optionLen);
+	char *arg = Tcl_GetStringFromObj(objv[1], &argLen);
+    	
+	if (strcmp(option, "-code") == 0) {
+	    register int c = arg[0];
+	    if ((c == 'o') && (strcmp(arg, "ok") == 0)) {
+		code = TCL_OK;
+	    } else if ((c == 'e') && (strcmp(arg, "error") == 0)) {
+		code = TCL_ERROR;
+	    } else if ((c == 'r') && (strcmp(arg, "return") == 0)) {
+		code = TCL_RETURN;
+	    } else if ((c == 'b') && (strcmp(arg, "break") == 0)) {
+		code = TCL_BREAK;
+	    } else if ((c == 'c') && (strcmp(arg, "continue") == 0)) {
+		code = TCL_CONTINUE;
+	    } else {
+		result = Tcl_GetIntFromObj((Tcl_Interp *) NULL, objv[1],
+		        &code);
+		if (result != TCL_OK) {
+		    Tcl_ResetResult(interp);
+		    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+			    "bad completion code \"",
+			    Tcl_GetStringFromObj(objv[1], (int *) NULL),
+			    "\": must be ok, error, return, break, ",
+			    "continue, or an integer", (char *) NULL);
+		    return result;
+		}
+	    }
+	} else if (strcmp(option, "-errorinfo") == 0) {
+	    iPtr->errorInfo =
+		(char *) ckalloc((unsigned) (strlen(arg) + 1));
+	    strcpy(iPtr->errorInfo, arg);
+	} else if (strcmp(option, "-errorcode") == 0) {
+	    iPtr->errorCode =
+		(char *) ckalloc((unsigned) (strlen(arg) + 1));
+	    strcpy(iPtr->errorCode, arg);
+	} else {
+	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		    "bad option \"", option,
+		    "\": must be -code, -errorcode, or -errorinfo",
+		    (char *) NULL);
+	    return TCL_ERROR;
+	}
+    }
+    
+    if (objc == 1) {
+	/*
+	 * Set the interpreter's object result. An inline version of
+	 * Tcl_SetObjResult.
+	 */
+
+	Tcl_SetObjResult(interp, objv[0]);
+    }
+    iPtr->returnCode = code;
+    return TCL_RETURN;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ScanCmd --
+ *
+ *	This procedure is invoked to process the "scan" Tcl command.
+ *	See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_ScanCmd(dummy, interp, argc, argv)
+    ClientData dummy;			/* Not used. */
+    Tcl_Interp *interp;			/* Current interpreter. */
+    int argc;				/* Number of arguments. */
+    char **argv;			/* Argument strings. */
+{
+#   define MAX_FIELDS 20
+    typedef struct {
+	char fmt;			/* Format for field. */
+	int size;			/* How many bytes to allow for
+					 * field. */
+	char *location;			/* Where field will be stored. */
+    } Field;
+    Field fields[MAX_FIELDS];		/* Info about all the fields in the
+					 * format string. */
+    register Field *curField;
+    int numFields = 0;			/* Number of fields actually
+					 * specified. */
+    int suppress;			/* Current field is assignment-
+					 * suppressed. */
+    int totalSize = 0;			/* Number of bytes needed to store
+					 * all results combined. */
+    char *results;			/* Where scanned output goes.
+					 * Malloced; NULL means not allocated
+					 * yet. */
+    int numScanned;			/* sscanf's result. */
+    register char *fmt;
+    int i, widthSpecified, length, code;
+    char buf[40];
+
+    /*
+     * The variables below are used to hold a copy of the format
+     * string, so that we can replace format specifiers like "%f"
+     * and "%F" with specifiers like "%lf"
+     */
+
+#   define STATIC_SIZE 5
+    char copyBuf[STATIC_SIZE], *fmtCopy;
+    register char *dst;
+
+    if (argc < 3) {
+	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+		" string format ?varName varName ...?\"", (char *) NULL);
+	return TCL_ERROR;
+    }
+
+    /*
+     * This procedure operates in four stages:
+     * 1. Scan the format string, collecting information about each field.
+     * 2. Allocate an array to hold all of the scanned fields.
+     * 3. Call sscanf to do all the dirty work, and have it store the
+     *    parsed fields in the array.
+     * 4. Pick off the fields from the array and assign them to variables.
+     */
+
+    code = TCL_OK;
+    results = NULL;
+    length = strlen(argv[2]) * 2 + 1;
+    if (length < STATIC_SIZE) {
+	fmtCopy = copyBuf;
+    } else {
+	fmtCopy = (char *) ckalloc((unsigned) length);
+    }
+    dst = fmtCopy;
+    for (fmt = argv[2]; *fmt != 0; fmt++) {
+	*dst = *fmt;
+	dst++;
+	if (*fmt != '%') {
+	    continue;
+	}
+	fmt++;
+	if (*fmt == '%') {
+	    *dst = *fmt;
+	    dst++;
+	    continue;
+	}
+	if (*fmt == '*') {
+	    suppress = 1;
+	    *dst = *fmt;
+	    dst++;
+	    fmt++;
+	} else {
+	    suppress = 0;
+	}
+	widthSpecified = 0;
+	while (isdigit(UCHAR(*fmt))) {
+	    widthSpecified = 1;
+	    *dst = *fmt;
+	    dst++;
+	    fmt++;
+	}
+	if ((*fmt == 'l') || (*fmt == 'h') || (*fmt == 'L')) {
+	    fmt++;
+	}
+	*dst = *fmt;
+	dst++;
+	if (suppress) {
+	    continue;
+	}
+	if (numFields == MAX_FIELDS) {
+	    Tcl_SetResult(interp, "too many fields to scan", TCL_STATIC);
+	    code = TCL_ERROR;
+	    goto done;
+	}
+	curField = &fields[numFields];
+	numFields++;
+	switch (*fmt) {
+	    case 'd':
+	    case 'i':
+	    case 'o':
+	    case 'x':
+		curField->fmt = 'd';
+		curField->size = sizeof(int);
+		break;
+
+	    case 'u':
+		curField->fmt = 'u';
+		curField->size = sizeof(int);
+		break;
+
+	    case 's':
+		curField->fmt = 's';
+		curField->size = strlen(argv[1]) + 1;
+		break;
+
+	    case 'c':
+                if (widthSpecified) {
+		    Tcl_SetResult(interp,
+		            "field width may not be specified in %c conversion",
+			    TCL_STATIC);
+		    code = TCL_ERROR;
+		    goto done;
+                }
+		curField->fmt = 'c';
+		curField->size = sizeof(int);
+		break;
+
+	    case 'e':
+	    case 'f':
+	    case 'g':
+		dst[-1] = 'l';
+		dst[0] = 'f';
+		dst++;
+		curField->fmt = 'f';
+		curField->size = sizeof(double);
+		break;
+
+	    case '[':
+		curField->fmt = 's';
+		curField->size = strlen(argv[1]) + 1;
+		do {
+		    fmt++;
+		    if (*fmt == 0) {
+			Tcl_SetResult(interp,
+			        "unmatched [ in format string", TCL_STATIC);
+			code = TCL_ERROR;
+			goto done;
+		    }
+		    *dst = *fmt;
+		    dst++;
+		} while (*fmt != ']');
+		break;
+
+	    default:
+		{
+		    char buf[50];
+
+		    sprintf(buf, "bad scan conversion character \"%c\"", *fmt);
+		    Tcl_SetResult(interp, buf, TCL_VOLATILE);
+		    code = TCL_ERROR;
+		    goto done;
+		}
+	}
+	curField->size = TCL_ALIGN(curField->size);
+	totalSize += curField->size;
+    }
+    *dst = 0;
+
+    if (numFields != (argc-3)) {
+	Tcl_SetResult(interp,
+		"different numbers of variable names and field specifiers",
+		TCL_STATIC);
+	code = TCL_ERROR;
+	goto done;
+    }
+
+    /*
+     * Step 2:
+     */
+
+    results = (char *) ckalloc((unsigned) totalSize);
+    for (i = 0, totalSize = 0, curField = fields;
+	    i < numFields; i++, curField++) {
+	curField->location = results + totalSize;
+	totalSize += curField->size;
+    }
+
+    /*
+     * Fill in the remaining fields with NULL;  the only purpose of
+     * this is to keep some memory analyzers, like Purify, from
+     * complaining.
+     */
+
+    for ( ; i < MAX_FIELDS; i++, curField++) {
+	curField->location = NULL;
+    }
+
+    /*
+     * Step 3:
+     */
+
+    numScanned = sscanf(argv[1], fmtCopy,
+	    fields[0].location, fields[1].location, fields[2].location,
+	    fields[3].location, fields[4].location, fields[5].location,
+	    fields[6].location, fields[7].location, fields[8].location,
+	    fields[9].location, fields[10].location, fields[11].location,
+	    fields[12].location, fields[13].location, fields[14].location,
+	    fields[15].location, fields[16].location, fields[17].location,
+	    fields[18].location, fields[19].location);
+
+    /*
+     * Step 4:
+     */
+
+    if (numScanned < numFields) {
+	numFields = numScanned;
+    }
+    for (i = 0, curField = fields; i < numFields; i++, curField++) {
+	switch (curField->fmt) {
+	    char string[TCL_DOUBLE_SPACE];
+
+	    case 'd':
+		TclFormatInt(string, *((int *) curField->location));
+		if (Tcl_SetVar(interp, argv[i+3], string, 0) == NULL) {
+		    storeError:
+		    Tcl_AppendResult(interp,
+			    "couldn't set variable \"", argv[i+3], "\"",
+			    (char *) NULL);
+		    code = TCL_ERROR;
+		    goto done;
+		}
+		break;
+
+	    case 'u':
+		sprintf(string, "%u", *((int *) curField->location));
+		if (Tcl_SetVar(interp, argv[i+3], string, 0) == NULL) {
+		    goto storeError;
+		}
+		break;
+
+	    case 'c':
+		TclFormatInt(string, *((char *) curField->location) & 0xff);
+		if (Tcl_SetVar(interp, argv[i+3], string, 0) == NULL) {
+		    goto storeError;
+		}
+		break;
+
+	    case 's':
+		if (Tcl_SetVar(interp, argv[i+3], curField->location, 0)
+			== NULL) {
+		    goto storeError;
+		}
+		break;
+
+	    case 'f':
+		Tcl_PrintDouble((Tcl_Interp *) NULL,
+			*((double *) curField->location), string);
+		if (Tcl_SetVar(interp, argv[i+3], string, 0) == NULL) {
+		    goto storeError;
+		}
+		break;
+	}
+    }
+    TclFormatInt(buf, numScanned);
+    Tcl_SetResult(interp, buf, TCL_VOLATILE);
+    done:
+    if (results != NULL) {
+	ckfree(results);
+    }
+    if (fmtCopy != copyBuf) {
+	ckfree(fmtCopy);
+    }
+    return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SplitObjCmd --
+ *
+ *	This procedure is invoked to process the "split" Tcl command.
+ *	See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_SplitObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    register char *p, *p2;
+    char *splitChars, *string, *elementStart;
+    int splitCharLen, stringLen, i, j;
+    Tcl_Obj *listPtr;
+
+    if (objc == 2) {
+	splitChars = " \n\t\r";
+	splitCharLen = 4;
+    } else if (objc == 3) {
+	splitChars = Tcl_GetStringFromObj(objv[2], &splitCharLen);
+    } else {
+	Tcl_WrongNumArgs(interp, 1, objv, "string ?splitChars?");
+	return TCL_ERROR;
+    }
+
+    string = Tcl_GetStringFromObj(objv[1], &stringLen);
+    listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+    
+    /*
+     * Handle the special case of splitting on every character.
+     */
+
+    if (splitCharLen == 0) {
+	for (i = 0, p = string;  i < stringLen;  i++, p++) {
+	    Tcl_ListObjAppendElement(interp, listPtr,
+                    Tcl_NewStringObj(p, 1));
+	}
+    } else {
+	/*
+	 * Normal case: split on any of a given set of characters.
+	 * Discard instances of the split characters.
+	 */
+
+	for (i = 0, p = elementStart = string;  i < stringLen;  i++, p++) {
+	    for (j = 0, p2 = splitChars;  j < splitCharLen;  j++, p2++) {
+		if (*p2 == *p) {
+		    Tcl_ListObjAppendElement(interp, listPtr,
+                            Tcl_NewStringObj(elementStart, (p-elementStart)));
+		    elementStart = p+1;
+		    break;
+		}
+	    }
+	}
+	if (p != string) {
+	    int remainingChars = stringLen - (elementStart-string);
+	    Tcl_ListObjAppendElement(interp, listPtr,
+                    Tcl_NewStringObj(elementStart, remainingChars));
+	}
+    }
+
+    Tcl_SetObjResult(interp, listPtr);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_StringObjCmd --
+ *
+ *	This procedure is invoked to process the "string" Tcl command.
+ *	See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_StringObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    int index, left, right;
+    Tcl_Obj *resultPtr;
+    char *string1, *string2;
+    int length1, length2;
+    static char *options[] = {
+	"compare",	"first",	"index",	"last",
+	"length",	"match",	"range",	"tolower",
+	"toupper",	"trim",		"trimleft",	"trimright",
+	"wordend",	"wordstart",	NULL
+    };
+    enum options {
+	STR_COMPARE,	STR_FIRST,	STR_INDEX,	STR_LAST,
+	STR_LENGTH,	STR_MATCH,	STR_RANGE,	STR_TOLOWER,
+	STR_TOUPPER,	STR_TRIM,	STR_TRIMLEFT,	STR_TRIMRIGHT,
+	STR_WORDEND,	STR_WORDSTART
+    };	  
+	    
+    if (objc < 2) {
+        Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
+	return TCL_ERROR;
+    }
+    
+    if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0,
+	    &index) != TCL_OK) {
+	return TCL_ERROR;
+    }
+
+    resultPtr = Tcl_GetObjResult(interp);
+    switch ((enum options) index) {
+	case STR_COMPARE: {
+	    int match, length;
+
+	    if (objc != 4) {
+	        Tcl_WrongNumArgs(interp, 2, objv, "string1 string2");
+		return TCL_ERROR;
+	    }
+
+	    string1 = Tcl_GetStringFromObj(objv[2], &length1);
+	    string2 = Tcl_GetStringFromObj(objv[3], &length2);
+
+	    length = (length1 < length2) ? length1 : length2;
+	    match = memcmp(string1, string2, (unsigned) length);
+	    if (match == 0) {
+	        match = length1 - length2;
+	    }
+	    Tcl_SetIntObj(resultPtr, (match > 0) ? 1 : (match < 0) ? -1 : 0);
+	    break;
+	}
+	case STR_FIRST: {
+	    register char *p, *end;
+	    int match;
+
+	    if (objc != 4) {
+	        badFirstLastArgs:
+	        Tcl_WrongNumArgs(interp, 2, objv, "string1 string2");
+		return TCL_ERROR;
+	    }
+
+	    match = -1;
+	    string1 = Tcl_GetStringFromObj(objv[2], &length1);
+	    string2 = Tcl_GetStringFromObj(objv[3], &length2);
+	    if (length1 > 0) {
+		end = string2 + length2 - length1 + 1;
+		for (p = string2;  p < end;  p++) {
+		  /*
+		   * Scan forward to find the first character.
+		   */
+		    
+		  p = memchr(p, *string1, (unsigned) (end - p));
+		  if (p == NULL) {
+		      break;
+		  }
+		  if (memcmp(string1, p, (unsigned) length1) == 0) {
+		      match = p - string2;
+		      break;
+		  }
+		}
+	    }
+	    Tcl_SetIntObj(resultPtr, match);
+	    break;
+	}
+	case STR_INDEX: {
+	    int index;
+
+	    if (objc != 4) {
+	        Tcl_WrongNumArgs(interp, 2, objv, "string charIndex");
+		return TCL_ERROR;
+	    }
+
+	    string1 = Tcl_GetStringFromObj(objv[2], &length1);
+	    if (Tcl_GetIntFromObj(interp, objv[3], &index) != TCL_OK) {
+		return TCL_ERROR;
+	    }
+	    if ((index >= 0) && (index < length1)) {
+	        Tcl_SetStringObj(resultPtr, string1 + index, 1);
+	    }
+	    break;
+	}
+	case STR_LAST: {
+	    register char *p;
+	    int match;
+
+	    if (objc != 4) {
+	        goto badFirstLastArgs;
+	    }
+
+	    match = -1;
+	    string1 = Tcl_GetStringFromObj(objv[2], &length1);
+	    string2 = Tcl_GetStringFromObj(objv[3], &length2);
+	    if (length1 > 0) {
+		for (p = string2 + length2 - length1;  p >= string2;  p--) {
+		    /*
+		     * Scan backwards to find the first character.
+		     */
+		    
+		    while ((p != string2) && (*p != *string1)) {
+			p--;
+		    }
+		    if (memcmp(string1, p, (unsigned) length1) == 0) {
+			match = p - string2;
+			break;
+		    }
+		}
+	    }
+	    Tcl_SetIntObj(resultPtr, match);
+	    break;
+	}
+	case STR_LENGTH: {
+	    if (objc != 3) {
+	        Tcl_WrongNumArgs(interp, 2, objv, "string");
+		return TCL_ERROR;
+	    }
+
+	    (void) Tcl_GetStringFromObj(objv[2], &length1);
+	    Tcl_SetIntObj(resultPtr, length1);
+	    break;
+	}
+	case STR_MATCH: {
+	    if (objc != 4) {
+	        Tcl_WrongNumArgs(interp, 2, objv, "pattern string");
+		return TCL_ERROR;
+	    }
+
+	    string1 = Tcl_GetStringFromObj(objv[2], &length1);
+	    string2 = Tcl_GetStringFromObj(objv[3], &length2);
+	    Tcl_SetBooleanObj(resultPtr, Tcl_StringMatch(string2, string1));
+	    break;
+	}
+	case STR_RANGE: {
+	    int first, last;
+
+	    if (objc != 5) {
+	        Tcl_WrongNumArgs(interp, 2, objv, "string first last");
+		return TCL_ERROR;
+	    }
+
+	    string1 = Tcl_GetStringFromObj(objv[2], &length1);
+	    if (TclGetIntForIndex(interp, objv[3], length1 - 1,
+		    &first) != TCL_OK) {
+		return TCL_ERROR;
+	    }
+	    if (TclGetIntForIndex(interp, objv[4], length1 - 1,
+		    &last) != TCL_OK) {
+		return TCL_ERROR;
+	    }
+	    if (first < 0) {
+		first = 0;
+	    }
+	    if (last >= length1 - 1) {
+		last = length1 - 1;
+	    }
+	    if (last >= first) {
+	        Tcl_SetStringObj(resultPtr, string1 + first, last - first + 1);
+	    }
+	    break;
+	}
+	case STR_TOLOWER: {
+	    register char *p, *end;
+
+	    if (objc != 3) {
+	        Tcl_WrongNumArgs(interp, 2, objv, "string");
+		return TCL_ERROR;
+	    }
+
+	    string1 = Tcl_GetStringFromObj(objv[2], &length1);
+
+	    /*
+	     * Since I know resultPtr is not a shared object, I can reach
+	     * in and diddle the bytes in its string rep to convert them in
+	     * place to lower case.
+	     */
+
+	    Tcl_SetStringObj(resultPtr, string1, length1);
+	    string1 = Tcl_GetStringFromObj(resultPtr, &length1);
+	    end = string1 + length1;
+	    for (p = string1; p < end; p++) {
+		if (isupper(UCHAR(*p))) {
+		    *p = (char) tolower(UCHAR(*p));
+		}
+	    }
+	    break;
+	}
+	case STR_TOUPPER: {
+	    register char *p, *end;
+
+	    if (objc != 3) {
+	        Tcl_WrongNumArgs(interp, 2, objv, "string");
+		return TCL_ERROR;
+	    }
+
+	    string1 = Tcl_GetStringFromObj(objv[2], &length1);
+
+	    /*
+	     * Since I know resultPtr is not a shared object, I can reach
+	     * in and diddle the bytes in its string rep to convert them in
+	     * place to upper case.
+	     */
+
+	    Tcl_SetStringObj(resultPtr, string1, length1);
+	    string1 = Tcl_GetStringFromObj(resultPtr, &length1);
+	    end = string1 + length1;
+	    for (p = string1; p < end; p++) {
+		if (islower(UCHAR(*p))) {
+		    *p = (char) toupper(UCHAR(*p));
+		}
+	    }
+	    break;
+	}
+	case STR_TRIM: {
+	    char ch;
+	    register char *p, *end;
+	    char *check, *checkEnd;
+
+	    left = 1;
+	    right = 1;
+
+	    trim:
+	    if (objc == 4) {
+		string2 = Tcl_GetStringFromObj(objv[3], &length2);
+	    } else if (objc == 3) {
+		string2 = " \t\n\r";
+		length2 = strlen(string2);
+	    } else {
+	        Tcl_WrongNumArgs(interp, 2, objv, "string ?chars?");
+		return TCL_ERROR;
+	    }
+	    string1 = Tcl_GetStringFromObj(objv[2], &length1);
+	    checkEnd = string2 + length2;
+
+	    if (left) {
+		end = string1 + length1;
+		for (p = string1; p < end; p++) {
+		    ch = *p;
+		    for (check = string2; ; check++) {
+			if (check >= checkEnd) {
+			    p = end;
+			    break;
+			}
+			if (ch == *check) {
+			    length1--;
+			    string1++;
+			    break;
+			}
+		    }
+		}
+	    }
+	    if (right) {
+	        end = string1;
+		for (p = string1 + length1; p > end; ) {
+		    p--;
+		    ch = *p;
+		    for (check = string2; ; check++) {
+		        if (check >= checkEnd) {
+			    p = end;
+			    break;
+			}
+			if (ch == *check) {
+			    length1--;
+			    break;
+			}
+		    }
+		}
+	    }
+	    Tcl_SetStringObj(resultPtr, string1, length1);
+	    break;
+	}
+	case STR_TRIMLEFT: {
+	    left = 1;
+	    right = 0;
+	    goto trim;
+	}
+	case STR_TRIMRIGHT: {
+	    left = 0;
+	    right = 1;
+	    goto trim;
+	}
+	case STR_WORDEND: {
+	    int cur, c;
+	    
+	    if (objc != 4) {
+	        Tcl_WrongNumArgs(interp, 2, objv, "string index");
+		return TCL_ERROR;
+	    }
+
+	    string1 = Tcl_GetStringFromObj(objv[2], &length1);
+	    if (Tcl_GetIntFromObj(interp, objv[3], &index) != TCL_OK) {
+	        return TCL_ERROR;
+	    }
+	    if (index < 0) {
+		index = 0;
+	    }
+	    cur = length1;
+	    if (index < length1) {
+		for (cur = index; cur < length1; cur++) {
+		    c = UCHAR(string1[cur]);
+		    if (!isalnum(c) && (c != '_')) {
+			break;
+		    }
+		}
+		if (cur == index) {
+		    cur = index + 1;
+		}
+	    }
+	    Tcl_SetIntObj(resultPtr, cur);
+	    break;
+	}
+	case STR_WORDSTART: {
+	    int cur, c;
+	    
+	    if (objc != 4) {
+	        Tcl_WrongNumArgs(interp, 2, objv, "string index");
+		return TCL_ERROR;
+	    }
+
+	    string1 = Tcl_GetStringFromObj(objv[2], &length1);
+	    if (Tcl_GetIntFromObj(interp, objv[3], &index) != TCL_OK) {
+		return TCL_ERROR;
+	    }
+	    if (index >= length1) {
+		index = length1 - 1;
+	    }
+	    cur = 0;
+	    if (index > 0) {
+	        for (cur = index; cur >= 0; cur--) {
+		    c = UCHAR(string1[cur]);
+		    if (!isalnum(c) && (c != '_')) {
+			break;
+		    }
+		}
+		if (cur != index) {
+		    cur += 1;
+		}
+	    }
+	    Tcl_SetIntObj(resultPtr, cur);
+	    break;
+	}
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SubstCmd --
+ *
+ *	This procedure is invoked to process the "subst" Tcl command.
+ *	See the user documentation for details on what it does.  This
+ *	command is an almost direct copy of an implementation by
+ *	Andrew Payne.
+ *
+ * Results:
+ *	A standard Tcl result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_SubstCmd(dummy, interp, argc, argv)
+    ClientData dummy;			/* Not used. */
+    Tcl_Interp *interp;			/* Current interpreter. */
+    int argc;				/* Number of arguments. */
+    char **argv;			/* Argument strings. */
+{
+    Interp *iPtr = (Interp *) interp;
+    Tcl_DString result;
+    char *p, *old, *value;
+    int code, count, doVars, doCmds, doBackslashes, i;
+    size_t length;
+    char c;
+
+    /*
+     * Parse command-line options.
+     */
+
+    doVars = doCmds = doBackslashes = 1;
+    for (i = 1; i < (argc-1); i++) {
+	p = argv[i];
+	if (*p != '-') {
+	    break;
+	}
+	length = strlen(p);
+	if (length < 4) {
+	    badSwitch:
+	    Tcl_AppendResult(interp, "bad switch \"", p,
+		    "\": must be -nobackslashes, -nocommands, ",
+		    "or -novariables", (char *) NULL);
+	    return TCL_ERROR;
+	}
+	if ((p[3] == 'b') && (strncmp(p, "-nobackslashes", length) == 0)) {
+	    doBackslashes = 0;
+	} else if ((p[3] == 'c') && (strncmp(p, "-nocommands", length) == 0)) {
+	    doCmds = 0;
+	} else if ((p[3] == 'v') && (strncmp(p, "-novariables", length) == 0)) {
+	    doVars = 0;
+	} else {
+	    goto badSwitch;
+	}
+    }
+    if (i != (argc-1)) {
+	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+		" ?-nobackslashes? ?-nocommands? ?-novariables? string\"",
+		(char *) NULL);
+	return TCL_ERROR;
+    }
+
+    /*
+     * Scan through the string one character at a time, performing
+     * command, variable, and backslash substitutions.
+     */
+
+    Tcl_DStringInit(&result);
+    old = p = argv[i];
+    while (*p != 0) {
+	switch (*p) {
+	    case '\\':
+		if (doBackslashes) {
+		    if (p != old) {
+			Tcl_DStringAppend(&result, old, p-old);
+		    }
+		    c = Tcl_Backslash(p, &count);
+		    Tcl_DStringAppend(&result, &c, 1);
+		    p += count;
+		    old = p;
+		} else {
+		    p++;
+		}
+		break;
+
+	    case '$':
+		if (doVars) {
+		    if (p != old) {
+			Tcl_DStringAppend(&result, old, p-old);
+		    }
+		    value = Tcl_ParseVar(interp, p, &p);
+		    if (value == NULL) {
+			Tcl_DStringFree(&result);
+			return TCL_ERROR;
+		    }
+		    Tcl_DStringAppend(&result, value, -1);
+		    old = p;
+		} else {
+		    p++;
+		}
+		break;
+
+	    case '[':
+		if (doCmds) {
+		    if (p != old) {
+			Tcl_DStringAppend(&result, old, p-old);
+		    }
+		    iPtr->evalFlags = TCL_BRACKET_TERM;
+		    code = Tcl_Eval(interp, p+1);
+		    if (code == TCL_ERROR) {
+			Tcl_DStringFree(&result);
+			return code;
+		    }
+		    old = p = (p+1 + iPtr->termOffset+1);
+		    Tcl_DStringAppend(&result, iPtr->result, -1);
+		    Tcl_ResetResult(interp);
+		} else {
+		    p++;
+		}
+		break;
+
+	    default:
+		p++;
+		break;
+	}
+    }
+    if (p != old) {
+	Tcl_DStringAppend(&result, old, p-old);
+    }
+    Tcl_DStringResult(interp, &result);
+    return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_TraceCmd --
+ *
+ *	This procedure is invoked to process the "trace" Tcl command.
+ *	See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl result.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_TraceCmd(dummy, interp, argc, argv)
+    ClientData dummy;			/* Not used. */
+    Tcl_Interp *interp;			/* Current interpreter. */
+    int argc;				/* Number of arguments. */
+    char **argv;			/* Argument strings. */
+{
+    int c;
+    size_t length;
+
+    if (argc < 2) {
+	Tcl_AppendResult(interp, "too few args: should be \"",
+		argv[0], " option [arg arg ...]\"", (char *) NULL);
+	return TCL_ERROR;
+    }
+    c = argv[1][1];
+    length = strlen(argv[1]);
+    if ((c == 'a') && (strncmp(argv[1], "variable", length) == 0)
+	    && (length >= 2)) {
+	char *p;
+	int flags, length;
+	TraceVarInfo *tvarPtr;
+
+	if (argc != 5) {
+	    Tcl_AppendResult(interp, "wrong # args: should be \"",
+		    argv[0], " variable name ops command\"", (char *) NULL);
+	    return TCL_ERROR;
+	}
+
+	flags = 0;
+	for (p = argv[3] ; *p != 0; p++) {
+	    if (*p == 'r') {
+		flags |= TCL_TRACE_READS;
+	    } else if (*p == 'w') {
+		flags |= TCL_TRACE_WRITES;
+	    } else if (*p == 'u') {
+		flags |= TCL_TRACE_UNSETS;
+	    } else {
+		goto badOps;
+	    }
+	}
+	if (flags == 0) {
+	    goto badOps;
+	}
+
+	length = strlen(argv[4]);
+	tvarPtr = (TraceVarInfo *) ckalloc((unsigned)
+		(sizeof(TraceVarInfo) - sizeof(tvarPtr->command) + length + 1));
+	tvarPtr->flags = flags;
+	tvarPtr->errMsg = NULL;
+	tvarPtr->length = length;
+	flags |= TCL_TRACE_UNSETS;
+	strcpy(tvarPtr->command, argv[4]);
+	if (Tcl_TraceVar(interp, argv[2], flags, TraceVarProc,
+		(ClientData) tvarPtr) != TCL_OK) {
+	    ckfree((char *) tvarPtr);
+	    return TCL_ERROR;
+	}
+    } else if ((c == 'd') && (strncmp(argv[1], "vdelete", length)
+	    && (length >= 2)) == 0) {
+	char *p;
+	int flags, length;
+	TraceVarInfo *tvarPtr;
+	ClientData clientData;
+
+	if (argc != 5) {
+	    Tcl_AppendResult(interp, "wrong # args: should be \"",
+		    argv[0], " vdelete name ops command\"", (char *) NULL);
+	    return TCL_ERROR;
+	}
+
+	flags = 0;
+	for (p = argv[3] ; *p != 0; p++) {
+	    if (*p == 'r') {
+		flags |= TCL_TRACE_READS;
+	    } else if (*p == 'w') {
+		flags |= TCL_TRACE_WRITES;
+	    } else if (*p == 'u') {
+		flags |= TCL_TRACE_UNSETS;
+	    } else {
+		goto badOps;
+	    }
+	}
+	if (flags == 0) {
+	    goto badOps;
+	}
+
+	/*
+	 * Search through all of our traces on this variable to
+	 * see if there's one with the given command.  If so, then
+	 * delete the first one that matches.
+	 */
+
+	length = strlen(argv[4]);
+	clientData = 0;
+	while ((clientData = Tcl_VarTraceInfo(interp, argv[2], 0,
+		TraceVarProc, clientData)) != 0) {
+	    tvarPtr = (TraceVarInfo *) clientData;
+	    if ((tvarPtr->length == length) && (tvarPtr->flags == flags)
+		    && (strncmp(argv[4], tvarPtr->command,
+		    (size_t) length) == 0)) {
+		Tcl_UntraceVar(interp, argv[2], flags | TCL_TRACE_UNSETS,
+			TraceVarProc, clientData);
+		if (tvarPtr->errMsg != NULL) {
+		    ckfree(tvarPtr->errMsg);
+		}
+		ckfree((char *) tvarPtr);
+		break;
+	    }
+	}
+    } else if ((c == 'i') && (strncmp(argv[1], "vinfo", length) == 0)
+	    && (length >= 2)) {
+	ClientData clientData;
+	char ops[4], *p;
+	char *prefix = "{";
+
+	if (argc != 3) {
+	    Tcl_AppendResult(interp, "wrong # args: should be \"",
+		    argv[0], " vinfo name\"", (char *) NULL);
+	    return TCL_ERROR;
+	}
+	clientData = 0;
+	while ((clientData = Tcl_VarTraceInfo(interp, argv[2], 0,
+		TraceVarProc, clientData)) != 0) {
+	    TraceVarInfo *tvarPtr = (TraceVarInfo *) clientData;
+	    p = ops;
+	    if (tvarPtr->flags & TCL_TRACE_READS) {
+		*p = 'r';
+		p++;
+	    }
+	    if (tvarPtr->flags & TCL_TRACE_WRITES) {
+		*p = 'w';
+		p++;
+	    }
+	    if (tvarPtr->flags & TCL_TRACE_UNSETS) {
+		*p = 'u';
+		p++;
+	    }
+	    *p = '\0';
+	    Tcl_AppendResult(interp, prefix, (char *) NULL);
+	    Tcl_AppendElement(interp, ops);
+	    Tcl_AppendElement(interp, tvarPtr->command);
+	    Tcl_AppendResult(interp, "}", (char *) NULL);
+	    prefix = " {";
+	}
+    } else {
+	Tcl_AppendResult(interp, "bad option \"", argv[1],
+		"\": should be variable, vdelete, or vinfo",
+		(char *) NULL);
+	return TCL_ERROR;
+    }
+    return TCL_OK;
+
+    badOps:
+    Tcl_AppendResult(interp, "bad operations \"", argv[3],
+	    "\": should be one or more of rwu", (char *) NULL);
+    return TCL_ERROR;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TraceVarProc --
+ *
+ *	This procedure is called to handle variable accesses that have
+ *	been traced using the "trace" command.
+ *
+ * Results:
+ *	Normally returns NULL.  If the trace command returns an error,
+ *	then this procedure returns an error string.
+ *
+ * Side effects:
+ *	Depends on the command associated with the trace.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+static char *
+TraceVarProc(clientData, interp, name1, name2, flags)
+    ClientData clientData;	/* Information about the variable trace. */
+    Tcl_Interp *interp;		/* Interpreter containing variable. */
+    char *name1;		/* Name of variable or array. */
+    char *name2;		/* Name of element within array;  NULL means
+				 * scalar variable is being referenced. */
+    int flags;			/* OR-ed bits giving operation and other
+				 * information. */
+{
+    Interp *iPtr = (Interp *) interp;
+    TraceVarInfo *tvarPtr = (TraceVarInfo *) clientData;
+    char *result;
+    int code;
+    Interp dummy;
+    Tcl_DString cmd;
+    Tcl_Obj *saveObjPtr, *oldObjResultPtr;
+
+    result = NULL;
+    if (tvarPtr->errMsg != NULL) {
+	ckfree(tvarPtr->errMsg);
+	tvarPtr->errMsg = NULL;
+    }
+    if ((tvarPtr->flags & flags) && !(flags & TCL_INTERP_DESTROYED)) {
+
+	/*
+	 * Generate a command to execute by appending list elements
+	 * for the two variable names and the operation.  The five
+	 * extra characters are for three space, the opcode character,
+	 * and the terminating null.
+	 */
+
+	if (name2 == NULL) {
+	    name2 = "";
+	}
+	Tcl_DStringInit(&cmd);
+	Tcl_DStringAppend(&cmd, tvarPtr->command, tvarPtr->length);
+	Tcl_DStringAppendElement(&cmd, name1);
+	Tcl_DStringAppendElement(&cmd, name2);
+	if (flags & TCL_TRACE_READS) {
+	    Tcl_DStringAppend(&cmd, " r", 2);
+	} else if (flags & TCL_TRACE_WRITES) {
+	    Tcl_DStringAppend(&cmd, " w", 2);
+	} else if (flags & TCL_TRACE_UNSETS) {
+	    Tcl_DStringAppend(&cmd, " u", 2);
+	}
+
+	/*
+	 * Execute the command.  Be careful to save and restore both the
+	 * string and object results from the interpreter used for
+	 * the command. We discard any object result the command returns.
+	 */
+
+	dummy.objResultPtr = Tcl_NewObj();
+	Tcl_IncrRefCount(dummy.objResultPtr);
+	if (interp->freeProc == 0) {
+	    dummy.freeProc = (Tcl_FreeProc *) 0;
+	    dummy.result = "";
+	    Tcl_SetResult((Tcl_Interp *) &dummy, interp->result,
+		    TCL_VOLATILE);
+	} else {
+	    dummy.freeProc = interp->freeProc;
+	    dummy.result = interp->result;
+	    interp->freeProc = (Tcl_FreeProc *) 0;
+	}
+	
+	saveObjPtr = Tcl_GetObjResult(interp);
+	Tcl_IncrRefCount(saveObjPtr);
+	
+	code = Tcl_Eval(interp, Tcl_DStringValue(&cmd));
+	if (code != TCL_OK) {	     /* copy error msg to result */
+	    tvarPtr->errMsg = (char *)
+		    ckalloc((unsigned) (strlen(interp->result) + 1));
+	    strcpy(tvarPtr->errMsg, interp->result);
+	    result = tvarPtr->errMsg;
+	    Tcl_ResetResult(interp); /* must clear error state. */
+	}
+
+	/*
+	 * Restore the interpreter's string result.
+	 */
+	
+	Tcl_SetResult(interp, dummy.result,
+		(dummy.freeProc == 0) ? TCL_VOLATILE : dummy.freeProc);
+
+	/*
+	 * Restore the interpreter's object result from saveObjPtr.
+	 */
+
+	oldObjResultPtr = iPtr->objResultPtr;
+	iPtr->objResultPtr = saveObjPtr;  /* was incremented above */
+	Tcl_DecrRefCount(oldObjResultPtr);
+
+	Tcl_DecrRefCount(dummy.objResultPtr);
+	dummy.objResultPtr = NULL;
+	Tcl_DStringFree(&cmd);
+    }
+    if (flags & TCL_TRACE_DESTROYED) {
+	result = NULL;
+	if (tvarPtr->errMsg != NULL) {
+	    ckfree(tvarPtr->errMsg);
+	}
+	ckfree((char *) tvarPtr);
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_WhileCmd --
+ *
+ *      This procedure is invoked to process the "while" Tcl command.
+ *      See the user documentation for details on what it does.
+ *
+ *	With the bytecode compiler, this procedure is only called when
+ *	a command name is computed at runtime, and is "while" or the name
+ *	to which "while" was renamed: e.g., "set z while; $z {$i<100} {}"
+ *
+ * Results:
+ *      A standard Tcl result.
+ *
+ * Side effects:
+ *      See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+        /* ARGSUSED */
+int
+Tcl_WhileCmd(dummy, interp, argc, argv)
+    ClientData dummy;                   /* Not used. */
+    Tcl_Interp *interp;                 /* Current interpreter. */
+    int argc;                           /* Number of arguments. */
+    char **argv;                        /* Argument strings. */
+{
+    int result, value;
+
+    if (argc != 3) {
+        Tcl_AppendResult(interp, "wrong # args: should be \"",
+                argv[0], " test command\"", (char *) NULL);
+        return TCL_ERROR;
+    }
+
+    while (1) {
+        result = Tcl_ExprBoolean(interp, argv[1], &value);
+        if (result != TCL_OK) {
+            return result;
+        }
+        if (!value) {
+            break;
+        }
+        result = Tcl_Eval(interp, argv[2]);
+        if ((result != TCL_OK) && (result != TCL_CONTINUE)) {
+            if (result == TCL_ERROR) {
+                char msg[60];
+                sprintf(msg, "\n    (\"while\" body line %d)",
+                        interp->errorLine);
+                Tcl_AddErrorInfo(interp, msg);
+            }
+            break;
+        }
+    }
+    if (result == TCL_BREAK) {
+        result = TCL_OK;
+    }
+    if (result == TCL_OK) {
+        Tcl_ResetResult(interp);
+    }
+    return result;
+}
+
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclCompExpr.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclCompExpr.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclCompExpr.c	(revision 5)
@@ -0,0 +1,2403 @@
+/* 
+ * tclCompExpr.c --
+ *
+ *	This file contains the code to compile Tcl expressions.
+ *
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclCompExpr.c,v 1.1 2008-06-04 13:58:05 demin Exp $
+ */
+
+#include "tclInt.h"
+#include "tclCompile.h"
+
+/*
+ * The stuff below is a bit of a hack so that this file can be used in
+ * environments that include no UNIX, i.e. no errno: just arrange to use
+ * the errno from tclExecute.c here.
+ */
+
+#ifndef TCL_GENERIC_ONLY
+#include "tclPort.h"
+#else
+#define NO_ERRNO_H
+#endif
+
+#ifdef NO_ERRNO_H
+extern int errno;			/* Use errno from tclExecute.c. */
+#define ERANGE 34
+#endif
+
+/*
+ * Boolean variable that controls whether expression compilation tracing
+ * is enabled.
+ */
+
+#ifdef TCL_COMPILE_DEBUG
+static int traceCompileExpr = 0;
+#endif /* TCL_COMPILE_DEBUG */
+
+/*
+ * The ExprInfo structure describes the state of compiling an expression.
+ * A pointer to an ExprInfo record is passed among the routines in
+ * this module.
+ */
+
+typedef struct ExprInfo {
+    int token;			/* Type of the last token parsed in expr.
+				 * See below for definitions. Corresponds
+				 * to the characters just before next. */
+    int objIndex;		/* If token is a literal value, the index of
+				 * an object holding the value in the code's
+				 * object table; otherwise is NULL. */
+    char *funcName;		/* If the token is FUNC_NAME, points to the
+				 * first character of the math function's
+				 * name; otherwise is NULL. */
+    char *next;			/* Position of the next character to be
+				 * scanned in the expression string. */
+    char *originalExpr;		/* The entire expression that was originally
+				 * passed to Tcl_ExprString et al. */
+    char *lastChar;		/* Pointer to terminating null in
+				 * originalExpr. */
+    int hasOperators;		/* Set 1 if the expr has operators; 0 if
+				 * expr is only a primary. If 1 after
+				 * compiling an expr, a tryCvtToNumeric
+				 * instruction is emitted to convert the
+				 * primary to a number if possible. */
+    int exprIsJustVarRef;	/* Set 1 if the expr consists of just a
+				 * variable reference as in the expression
+				 * of "if $b then...". Otherwise 0. If 1 the
+				 * expr is compiled out-of-line in order to
+				 * implement expr's 2 level substitution
+				 * semantics properly. */
+    int exprIsComparison;	/* Set 1 if the top-level operator in the
+				 * expr is a comparison. Otherwise 0. If 1,
+				 * because the operands might be strings,
+				 * the expr is compiled out-of-line in order
+				 * to implement expr's 2 level substitution
+				 * semantics properly. */
+} ExprInfo;
+
+/*
+ * Definitions of the different tokens that appear in expressions. The order
+ * of these must match the corresponding entries in the operatorStrings
+ * array below.
+ */
+
+#define LITERAL		0
+#define FUNC_NAME	(LITERAL + 1)
+#define OPEN_BRACKET	(LITERAL + 2)
+#define CLOSE_BRACKET	(LITERAL + 3)
+#define OPEN_PAREN	(LITERAL + 4)
+#define CLOSE_PAREN	(LITERAL + 5)
+#define DOLLAR		(LITERAL + 6)
+#define QUOTE		(LITERAL + 7)
+#define COMMA		(LITERAL + 8)
+#define END		(LITERAL + 9)
+#define UNKNOWN		(LITERAL + 10)
+
+/*
+ * Binary operators:
+ */
+
+#define MULT		(UNKNOWN + 1)
+#define DIVIDE		(MULT + 1)
+#define MOD		(MULT + 2)
+#define PLUS		(MULT + 3)
+#define MINUS		(MULT + 4)
+#define LEFT_SHIFT	(MULT + 5)
+#define RIGHT_SHIFT	(MULT + 6)
+#define LESS		(MULT + 7)
+#define GREATER		(MULT + 8)
+#define LEQ		(MULT + 9)
+#define GEQ		(MULT + 10)
+#define EQUAL		(MULT + 11)
+#define NEQ		(MULT + 12)
+#define BIT_AND		(MULT + 13)
+#define BIT_XOR		(MULT + 14)
+#define BIT_OR		(MULT + 15)
+#define AND		(MULT + 16)
+#define OR		(MULT + 17)
+#define QUESTY		(MULT + 18)
+#define COLON		(MULT + 19)
+
+/*
+ * Unary operators. Unary minus and plus are represented by the (binary)
+ * tokens MINUS and PLUS.
+ */
+
+#define NOT		(COLON + 1)
+#define BIT_NOT		(NOT + 1)
+
+/*
+ * Mapping from tokens to strings; used for debugging messages. These
+ * entries must match the order and number of the token definitions above.
+ */
+
+#ifdef TCL_COMPILE_DEBUG
+static char *tokenStrings[] = {
+    "LITERAL", "FUNCNAME",
+    "[", "]", "(", ")", "$", "\"", ",", "END", "UNKNOWN",
+    "*", "/", "%", "+", "-",
+    "<<", ">>", "<", ">", "<=", ">=", "==", "!=",
+    "&", "^", "|", "&&", "||", "?", ":",
+    "!", "~"
+};
+#endif /* TCL_COMPILE_DEBUG */
+
+/*
+ * Declarations for local procedures to this file:
+ */
+
+static int		CompileAddExpr _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExprInfo *infoPtr, int flags,
+			    CompileEnv *envPtr));
+static int		CompileBitAndExpr _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExprInfo *infoPtr, int flags,
+			    CompileEnv *envPtr));
+static int		CompileBitOrExpr _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExprInfo *infoPtr, int flags,
+			    CompileEnv *envPtr));
+static int		CompileBitXorExpr _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExprInfo *infoPtr, int flags,
+			    CompileEnv *envPtr));
+static int		CompileCondExpr _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExprInfo *infoPtr, int flags,
+			    CompileEnv *envPtr));
+static int		CompileEqualityExpr _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExprInfo *infoPtr, int flags,
+			    CompileEnv *envPtr));
+static int		CompileLandExpr _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExprInfo *infoPtr, int flags,
+			    CompileEnv *envPtr));
+static int		CompileLorExpr _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExprInfo *infoPtr, int flags,
+			    CompileEnv *envPtr));
+static int		CompileMathFuncCall _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExprInfo *infoPtr, int flags,
+			    CompileEnv *envPtr));
+static int		CompileMultiplyExpr _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExprInfo *infoPtr, int flags,
+			    CompileEnv *envPtr));
+static int		CompilePrimaryExpr _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExprInfo *infoPtr, int flags,
+			    CompileEnv *envPtr));
+static int		CompileRelationalExpr _ANSI_ARGS_((
+    			    Tcl_Interp *interp, ExprInfo *infoPtr,
+			    int flags, CompileEnv *envPtr));
+static int		CompileShiftExpr _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExprInfo *infoPtr, int flags,
+			    CompileEnv *envPtr));
+static int		CompileUnaryExpr _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExprInfo *infoPtr, int flags,
+			    CompileEnv *envPtr));
+static int		GetToken _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExprInfo *infoPtr, CompileEnv *envPtr));
+
+/*
+ * Macro used to debug the execution of the recursive descent parser used
+ * to compile expressions.
+ */
+
+#ifdef TCL_COMPILE_DEBUG
+#define HERE(production, level) \
+    if (traceCompileExpr) { \
+	fprintf(stderr, "%*s%s: token=%s, next=\"%.20s\"\n", \
+		(level), " ", (production), tokenStrings[infoPtr->token], \
+		infoPtr->next); \
+    }
+#else
+#define HERE(production, level)
+#endif /* TCL_COMPILE_DEBUG */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileExpr --
+ *
+ *	This procedure compiles a string containing a Tcl expression into
+ *	Tcl bytecodes. This procedure is the top-level interface to the
+ *	the expression compilation module, and is used by such public
+ *	procedures as Tcl_ExprString, Tcl_ExprStringObj, Tcl_ExprLong,
+ *	Tcl_ExprDouble, Tcl_ExprBoolean, and Tcl_ExprBooleanObj.
+ *
+ *	Note that the topmost recursive-descent parsing routine used by
+ *	TclCompileExpr to compile expressions is called "CompileCondExpr"
+ *	and not, e.g., "CompileExpr". This is done to avoid an extra
+ *	procedure call since such a procedure would only return the result
+ *	of calling CompileCondExpr. Other recursive-descent procedures
+ *	that need to parse expressions also call CompileCondExpr.
+ *
+ * Results:
+ *	The return value is TCL_OK on a successful compilation and TCL_ERROR
+ *	on failure. If TCL_ERROR is returned, then the interpreter's result
+ *	contains an error message.
+ *
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one successfully processed; this might
+ *	be the offset of the ']' (if flags & TCL_BRACKET_TERM), or the
+ *	offset of the '\0' at the end of the string.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the expression.
+ *
+ *	envPtr->exprIsJustVarRef is set 1 if the expression consisted of
+ *	a single variable reference as in the expression of "if $b then...".
+ *	Otherwise it is set 0. This is used to implement Tcl's two level
+ *	expression substitution semantics properly.
+ *
+ *	envPtr->exprIsComparison is set 1 if the top-level operator in the
+ *	expr is a comparison. Otherwise it is set 0. If 1, because the
+ *	operands might be strings, the expr is compiled out-of-line in order
+ *	to implement expr's 2 level substitution semantics properly.
+ *
+ * Side effects:
+ *	Adds instructions to envPtr to evaluate the expression at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileExpr(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    char *string;		/* The source string to compile. */
+    char *lastChar;		/* Pointer to terminating character of
+				 * string. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    Interp *iPtr = (Interp *) interp;
+    ExprInfo info;
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute the expression. */
+    int result;
+
+#ifdef TCL_COMPILE_DEBUG
+    if (traceCompileExpr) {
+	fprintf(stderr, "expr: string=\"%.30s\"\n", string);
+    }
+#endif /* TCL_COMPILE_DEBUG */
+
+    /*
+     * Register the builtin math functions the first time an expression is
+     * compiled.
+     */
+
+    if (!(iPtr->flags & EXPR_INITIALIZED)) {
+	BuiltinFunc *funcPtr;
+	Tcl_HashEntry *hPtr;
+	MathFunc *mathFuncPtr;
+	int i;
+
+	iPtr->flags |= EXPR_INITIALIZED;
+	i = 0;
+	for (funcPtr = builtinFuncTable; funcPtr->name != NULL; funcPtr++) {
+	    Tcl_CreateMathFunc(interp, funcPtr->name,
+		    funcPtr->numArgs, funcPtr->argTypes,
+		    (Tcl_MathProc *) NULL, (ClientData) 0);
+	    
+	    hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcPtr->name);
+	    if (hPtr == NULL) {
+		panic("TclCompileExpr: Tcl_CreateMathFunc incorrectly registered '%s'", funcPtr->name);
+		return TCL_ERROR;
+	    }
+	    mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
+	    mathFuncPtr->builtinFuncIndex = i;
+	    i++;
+	}
+    }
+
+    info.token = UNKNOWN;
+    info.objIndex = -1;
+    info.funcName = NULL;
+    info.next = string;
+    info.originalExpr = string;
+    info.lastChar = lastChar;
+    info.hasOperators = 0;
+    info.exprIsJustVarRef = 1;	/* will be set 0 if anything else is seen */
+    info.exprIsComparison = 0;	/* set 1 if topmost operator is <,==,etc. */
+
+    /*
+     * Get the first token then compile an expression.
+     */
+
+    result = GetToken(interp, &info, envPtr);
+    if (result != TCL_OK) {
+	goto done;
+    }
+    
+    result = CompileCondExpr(interp, &info, flags, envPtr);
+    if (result != TCL_OK) {
+	goto done;
+    }
+    if (info.token != END) {
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		"syntax error in expression \"", string, "\"", (char *) NULL);
+	result = TCL_ERROR;
+	goto done;
+    }
+    if (!info.hasOperators) {
+	/*
+	 * Attempt to convert the primary's object to an int or double.
+	 * This is done in order to support Tcl's policy of interpreting
+	 * operands if at all possible as first integers, else
+	 * floating-point numbers.
+	 */
+	
+	TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
+    }
+    maxDepth = envPtr->maxStackDepth;
+
+    done:
+    envPtr->termOffset = (info.next - string);
+    envPtr->maxStackDepth = maxDepth;
+    envPtr->exprIsJustVarRef = info.exprIsJustVarRef;
+    envPtr->exprIsComparison = info.exprIsComparison;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileCondExpr --
+ *
+ *	This procedure compiles a Tcl conditional expression:
+ *	condExpr ::= lorExpr ['?' condExpr ':' condExpr]
+ *
+ *	Note that this is the topmost recursive-descent parsing routine used
+ *	by TclCompileExpr to compile expressions. It does not call an
+ *	separate, higher-level "CompileExpr" procedure. This avoids an extra
+ *	procedure call since such a procedure would only return the result
+ *	of calling CompileCondExpr. Other recursive-descent procedures that
+ *	need to parse expressions also call CompileCondExpr.
+ *
+ * Results:
+ *	The return value is TCL_OK on a successful compilation and TCL_ERROR
+ *	on failure. If TCL_ERROR is returned, then the interpreter's result
+ *	contains an error message.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the expression.
+ *
+ * Side effects:
+ *	Adds instructions to envPtr to evaluate the expression at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileCondExpr(interp, infoPtr, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    ExprInfo *infoPtr;		/* Describes the compilation state for the
+				 * expression being compiled. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute the expression. */
+    JumpFixup jumpAroundThenFixup, jumpAroundElseFixup;
+				/* Used to update or replace one-byte jumps
+				 * around the then and else expressions when
+				 * their target PCs are determined. */
+    int elseCodeOffset, currCodeOffset, jumpDist, result;
+    
+    HERE("condExpr", 1);
+    result = CompileLorExpr(interp, infoPtr, flags, envPtr);
+    if (result != TCL_OK) {
+	goto done;
+    }
+    maxDepth = envPtr->maxStackDepth;
+    
+    if (infoPtr->token == QUESTY) {
+	result = GetToken(interp, infoPtr, envPtr); /* skip over the '?' */
+	if (result != TCL_OK) {
+	    goto done;
+	}
+
+	/*
+	 * Emit the jump around the "then" clause to the "else" condExpr if
+	 * the test was false. We emit a one byte (relative) jump here, and
+	 * replace it later with a four byte jump if the jump target is more
+	 * than 127 bytes away.
+	 */
+
+	TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpAroundThenFixup);
+
+	/*
+	 * Compile the "then" expression. Note that if a subexpression
+	 * is only a primary, we need to try to convert it to numeric.
+	 * This is done in order to support Tcl's policy of interpreting
+	 * operands if at all possible as first integers, else
+	 * floating-point numbers.
+	 */
+
+	infoPtr->hasOperators = 0;
+	infoPtr->exprIsJustVarRef = 0;
+	infoPtr->exprIsComparison = 0;
+	result = CompileCondExpr(interp, infoPtr, flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
+	if (infoPtr->token != COLON) {
+	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		    "syntax error in expression \"", infoPtr->originalExpr,
+		    "\"", (char *) NULL);
+	    result = TCL_ERROR;
+	    goto done;
+	}
+	if (!infoPtr->hasOperators) {
+	    TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
+	}
+	result = GetToken(interp, infoPtr, envPtr); /* skip over the ':' */
+	if (result != TCL_OK) {
+	    goto done;
+	}
+
+	/*
+	 * Emit an unconditional jump around the "else" condExpr.
+	 */
+
+	TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP,
+	        &jumpAroundElseFixup);
+
+	/*
+	 * Compile the "else" expression.
+	 */
+
+	infoPtr->hasOperators = 0;
+	elseCodeOffset = TclCurrCodeOffset();
+	result = CompileCondExpr(interp, infoPtr, flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
+	if (!infoPtr->hasOperators) {
+	    TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
+	}
+
+	/*
+	 * Fix up the second jump: the unconditional jump around the "else"
+	 * expression. If the distance is too great (> 127 bytes), replace
+	 * it with a four byte instruction and move the instructions after
+	 * the jump down.
+	 */
+
+	currCodeOffset = TclCurrCodeOffset();
+	jumpDist = (currCodeOffset - jumpAroundElseFixup.codeOffset);
+	if (TclFixupForwardJump(envPtr, &jumpAroundElseFixup, jumpDist, 127)) {
+	    /*
+	     * Update the else expression's starting code offset since it
+	     * moved down 3 bytes too.
+	     */
+	    
+	    elseCodeOffset += 3;
+	}
+	
+	/*
+	 * Now fix up the first branch: the jumpFalse after the test. If the
+	 * distance is too great, replace it with a four byte instruction
+	 * and update the code offsets for the commands in both the "then"
+	 * and "else" expressions.
+	 */
+
+	jumpDist = (elseCodeOffset - jumpAroundThenFixup.codeOffset);
+	TclFixupForwardJump(envPtr, &jumpAroundThenFixup, jumpDist, 127);
+
+	infoPtr->hasOperators = 1;
+
+	/*
+	 * A comparison is not the top-level operator in this expression.
+	 */
+
+	infoPtr->exprIsComparison = 0;
+    }
+
+    done:
+    envPtr->maxStackDepth = maxDepth;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileLorExpr --
+ *
+ *	This procedure compiles a Tcl logical or expression:
+ *	lorExpr ::= landExpr {'||' landExpr}
+ *
+ * Results:
+ *	The return value is TCL_OK on a successful compilation and TCL_ERROR
+ *	on failure. If TCL_ERROR is returned, then the interpreter's result
+ *	contains an error message.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the expression.
+ *
+ * Side effects:
+ *	Adds instructions to envPtr to evaluate the expression at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileLorExpr(interp, infoPtr, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    ExprInfo *infoPtr;		/* Describes the compilation state for the
+				 * expression being compiled. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    int maxDepth;		/* Maximum number of stack elements needed
+				 * to execute the expression. */
+    JumpFixupArray jumpFixupArray;
+				/* Used to fix up the forward "short
+				 * circuit" jump after each or-ed
+				 * subexpression to just after the last
+				 * subexpression. */
+    JumpFixup jumpTrueFixup, jumpFixup;
+    				/* Used to emit the jumps in the code to
+				 * convert the first operand to a 0 or 1. */
+    int fixupIndex, jumpDist, currCodeOffset, objIndex, j, result;
+    Tcl_Obj *objPtr;
+    
+    HERE("lorExpr", 2);
+    result = CompileLandExpr(interp, infoPtr, flags, envPtr);
+    if ((result != TCL_OK) || (infoPtr->token != OR)) {
+	return result;		/* envPtr->maxStackDepth is already set */
+    }
+
+    infoPtr->hasOperators = 1;
+    infoPtr->exprIsJustVarRef = 0;
+    maxDepth = envPtr->maxStackDepth;
+    TclInitJumpFixupArray(&jumpFixupArray);
+    while (infoPtr->token == OR) {
+	result = GetToken(interp, infoPtr, envPtr); /* skip over the '||' */
+	if (result != TCL_OK) {
+	    goto done;
+	}
+
+	if (jumpFixupArray.next == 0) {
+	    /*
+	     * Just the first "lor" operand is on the stack. The following
+	     * is slightly ugly: we need to convert that first "lor" operand
+	     * to a "0" or "1" to get the correct result if it is nonzero.
+	     * Eventually we'll use a new instruction for this.
+	     */
+
+	    TclEmitForwardJump(envPtr, TCL_TRUE_JUMP, &jumpTrueFixup);
+	    
+	    objIndex = TclObjIndexForString("0", 1, /*allocStrRep*/ 0,
+					    /*inHeap*/ 0, envPtr);
+	    objPtr = envPtr->objArrayPtr[objIndex];
+
+	    Tcl_InvalidateStringRep(objPtr);
+	    objPtr->internalRep.longValue = 0;
+	    objPtr->typePtr = &tclIntType;
+	    
+	    TclEmitPush(objIndex, envPtr);
+	    TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup);
+
+	    jumpDist = (TclCurrCodeOffset() - jumpTrueFixup.codeOffset);
+	    if (TclFixupForwardJump(envPtr, &jumpTrueFixup, jumpDist, 127)) {
+		panic("CompileLorExpr: bad jump distance %d\n", jumpDist);
+	    }
+	    objIndex = TclObjIndexForString("1", 1, /*allocStrRep*/ 0,
+				            /*inHeap*/ 0, envPtr);
+	    objPtr = envPtr->objArrayPtr[objIndex];
+
+	    Tcl_InvalidateStringRep(objPtr);
+	    objPtr->internalRep.longValue = 1;
+	    objPtr->typePtr = &tclIntType;
+	    
+	    TclEmitPush(objIndex, envPtr);
+
+	    jumpDist = (TclCurrCodeOffset() - jumpFixup.codeOffset);
+	    if (TclFixupForwardJump(envPtr, &jumpFixup, jumpDist, 127)) {
+		panic("CompileLorExpr: bad jump distance %d\n", jumpDist);
+	    }
+	}
+
+	/*
+	 * Duplicate the value on top of the stack to prevent the jump from
+	 * consuming it.
+	 */
+
+	TclEmitOpcode(INST_DUP, envPtr);
+
+	/*
+	 * Emit the "short circuit" jump around the rest of the lorExp if
+	 * the previous expression was true. We emit a one byte (relative)
+	 * jump here, and replace it later with a four byte jump if the jump
+	 * target is more than 127 bytes away.
+	 */
+
+	if (jumpFixupArray.next == jumpFixupArray.end) {
+	    TclExpandJumpFixupArray(&jumpFixupArray);
+	}
+	fixupIndex = jumpFixupArray.next;
+	jumpFixupArray.next++;
+	TclEmitForwardJump(envPtr, TCL_TRUE_JUMP,
+	        &(jumpFixupArray.fixup[fixupIndex]));
+	
+	/*
+	 * Compile the subexpression.
+	 */
+
+	result = CompileLandExpr(interp, infoPtr, flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth);
+
+	/*
+	 * Emit a "logical or" instruction. This does not try to "short-
+	 * circuit" the evaluation of both operands of a Tcl "||" operator,
+	 * but instead ensures that we either have a "1" or a "0" result.
+	 */
+
+	TclEmitOpcode(INST_LOR, envPtr);
+    }
+
+    /*
+     * Now that we know the target of the forward jumps, update the jumps
+     * with the correct distance. Also, if the distance is too great (> 127
+     * bytes), replace the jump with a four byte instruction and move the
+     * instructions after the jump down.
+     */
+    
+    for (j = jumpFixupArray.next;  j > 0;  j--) {
+	fixupIndex = (j - 1);	/* process closest jump first */
+	currCodeOffset = TclCurrCodeOffset();
+	jumpDist = (currCodeOffset - jumpFixupArray.fixup[fixupIndex].codeOffset);
+	TclFixupForwardJump(envPtr, &(jumpFixupArray.fixup[fixupIndex]), jumpDist, 127);
+    }
+
+    /*
+     * We get here only if one or more ||'s appear as top-level operators.
+     */
+
+    done:
+    infoPtr->exprIsComparison = 0;
+    TclFreeJumpFixupArray(&jumpFixupArray);
+    envPtr->maxStackDepth = maxDepth;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileLandExpr --
+ *
+ *	This procedure compiles a Tcl logical and expression:
+ *	landExpr ::= bitOrExpr {'&&' bitOrExpr}
+ *
+ * Results:
+ *	The return value is TCL_OK on a successful compilation and TCL_ERROR
+ *	on failure. If TCL_ERROR is returned, then the interpreter's result
+ *	contains an error message.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the expression.
+ *
+ * Side effects:
+ *	Adds instructions to envPtr to evaluate the expression at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileLandExpr(interp, infoPtr, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    ExprInfo *infoPtr;		/* Describes the compilation state for the
+				 * expression being compiled. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    int maxDepth;		/* Maximum number of stack elements needed
+				 * to execute the expression. */
+    JumpFixupArray jumpFixupArray;
+				/* Used to fix up the forward "short
+				 * circuit" jump after each and-ed
+				 * subexpression to just after the last
+				 * subexpression. */
+    JumpFixup jumpTrueFixup, jumpFixup;
+    				/* Used to emit the jumps in the code to
+				 * convert the first operand to a 0 or 1. */
+    int fixupIndex, jumpDist, currCodeOffset, objIndex, j, result;
+    Tcl_Obj *objPtr;
+
+    HERE("landExpr", 3);
+    result = CompileBitOrExpr(interp, infoPtr, flags, envPtr);
+    if ((result != TCL_OK) || (infoPtr->token != AND)) {
+	return result;		/* envPtr->maxStackDepth is already set */
+    }
+
+    infoPtr->hasOperators = 1;
+    infoPtr->exprIsJustVarRef = 0;
+    maxDepth = envPtr->maxStackDepth;
+    TclInitJumpFixupArray(&jumpFixupArray);
+    while (infoPtr->token == AND) {
+	result = GetToken(interp, infoPtr, envPtr); /* skip over the '&&' */
+	if (result != TCL_OK) {
+	    goto done;
+	}
+
+	if (jumpFixupArray.next == 0) {
+	    /*
+	     * Just the first "land" operand is on the stack. The following
+	     * is slightly ugly: we need to convert the first "land" operand
+	     * to a "0" or "1" to get the correct result if it is
+	     * nonzero. Eventually we'll use a new instruction.
+	     */
+
+	    TclEmitForwardJump(envPtr, TCL_TRUE_JUMP, &jumpTrueFixup);
+	     
+	    objIndex = TclObjIndexForString("0", 1, /*allocStrRep*/ 0,
+				            /*inHeap*/ 0, envPtr);
+	    objPtr = envPtr->objArrayPtr[objIndex];
+
+	    Tcl_InvalidateStringRep(objPtr);
+	    objPtr->internalRep.longValue = 0;
+	    objPtr->typePtr = &tclIntType;
+	    
+	    TclEmitPush(objIndex, envPtr);
+	    TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup);
+
+	    jumpDist = (TclCurrCodeOffset() - jumpTrueFixup.codeOffset);
+	    if (TclFixupForwardJump(envPtr, &jumpTrueFixup, jumpDist, 127)) {
+		panic("CompileLandExpr: bad jump distance %d\n", jumpDist);
+	    }
+	    objIndex = TclObjIndexForString("1", 1, /*allocStrRep*/ 0,
+				            /*inHeap*/ 0, envPtr);
+	    objPtr = envPtr->objArrayPtr[objIndex];
+
+	    Tcl_InvalidateStringRep(objPtr);
+	    objPtr->internalRep.longValue = 1;
+	    objPtr->typePtr = &tclIntType;
+	    
+	    TclEmitPush(objIndex, envPtr);
+
+	    jumpDist = (TclCurrCodeOffset() - jumpFixup.codeOffset);
+	    if (TclFixupForwardJump(envPtr, &jumpFixup, jumpDist, 127)) {
+		panic("CompileLandExpr: bad jump distance %d\n", jumpDist);
+	    }
+	}
+
+	/*
+	 * Duplicate the value on top of the stack to prevent the jump from
+	 * consuming it.
+	 */
+
+	TclEmitOpcode(INST_DUP, envPtr);
+
+	/*
+	 * Emit the "short circuit" jump around the rest of the landExp if
+	 * the previous expression was false. We emit a one byte (relative)
+	 * jump here, and replace it later with a four byte jump if the jump
+	 * target is more than 127 bytes away.
+	 */
+
+	if (jumpFixupArray.next == jumpFixupArray.end) {
+	    TclExpandJumpFixupArray(&jumpFixupArray);
+	}
+	fixupIndex = jumpFixupArray.next;
+	jumpFixupArray.next++;
+	TclEmitForwardJump(envPtr, TCL_FALSE_JUMP,
+		&(jumpFixupArray.fixup[fixupIndex]));
+	
+	/*
+	 * Compile the subexpression.
+	 */
+
+	result = CompileBitOrExpr(interp, infoPtr, flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth);
+
+	/*
+	 * Emit a "logical and" instruction. This does not try to "short-
+	 * circuit" the evaluation of both operands of a Tcl "&&" operator,
+	 * but instead ensures that we either have a "1" or a "0" result.
+	 */
+
+	TclEmitOpcode(INST_LAND, envPtr);
+    }
+
+    /*
+     * Now that we know the target of the forward jumps, update the jumps
+     * with the correct distance. Also, if the distance is too great (> 127
+     * bytes), replace the jump with a four byte instruction and move the
+     * instructions after the jump down.
+     */
+    
+    for (j = jumpFixupArray.next;  j > 0;  j--) {
+	fixupIndex = (j - 1);	/* process closest jump first */
+	currCodeOffset = TclCurrCodeOffset();
+	jumpDist = (currCodeOffset - jumpFixupArray.fixup[fixupIndex].codeOffset);
+	TclFixupForwardJump(envPtr, &(jumpFixupArray.fixup[fixupIndex]),
+	        jumpDist, 127);
+    }
+
+    /*
+     * We get here only if one or more &&'s appear as top-level operators.
+     */
+
+    done:
+    infoPtr->exprIsComparison = 0;
+    TclFreeJumpFixupArray(&jumpFixupArray);
+    envPtr->maxStackDepth = maxDepth;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileBitOrExpr --
+ *
+ *	This procedure compiles a Tcl bitwise or expression:
+ *	bitOrExpr ::= bitXorExpr {'|' bitXorExpr}
+ *
+ * Results:
+ *	The return value is TCL_OK on a successful compilation and TCL_ERROR
+ *	on failure. If TCL_ERROR is returned, then the interpreter's result
+ *	contains an error message.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the expression.
+ *
+ * Side effects:
+ *	Adds instructions to envPtr to evaluate the expression at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileBitOrExpr(interp, infoPtr, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    ExprInfo *infoPtr;		/* Describes the compilation state for the
+				 * expression being compiled. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute the expression. */
+    int result;
+
+    HERE("bitOrExpr", 4);
+    result = CompileBitXorExpr(interp, infoPtr, flags, envPtr);
+    if (result != TCL_OK) {
+	goto done;
+    }
+    maxDepth = envPtr->maxStackDepth;
+    
+    while (infoPtr->token == BIT_OR) {
+	infoPtr->hasOperators = 1;
+	infoPtr->exprIsJustVarRef = 0;
+	result = GetToken(interp, infoPtr, envPtr); /* skip over the '|' */
+	if (result != TCL_OK) {
+	    goto done;
+	}
+
+	result = CompileBitXorExpr(interp, infoPtr, flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth);
+	
+	TclEmitOpcode(INST_BITOR, envPtr);
+
+	/*
+	 * A comparison is not the top-level operator in this expression.
+	 */
+
+	infoPtr->exprIsComparison = 0;
+    }
+
+    done:
+    envPtr->maxStackDepth = maxDepth;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileBitXorExpr --
+ *
+ *	This procedure compiles a Tcl bitwise exclusive or expression:
+ *	bitXorExpr ::= bitAndExpr {'^' bitAndExpr}
+ *
+ * Results:
+ *	The return value is TCL_OK on a successful compilation and TCL_ERROR
+ *	on failure. If TCL_ERROR is returned, then the interpreter's result
+ *	contains an error message.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the expression.
+ *
+ * Side effects:
+ *	Adds instructions to envPtr to evaluate the expression at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileBitXorExpr(interp, infoPtr, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    ExprInfo *infoPtr;		/* Describes the compilation state for the
+				 * expression being compiled. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute the expression. */
+    int result;
+
+    HERE("bitXorExpr", 5);
+    result = CompileBitAndExpr(interp, infoPtr, flags, envPtr);
+    if (result != TCL_OK) {
+	goto done;
+    }
+    maxDepth = envPtr->maxStackDepth;
+    
+    while (infoPtr->token == BIT_XOR) {
+	infoPtr->hasOperators = 1;
+	infoPtr->exprIsJustVarRef = 0;
+	result = GetToken(interp, infoPtr, envPtr); /* skip over the '^' */
+	if (result != TCL_OK) {
+	    goto done;
+	}
+
+	result = CompileBitAndExpr(interp, infoPtr, flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth);
+	
+	TclEmitOpcode(INST_BITXOR, envPtr);
+
+	/*
+	 * A comparison is not the top-level operator in this expression.
+	 */
+
+	infoPtr->exprIsComparison = 0;
+    }
+
+    done:
+    envPtr->maxStackDepth = maxDepth;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileBitAndExpr --
+ *
+ *	This procedure compiles a Tcl bitwise and expression:
+ *	bitAndExpr ::= equalityExpr {'&' equalityExpr}
+ *
+ * Results:
+ *	The return value is TCL_OK on a successful compilation and TCL_ERROR
+ *	on failure. If TCL_ERROR is returned, then the interpreter's result
+ *	contains an error message.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the expression.
+ *
+ * Side effects:
+ *	Adds instructions to envPtr to evaluate the expression at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileBitAndExpr(interp, infoPtr, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    ExprInfo *infoPtr;		/* Describes the compilation state for the
+				 * expression being compiled. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute the expression. */
+    int result;
+
+    HERE("bitAndExpr", 6);
+    result = CompileEqualityExpr(interp, infoPtr, flags, envPtr);
+    if (result != TCL_OK) {
+	goto done;
+    }
+    maxDepth = envPtr->maxStackDepth;
+    
+    while (infoPtr->token == BIT_AND) {
+	infoPtr->hasOperators = 1;
+	infoPtr->exprIsJustVarRef = 0;
+	result = GetToken(interp, infoPtr, envPtr); /* skip over the '&' */
+	if (result != TCL_OK) {
+	    goto done;
+	}
+
+	result = CompileEqualityExpr(interp, infoPtr, flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth);
+	
+	TclEmitOpcode(INST_BITAND, envPtr);
+
+	/*
+	 * A comparison is not the top-level operator in this expression.
+	 */
+
+	infoPtr->exprIsComparison = 0;
+    }
+
+    done:
+    envPtr->maxStackDepth = maxDepth;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileEqualityExpr --
+ *
+ *	This procedure compiles a Tcl equality (inequality) expression:
+ *	equalityExpr ::= relationalExpr {('==' | '!=') relationalExpr}
+ *
+ * Results:
+ *	The return value is TCL_OK on a successful compilation and TCL_ERROR
+ *	on failure. If TCL_ERROR is returned, then the interpreter's result
+ *	contains an error message.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the expression.
+ *
+ * Side effects:
+ *	Adds instructions to envPtr to evaluate the expression at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileEqualityExpr(interp, infoPtr, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    ExprInfo *infoPtr;		/* Describes the compilation state for the
+				 * expression being compiled. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute the expression. */
+    int op, result;
+
+    HERE("equalityExpr", 7);
+    result = CompileRelationalExpr(interp, infoPtr, flags, envPtr);
+    if (result != TCL_OK) {
+	goto done;
+    }
+    maxDepth = envPtr->maxStackDepth;
+
+    op = infoPtr->token;
+    while ((op == EQUAL) || (op == NEQ)) {
+	infoPtr->hasOperators = 1;
+	infoPtr->exprIsJustVarRef = 0;
+	result = GetToken(interp, infoPtr, envPtr); /* skip over == or != */
+	if (result != TCL_OK) {
+	    goto done;
+	}
+
+	result = CompileRelationalExpr(interp, infoPtr, flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth);
+
+	if (op == EQUAL) {
+	    TclEmitOpcode(INST_EQ, envPtr);
+	} else {
+	    TclEmitOpcode(INST_NEQ, envPtr);
+	}
+	
+	op = infoPtr->token;
+
+	/*
+	 * A comparison _is_ the top-level operator in this expression.
+	 */
+	
+	infoPtr->exprIsComparison = 1;
+    }
+
+    done:
+    envPtr->maxStackDepth = maxDepth;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileRelationalExpr --
+ *
+ *	This procedure compiles a Tcl relational expression:
+ *	relationalExpr ::= shiftExpr {('<' | '>' | '<=' | '>=') shiftExpr}
+ *
+ * Results:
+ *	The return value is TCL_OK on a successful compilation and TCL_ERROR
+ *	on failure. If TCL_ERROR is returned, then the interpreter's result
+ *	contains an error message.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the expression.
+ *
+ * Side effects:
+ *	Adds instructions to envPtr to evaluate the expression at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileRelationalExpr(interp, infoPtr, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    ExprInfo *infoPtr;		/* Describes the compilation state for the
+				 * expression being compiled. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute the expression. */
+    int op, result;
+
+    HERE("relationalExpr", 8);
+    result = CompileShiftExpr(interp, infoPtr, flags, envPtr);
+    if (result != TCL_OK) {
+	goto done;
+    }
+    maxDepth = envPtr->maxStackDepth;
+
+    op = infoPtr->token;
+    while ((op == LESS) || (op == GREATER) || (op == LEQ) || (op == GEQ)) {
+	infoPtr->hasOperators = 1;
+	infoPtr->exprIsJustVarRef = 0;
+	result = GetToken(interp, infoPtr, envPtr); /* skip over the op */
+	if (result != TCL_OK) {
+	    goto done;
+	}
+
+	result = CompileShiftExpr(interp, infoPtr, flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth);
+
+	switch (op) {
+	case LESS:
+	    TclEmitOpcode(INST_LT, envPtr);
+	    break;
+	case GREATER:
+	    TclEmitOpcode(INST_GT, envPtr);
+	    break;
+	case LEQ:
+	    TclEmitOpcode(INST_LE, envPtr);
+	    break;
+	case GEQ:
+	    TclEmitOpcode(INST_GE, envPtr);
+	    break;
+	}
+
+	op = infoPtr->token;
+
+	/*
+	 * A comparison _is_ the top-level operator in this expression.
+	 */
+	
+	infoPtr->exprIsComparison = 1;
+    }
+
+    done:
+    envPtr->maxStackDepth = maxDepth;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileShiftExpr --
+ *
+ *	This procedure compiles a Tcl shift expression:
+ *	shiftExpr ::= addExpr {('<<' | '>>') addExpr}
+ *
+ * Results:
+ *	The return value is TCL_OK on a successful compilation and TCL_ERROR
+ *	on failure. If TCL_ERROR is returned, then the interpreter's result
+ *	contains an error message.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the expression.
+ *
+ * Side effects:
+ *	Adds instructions to envPtr to evaluate the expression at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileShiftExpr(interp, infoPtr, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    ExprInfo *infoPtr;		/* Describes the compilation state for the
+				 * expression being compiled. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute the expression. */
+    int op, result;
+
+    HERE("shiftExpr", 9);
+    result = CompileAddExpr(interp, infoPtr, flags, envPtr);
+    if (result != TCL_OK) {
+	goto done;
+    }
+    maxDepth = envPtr->maxStackDepth;
+
+    op = infoPtr->token;
+    while ((op == LEFT_SHIFT) || (op == RIGHT_SHIFT)) {
+	infoPtr->hasOperators = 1;
+	infoPtr->exprIsJustVarRef = 0;
+	result = GetToken(interp, infoPtr, envPtr); /* skip over << or >> */
+	if (result != TCL_OK) {
+	    goto done;
+	}
+
+	result = CompileAddExpr(interp, infoPtr, flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth);
+
+	if (op == LEFT_SHIFT) {
+	    TclEmitOpcode(INST_LSHIFT, envPtr);
+	} else {
+	    TclEmitOpcode(INST_RSHIFT, envPtr);
+	}
+
+	op = infoPtr->token;
+
+	/*
+	 * A comparison is not the top-level operator in this expression.
+	 */
+
+	infoPtr->exprIsComparison = 0;
+    }
+
+    done:
+    envPtr->maxStackDepth = maxDepth;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileAddExpr --
+ *
+ *	This procedure compiles a Tcl addition expression:
+ *	addExpr ::= multiplyExpr {('+' | '-') multiplyExpr}
+ *
+ * Results:
+ *	The return value is TCL_OK on a successful compilation and TCL_ERROR
+ *	on failure. If TCL_ERROR is returned, then the interpreter's result
+ *	contains an error message.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the expression.
+ *
+ * Side effects:
+ *	Adds instructions to envPtr to evaluate the expression at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileAddExpr(interp, infoPtr, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    ExprInfo *infoPtr;		/* Describes the compilation state for the
+				 * expression being compiled. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute the expression. */
+    int op, result;
+
+    HERE("addExpr", 10);
+    result = CompileMultiplyExpr(interp, infoPtr, flags, envPtr);
+    if (result != TCL_OK) {
+	goto done;
+    }
+    maxDepth = envPtr->maxStackDepth;
+
+    op = infoPtr->token;
+    while ((op == PLUS) || (op == MINUS)) {
+	infoPtr->hasOperators = 1;
+	infoPtr->exprIsJustVarRef = 0;
+	result = GetToken(interp, infoPtr, envPtr); /* skip over + or - */
+	if (result != TCL_OK) {
+	    goto done;
+	}
+
+	result = CompileMultiplyExpr(interp, infoPtr, flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth);
+
+	if (op == PLUS) {
+	    TclEmitOpcode(INST_ADD, envPtr);
+	} else {
+	    TclEmitOpcode(INST_SUB, envPtr);
+	}
+
+	op = infoPtr->token;
+
+	/*
+	 * A comparison is not the top-level operator in this expression.
+	 */
+
+	infoPtr->exprIsComparison = 0;
+    }
+
+    done:
+    envPtr->maxStackDepth = maxDepth;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileMultiplyExpr --
+ *
+ *	This procedure compiles a Tcl multiply expression:
+ *	multiplyExpr ::= unaryExpr {('*' | '/' | '%') unaryExpr}
+ *
+ * Results:
+ *	The return value is TCL_OK on a successful compilation and TCL_ERROR
+ *	on failure. If TCL_ERROR is returned, then the interpreter's result
+ *	contains an error message.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the expression.
+ *
+ * Side effects:
+ *	Adds instructions to envPtr to evaluate the expression at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileMultiplyExpr(interp, infoPtr, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    ExprInfo *infoPtr;		/* Describes the compilation state for the
+				 * expression being compiled. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute the expression. */
+    int op, result;
+
+    HERE("multiplyExpr", 11);
+    result = CompileUnaryExpr(interp, infoPtr, flags, envPtr);
+    if (result != TCL_OK) {
+	goto done;
+    }
+    maxDepth = envPtr->maxStackDepth;
+
+    op = infoPtr->token;
+    while ((op == MULT) || (op == DIVIDE) || (op == MOD)) {
+	infoPtr->hasOperators = 1;
+	infoPtr->exprIsJustVarRef = 0;
+	result = GetToken(interp, infoPtr, envPtr); /* skip over * or / */
+	if (result != TCL_OK) {
+	    goto done;
+	}
+
+	result = CompileUnaryExpr(interp, infoPtr, flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth);
+
+	if (op == MULT) {
+	    TclEmitOpcode(INST_MULT, envPtr);
+	} else if (op == DIVIDE) {
+	    TclEmitOpcode(INST_DIV, envPtr);
+	} else {
+	    TclEmitOpcode(INST_MOD, envPtr);
+	}
+
+	op = infoPtr->token;
+
+	/*
+	 * A comparison is not the top-level operator in this expression.
+	 */
+
+	infoPtr->exprIsComparison = 0;
+    }
+
+    done:
+    envPtr->maxStackDepth = maxDepth;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileUnaryExpr --
+ *
+ *	This procedure compiles a Tcl unary expression:
+ *	unaryExpr ::= ('+' | '-' | '~' | '!') unaryExpr | primaryExpr
+ *
+ * Results:
+ *	The return value is TCL_OK on a successful compilation and TCL_ERROR
+ *	on failure. If TCL_ERROR is returned, then the interpreter's result
+ *	contains an error message.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the expression.
+ *
+ * Side effects:
+ *	Adds instructions to envPtr to evaluate the expression at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileUnaryExpr(interp, infoPtr, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    ExprInfo *infoPtr;		/* Describes the compilation state for the
+				 * expression being compiled. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute the expression. */
+    int op, result;
+
+    HERE("unaryExpr", 12);
+    op = infoPtr->token;
+    if ((op == PLUS) || (op == MINUS) || (op == BIT_NOT) || (op == NOT)) {
+	infoPtr->hasOperators = 1;
+	infoPtr->exprIsJustVarRef = 0;
+	result = GetToken(interp, infoPtr, envPtr); /* skip over the op */
+	if (result != TCL_OK) {
+	    goto done;
+	}
+
+	result = CompileUnaryExpr(interp, infoPtr, flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = envPtr->maxStackDepth;
+
+	switch (op) {
+	case PLUS:
+	    TclEmitOpcode(INST_UPLUS, envPtr);
+	    break;
+	case MINUS:
+	    TclEmitOpcode(INST_UMINUS, envPtr);
+	    break;
+	case BIT_NOT:
+	    TclEmitOpcode(INST_BITNOT, envPtr);
+	    break;
+	case NOT:
+	    TclEmitOpcode(INST_LNOT, envPtr);
+	    break;
+	}
+
+	/*
+	 * A comparison is not the top-level operator in this expression.
+	 */
+
+	infoPtr->exprIsComparison = 0;
+    } else {			/* must be a primaryExpr */
+	result = CompilePrimaryExpr(interp, infoPtr, flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = envPtr->maxStackDepth;
+    }
+
+    done:
+    envPtr->maxStackDepth = maxDepth;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompilePrimaryExpr --
+ *
+ *	This procedure compiles a Tcl primary expression:
+ *	primaryExpr ::= literal | varReference | quotedString |
+ *			'[' command ']' | mathFuncCall | '(' condExpr ')'
+ *
+ * Results:
+ *	The return value is TCL_OK on a successful compilation and TCL_ERROR
+ *	on failure. If TCL_ERROR is returned, then the interpreter's result
+ *	contains an error message.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the expression.
+ *
+ * Side effects:
+ *	Adds instructions to envPtr to evaluate the expression at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompilePrimaryExpr(interp, infoPtr, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    ExprInfo *infoPtr;		/* Describes the compilation state for the
+				 * expression being compiled. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute the expression. */
+    int theToken;
+    char *dollarPtr, *quotePtr, *cmdPtr, *termPtr;
+    int result = TCL_OK;
+
+    /*
+     * We emit tryCvtToNumeric instructions after most of these primary
+     * expressions in order to support Tcl's policy of interpreting operands
+     * as first integers if possible, otherwise floating-point numbers if
+     * possible.
+     */
+
+    HERE("primaryExpr", 13);
+    theToken = infoPtr->token;
+
+    if ((theToken != DOLLAR) && (theToken != OPEN_PAREN)) {
+	infoPtr->exprIsJustVarRef = 0;
+    }
+    switch (theToken) {
+    case LITERAL:		/* int, double, or string in braces */
+	TclEmitPush(infoPtr->objIndex, envPtr);
+	maxDepth = 1;
+	break;
+	
+    case DOLLAR:		/* $var variable reference */
+	dollarPtr = (infoPtr->next - 1);
+	envPtr->pushSimpleWords = 1;
+	result = TclCompileDollarVar(interp, dollarPtr,
+		infoPtr->lastChar, flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = envPtr->maxStackDepth;
+	infoPtr->next = (dollarPtr + envPtr->termOffset);
+	break;
+	
+    case QUOTE:			/* quotedString */
+	quotePtr = infoPtr->next;
+	envPtr->pushSimpleWords = 1;
+	result = TclCompileQuotes(interp, quotePtr,
+		infoPtr->lastChar, '"', flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = envPtr->maxStackDepth;
+	infoPtr->next = (quotePtr + envPtr->termOffset);
+	break;
+	
+    case OPEN_BRACKET:		/* '[' command ']' */
+	cmdPtr = infoPtr->next;
+	envPtr->pushSimpleWords = 1;
+	result = TclCompileString(interp, cmdPtr,
+		infoPtr->lastChar, (flags | TCL_BRACKET_TERM), envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	termPtr = (cmdPtr + envPtr->termOffset);
+	if (*termPtr == ']') {
+	    infoPtr->next = (termPtr + 1); /* advance over the ']'. */
+	} else if (termPtr == infoPtr->lastChar) {
+	    /*
+	     * Missing ] at end of nested command.
+	     */
+	    
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	            "missing close-bracket", -1);
+	    result = TCL_ERROR;
+	    goto done;
+	} else {
+	    panic("CompilePrimaryExpr: unexpected termination char '%c' for nested command\n", *termPtr);
+	}
+	maxDepth = envPtr->maxStackDepth;
+	break;
+	
+    case FUNC_NAME:
+	result = CompileMathFuncCall(interp, infoPtr, flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = envPtr->maxStackDepth;
+	break;
+	
+    case OPEN_PAREN:
+	result = GetToken(interp, infoPtr, envPtr); /* skip over the '(' */
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	infoPtr->exprIsComparison = 0;
+	result = CompileCondExpr(interp, infoPtr, flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = envPtr->maxStackDepth;
+	if (infoPtr->token != CLOSE_PAREN) {
+	    goto syntaxError;
+	}
+	break;
+	
+    default:
+	goto syntaxError;
+    }
+
+    if (theToken != FUNC_NAME) {
+	/*
+	 * Advance to the next token before returning.
+	 */
+	
+	result = GetToken(interp, infoPtr, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+    }
+
+    done:
+    envPtr->maxStackDepth = maxDepth;
+    return result;
+
+    syntaxError:
+    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+	    "syntax error in expression \"", infoPtr->originalExpr,
+	    "\"", (char *) NULL);
+    return TCL_ERROR;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileMathFuncCall --
+ *
+ *	This procedure compiles a call on a math function in an expression:
+ *	mathFuncCall ::= funcName '(' [condExpr {',' condExpr}] ')'
+ *
+ * Results:
+ *	The return value is TCL_OK on a successful compilation and TCL_ERROR
+ *	on failure. If TCL_ERROR is returned, then the interpreter's result
+ *	contains an error message.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the function.
+ *
+ * Side effects:
+ *	Adds instructions to envPtr to evaluate the math function at
+ *	runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileMathFuncCall(interp, infoPtr, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    ExprInfo *infoPtr;		/* Describes the compilation state for the
+				 * expression being compiled. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    Interp *iPtr = (Interp *) interp;
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute the expression. */
+    MathFunc *mathFuncPtr;	/* Info about math function. */
+    int objIndex;		/* The object array index for an object
+				 * holding the function name if it is not
+				 * builtin. */
+    Tcl_HashEntry *hPtr;
+    char *p, *funcName;
+    char savedChar;
+    int result, i;
+
+    /*
+     * infoPtr->funcName points to the first character of the math
+     * function's name. Look for the end of its name and look up the
+     * MathFunc record for the function.
+     */
+
+    funcName = p = infoPtr->funcName;
+    while (isalnum(UCHAR(*p)) || (*p == '_')) {
+	p++;
+    }
+    infoPtr->next = p;
+    
+    result = GetToken(interp, infoPtr, envPtr); /* skip over func name */
+    if (result != TCL_OK) {
+	goto done;
+    }
+    if (infoPtr->token != OPEN_PAREN) {
+	goto syntaxError;
+    }
+    result = GetToken(interp, infoPtr, envPtr); /* skip over '(' */
+    if (result != TCL_OK) {
+	goto done;
+    }
+    
+    savedChar = *p;
+    *p = 0;
+    hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcName);
+    if (hPtr == NULL) {
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		"unknown math function \"", funcName, "\"", (char *) NULL);
+	result = TCL_ERROR;
+	*p = savedChar;
+	goto done;
+    }
+    mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
+
+    /*
+     * If not a builtin function, push an object with the function's name.
+     */
+
+    if (mathFuncPtr->builtinFuncIndex < 0) {   /* not builtin */
+	objIndex = TclObjIndexForString(funcName, -1, /*allocStrRep*/ 1,
+				        /*inHeap*/ 0, envPtr);
+	TclEmitPush(objIndex, envPtr);
+	maxDepth = 1;
+    }
+
+    /*
+     * Restore the saved character after the function name.
+     */
+
+    *p = savedChar;
+
+    /*
+     * Compile the arguments for the function, if there are any.
+     */
+
+    if (mathFuncPtr->numArgs > 0) {
+	for (i = 0;  ;  i++) {
+	    infoPtr->exprIsComparison = 0;
+	    result = CompileCondExpr(interp, infoPtr, flags, envPtr);
+	    if (result != TCL_OK) {
+		goto done;
+	    }
+    
+	    /*
+	     * Check for a ',' between arguments or a ')' ending the
+	     * argument list.
+	     */
+    
+	    if (i == (mathFuncPtr->numArgs-1)) {
+		if (infoPtr->token == CLOSE_PAREN) {
+		    break;	/* exit the argument parsing loop */
+		} else if (infoPtr->token == COMMA) {
+		    Tcl_ResetResult(interp);
+		    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		            "too many arguments for math function", -1);
+		    result = TCL_ERROR;
+		    goto done;
+		} else {
+		    goto syntaxError;
+		}
+	    }
+	    if (infoPtr->token != COMMA) {
+		if (infoPtr->token == CLOSE_PAREN) {
+		    Tcl_ResetResult(interp);
+		    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		            "too few arguments for math function", -1);
+		    result = TCL_ERROR;
+		    goto done;
+		} else {
+		    goto syntaxError;
+		}
+	    }
+	    result = GetToken(interp, infoPtr, envPtr); /* skip over , */
+	    if (result != TCL_OK) {
+		goto done;
+	    }
+	    maxDepth++;
+	}
+    }
+
+    if (infoPtr->token != CLOSE_PAREN) {
+	goto syntaxError;
+    }
+    result = GetToken(interp, infoPtr, envPtr); /* skip over ')' */
+    if (result != TCL_OK) {
+	goto done;
+    }
+    
+    /*
+     * Compile the call on the math function. Note that the "objc" argument
+     * count for non-builtin functions is incremented by 1 to include the
+     * the function name itself.
+     */
+
+    if (mathFuncPtr->builtinFuncIndex >= 0) { /* a builtin function */
+	TclEmitInstUInt1(INST_CALL_BUILTIN_FUNC1,
+			mathFuncPtr->builtinFuncIndex, envPtr);
+    } else {
+	TclEmitInstUInt1(INST_CALL_FUNC1, (mathFuncPtr->numArgs+1), envPtr);
+    }
+
+    /*
+     * A comparison is not the top-level operator in this expression.
+     */
+
+    done:
+    infoPtr->exprIsComparison = 0;
+    envPtr->maxStackDepth = maxDepth;
+    return result;
+
+    syntaxError:
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		"syntax error in expression \"", infoPtr->originalExpr,
+		"\"", (char *) NULL);
+    return TCL_ERROR;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetToken --
+ *
+ *	Lexical scanner used to compile expressions: parses a single 
+ *	operator or other syntactic element from an expression string.
+ *
+ * Results:
+ *	TCL_OK is returned unless an error occurred. In that case a standard
+ *	Tcl error is returned, using the interpreter's result to hold an
+ *	error message. TCL_ERROR is returned if an integer overflow, or a
+ *	floating-point overflow or underflow occurred while reading in a
+ *	number. If the lexical analysis is successful, infoPtr->token refers
+ *	to the next symbol in the expression string, and infoPtr->next is
+ *	advanced past the token. Also, if the token is a integer, double, or
+ *	string literal, then infoPtr->objIndex the index of an object
+ *	holding the value in the code's object table; otherwise is NULL.
+ *
+ * Side effects:
+ *	Object are added to envPtr to hold the values of scanned literal
+ *	integers, doubles, or strings.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetToken(interp, infoPtr, envPtr)
+    Tcl_Interp *interp;			/* Interpreter to use for error
+					 * reporting. */
+    register ExprInfo *infoPtr;         /* Describes the state of the
+					 * compiling the expression,
+					 * including the resulting token. */
+    CompileEnv *envPtr;			/* Holds objects that store literal
+					 * values that are scanned. */
+{
+    register char *src;		/* Points to current source char. */
+    register char c;		/* The current char. */
+    register int type;		/* Current char's CHAR_TYPE type. */
+    char *termPtr;		/* Points to char terminating a literal. */
+    char savedChar;		/* Holds the character termporarily replaced
+				 * by a null character during processing of
+				 * literal tokens. */
+    int objIndex;		/* The object array index for an object
+				 * holding a scanned literal. */
+    long longValue;		/* Value of a scanned integer literal. */
+    double doubleValue;		/* Value of a scanned double literal. */
+    Tcl_Obj *objPtr;
+
+    /*
+     * First initialize the scanner's "result" fields to default values.
+     */
+    
+    infoPtr->token = UNKNOWN;
+    infoPtr->objIndex = -1;
+    infoPtr->funcName = NULL;
+
+    /*
+     * Scan over leading white space at the start of a token. Note that a
+     * backslash-newline is treated as a space.
+     */
+
+    src = infoPtr->next;
+    c = *src;
+    type = CHAR_TYPE(src, infoPtr->lastChar);
+    while ((type & (TCL_SPACE | TCL_BACKSLASH)) || (c == '\n')) {
+	if (type == TCL_BACKSLASH) {
+	    if (src[1] == '\n') {
+		src += 2;
+	    } else {
+		break;	/* no longer white space */
+	    }
+	} else {
+	    src++;
+	}
+	c = *src;
+	type = CHAR_TYPE(src, infoPtr->lastChar);
+    }
+    if (src == infoPtr->lastChar) {
+	infoPtr->token = END;
+	infoPtr->next = src;
+	return TCL_OK;
+    }
+
+    /*
+     * Try to parse the token first as an integer or floating-point
+     * number. Don't check for a number if the first character is "+" or
+     * "-". If we did, we might treat a binary operator as unary by mistake,
+     * which would eventually cause a syntax error.
+     */
+
+    if ((*src != '+') && (*src != '-')) {
+	int startsWithDigit = isdigit(UCHAR(*src));
+	
+	if (startsWithDigit && TclLooksLikeInt(src)) {
+	    errno = 0;
+	    longValue = strtoul(src, &termPtr, 0);
+	    if (errno == ERANGE) {
+		char *s = "integer value too large to represent";
+		
+		Tcl_ResetResult(interp);
+		Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
+		Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s,
+			(char *) NULL);
+		return TCL_ERROR;
+	    }
+	    if (termPtr != src) {
+		/*
+		 * src was the start of a valid integer. Find/create an
+		 * object in envPtr's object array to contain the integer.
+		 */
+	    
+		savedChar = *termPtr;
+		*termPtr = '\0';
+		objIndex = TclObjIndexForString(src, termPtr - src,
+		        /*allocStrRep*/ 0, /*inHeap*/ 0, envPtr);
+		*termPtr = savedChar;  /* restore the saved char */
+		
+		objPtr = envPtr->objArrayPtr[objIndex];
+		Tcl_InvalidateStringRep(objPtr);
+		objPtr->internalRep.longValue = longValue;
+		objPtr->typePtr = &tclIntType;
+		
+		infoPtr->token = LITERAL;
+		infoPtr->objIndex = objIndex;
+		infoPtr->next = termPtr;
+		return TCL_OK;
+	    }
+	} else if (startsWithDigit || (*src == '.')
+	        || (*src == 'n') || (*src == 'N')) {
+	    errno = 0;
+	    doubleValue = strtod(src, &termPtr);
+	    if (termPtr != src) {
+		if (errno != 0) {
+		    TclExprFloatError(interp, doubleValue);
+		    return TCL_ERROR;
+		}
+
+		/*
+		 * Find/create an object in the object array containing the
+		 * double.
+		 */
+		
+		savedChar = *termPtr;
+		*termPtr = '\0';
+		objIndex = TclObjIndexForString(src, termPtr - src,
+			/*allocStrRep*/ 1, /*inHeap*/ 0, envPtr);
+		*termPtr = savedChar;  /* restore the saved char */
+		
+		objPtr = envPtr->objArrayPtr[objIndex];
+		objPtr->internalRep.doubleValue = doubleValue;
+		objPtr->typePtr = &tclDoubleType;
+		
+		infoPtr->token = LITERAL;
+		infoPtr->objIndex = objIndex;
+		infoPtr->next = termPtr;
+		return TCL_OK;
+	    }
+	}
+    }
+
+    /*
+     * Not an integer or double literal. Check next for a string literal
+     * in braces.
+     */
+
+    if (*src == '{') {
+	int level = 0;		 /* The {} nesting level. */
+	int hasBackslashNL = 0;  /* Nonzero if '\newline' was found. */
+	char *string = src;	 /* Set below to point just after the
+				  * starting '{'. */
+	char *last;		 /* Points just before terminating '}'. */
+	int numChars;		 /* Number of chars in braced string. */
+	char savedChar;		 /* Holds the character from string
+				  * termporarily replaced by a null char
+				  * during braced string processing. */
+	int numRead;
+
+	/*
+	 * Check first for any backslash-newlines, since we must treat
+	 * backslash-newlines specially (they must be replaced by spaces).
+	 */
+
+	while (1) {
+	    if (src == infoPtr->lastChar) {
+		Tcl_ResetResult(interp);
+		Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		        "missing close-brace", -1);
+		return TCL_ERROR;
+	    } else if (CHAR_TYPE(src, infoPtr->lastChar) == TCL_NORMAL) {
+		src++;
+		continue;
+	    }
+	    c = *src++;
+	    if (c == '{') {
+		level++;
+	    } else if (c == '}') {
+		--level;
+		if (level == 0) {
+		    last = (src - 2); /* i.e. just before terminating } */
+		    break;
+		}
+	    } else if (c == '\\') {
+		if (*src == '\n') {
+		    hasBackslashNL = 1;
+		}
+		(void) Tcl_Backslash(src-1, &numRead);
+		src += numRead - 1;
+	    }
+	}
+
+	/*
+	 * Create a string object for the braced string. This will start at
+	 * "string" and ends just after "last" (which points to the final
+	 * character before the terminating '}'). If backslash-newlines were
+	 * found, we copy characters one at a time into a heap-allocated
+	 * buffer and do backslash-newline substitutions.
+	 */
+
+	string++;
+	numChars = (last - string + 1);
+	savedChar = string[numChars];
+	string[numChars] = '\0';
+	if (hasBackslashNL && (numChars > 0)) {
+	    char *buffer = ckalloc((unsigned) numChars + 1);
+	    register char *dst = buffer;
+	    register char *p = string;
+	    while (p <= last) {
+		c = *dst++ = *p++;
+		if (c == '\\') {
+		    if (*p == '\n') {
+			dst[-1] = Tcl_Backslash(p-1, &numRead);
+			p += numRead - 1;
+		    } else {
+			(void) Tcl_Backslash(p-1, &numRead);
+			while (numRead > 1) {
+			    *dst++ = *p++;
+			    numRead--;
+			}
+		    }
+		}
+	    }
+	    *dst = '\0';
+	    objIndex = TclObjIndexForString(buffer, dst - buffer,
+		    /*allocStrRep*/ 1, /*inHeap*/ 1, envPtr);
+	} else {
+	    objIndex = TclObjIndexForString(string, numChars,
+		    /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr);
+	}
+	string[numChars] = savedChar;   /* restore the saved char */
+
+	infoPtr->token = LITERAL;
+	infoPtr->objIndex = objIndex;
+	infoPtr->next = src;
+	return TCL_OK;
+    }
+
+    /*
+     * Not an literal value.
+     */
+
+    infoPtr->next = src+1;   /* assume a 1 char token and advance over it */
+    switch (*src) {
+	case '[':
+	    infoPtr->token = OPEN_BRACKET;
+	    return TCL_OK;
+
+	case ']':
+	    infoPtr->token = CLOSE_BRACKET;
+	    return TCL_OK;
+
+	case '(':
+	    infoPtr->token = OPEN_PAREN;
+	    return TCL_OK;
+
+	case ')':
+	    infoPtr->token = CLOSE_PAREN;
+	    return TCL_OK;
+
+	case '$':
+	    infoPtr->token = DOLLAR;
+	    return TCL_OK;
+
+	case '"':
+	    infoPtr->token = QUOTE;
+	    return TCL_OK;
+
+	case ',':
+	    infoPtr->token = COMMA;
+	    return TCL_OK;
+
+	case '*':
+	    infoPtr->token = MULT;
+	    return TCL_OK;
+
+	case '/':
+	    infoPtr->token = DIVIDE;
+	    return TCL_OK;
+
+	case '%':
+	    infoPtr->token = MOD;
+	    return TCL_OK;
+
+	case '+':
+	    infoPtr->token = PLUS;
+	    return TCL_OK;
+
+	case '-':
+	    infoPtr->token = MINUS;
+	    return TCL_OK;
+
+	case '?':
+	    infoPtr->token = QUESTY;
+	    return TCL_OK;
+
+	case ':':
+	    infoPtr->token = COLON;
+	    return TCL_OK;
+
+	case '<':
+	    switch (src[1]) {
+		case '<':
+		    infoPtr->next = src+2;
+		    infoPtr->token = LEFT_SHIFT;
+		    break;
+		case '=':
+		    infoPtr->next = src+2;
+		    infoPtr->token = LEQ;
+		    break;
+		default:
+		    infoPtr->token = LESS;
+		    break;
+	    }
+	    return TCL_OK;
+
+	case '>':
+	    switch (src[1]) {
+		case '>':
+		    infoPtr->next = src+2;
+		    infoPtr->token = RIGHT_SHIFT;
+		    break;
+		case '=':
+		    infoPtr->next = src+2;
+		    infoPtr->token = GEQ;
+		    break;
+		default:
+		    infoPtr->token = GREATER;
+		    break;
+	    }
+	    return TCL_OK;
+
+	case '=':
+	    if (src[1] == '=') {
+		infoPtr->next = src+2;
+		infoPtr->token = EQUAL;
+	    } else {
+		infoPtr->token = UNKNOWN;
+	    }
+	    return TCL_OK;
+
+	case '!':
+	    if (src[1] == '=') {
+		infoPtr->next = src+2;
+		infoPtr->token = NEQ;
+	    } else {
+		infoPtr->token = NOT;
+	    }
+	    return TCL_OK;
+
+	case '&':
+	    if (src[1] == '&') {
+		infoPtr->next = src+2;
+		infoPtr->token = AND;
+	    } else {
+		infoPtr->token = BIT_AND;
+	    }
+	    return TCL_OK;
+
+	case '^':
+	    infoPtr->token = BIT_XOR;
+	    return TCL_OK;
+
+	case '|':
+	    if (src[1] == '|') {
+		infoPtr->next = src+2;
+		infoPtr->token = OR;
+	    } else {
+		infoPtr->token = BIT_OR;
+	    }
+	    return TCL_OK;
+
+	case '~':
+	    infoPtr->token = BIT_NOT;
+	    return TCL_OK;
+
+	default:
+	    if (isalpha(UCHAR(*src))) {
+		infoPtr->token = FUNC_NAME;
+		infoPtr->funcName = src;
+		while (isalnum(UCHAR(*src)) || (*src == '_')) {
+		    src++;
+		}
+		infoPtr->next = src;
+		return TCL_OK;
+	    }
+	    infoPtr->next = src+1;
+	    infoPtr->token = UNKNOWN;
+	    return TCL_OK;
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CreateMathFunc --
+ *
+ *	Creates a new math function for expressions in a given
+ *	interpreter.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The function defined by "name" is created or redefined. If the
+ *	function already exists then its definition is replaced; this
+ *	includes the builtin functions. Redefining a builtin function forces
+ *	all existing code to be invalidated since that code may be compiled
+ *	using an instruction specific to the replaced function. In addition,
+ *	redefioning a non-builtin function will force existing code to be
+ *	invalidated if the number of arguments has changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_CreateMathFunc(interp, name, numArgs, argTypes, proc, clientData)
+    Tcl_Interp *interp;			/* Interpreter in which function is
+					 * to be available. */
+    char *name;				/* Name of function (e.g. "sin"). */
+    int numArgs;			/* Nnumber of arguments required by
+					 * function. */
+    Tcl_ValueType *argTypes;		/* Array of types acceptable for
+					 * each argument. */
+    Tcl_MathProc *proc;			/* Procedure that implements the
+					 * math function. */
+    ClientData clientData;		/* Additional value to pass to the
+					 * function. */
+{
+    Interp *iPtr = (Interp *) interp;
+    Tcl_HashEntry *hPtr;
+    MathFunc *mathFuncPtr;
+    int new, i;
+
+    hPtr = Tcl_CreateHashEntry(&iPtr->mathFuncTable, name, &new);
+    if (new) {
+	Tcl_SetHashValue(hPtr, ckalloc(sizeof(MathFunc)));
+    }
+    mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
+
+    if (!new) {	
+	if (mathFuncPtr->builtinFuncIndex >= 0) {
+	    /*
+	     * We are redefining a builtin math function. Invalidate the
+             * interpreter's existing code by incrementing its
+             * compileEpoch member. This field is checked in Tcl_EvalObj
+             * and ObjInterpProc, and code whose compilation epoch doesn't
+             * match is recompiled. Newly compiled code will no longer
+             * treat the function as builtin.
+	     */
+
+	    iPtr->compileEpoch++;
+	} else {
+	    /*
+	     * A non-builtin function is being redefined. We must invalidate
+             * existing code if the number of arguments has changed. This
+	     * is because existing code was compiled assuming that number.
+	     */
+
+	    if (numArgs != mathFuncPtr->numArgs) {
+		iPtr->compileEpoch++;
+	    }
+	}
+    }
+    
+    mathFuncPtr->builtinFuncIndex = -1;	/* can't be a builtin function */
+    if (numArgs > MAX_MATH_ARGS) {
+	numArgs = MAX_MATH_ARGS;
+    }
+    mathFuncPtr->numArgs = numArgs;
+    for (i = 0;  i < numArgs;  i++) {
+	mathFuncPtr->argTypes[i] = argTypes[i];
+    }
+    mathFuncPtr->proc = proc;
+    mathFuncPtr->clientData = clientData;
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclCompile.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclCompile.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclCompile.c	(revision 5)
@@ -0,0 +1,8149 @@
+/* 
+ * tclCompile.c --
+ *
+ *	This file contains procedures that compile Tcl commands or parts
+ *	of commands (like quoted strings or nested sub-commands) into a
+ *	sequence of instructions ("bytecodes"). 
+ *
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclCompile.c,v 1.1 2008-06-04 13:58:05 demin Exp $
+ */
+
+#include "tclInt.h"
+#include "tclCompile.h"
+
+/*
+ * Variable that controls whether compilation tracing is enabled and, if so,
+ * what level of tracing is desired:
+ *    0: no compilation tracing
+ *    1: summarize compilation of top level cmds and proc bodies
+ *    2: display all instructions of each ByteCode compiled
+ * This variable is linked to the Tcl variable "tcl_traceCompile".
+ */
+
+int tclTraceCompile = 0;
+static int traceInitialized = 0;
+
+/*
+ * Count of the number of compilations and various other compilation-
+ * related statistics.
+ */
+
+#ifdef TCL_COMPILE_STATS
+long tclNumCompilations = 0;
+double tclTotalSourceBytes = 0.0;
+double tclTotalCodeBytes = 0.0;
+
+double tclTotalInstBytes = 0.0;
+double tclTotalObjBytes = 0.0;
+double tclTotalExceptBytes = 0.0;
+double tclTotalAuxBytes = 0.0;
+double tclTotalCmdMapBytes = 0.0;
+
+double tclCurrentSourceBytes = 0.0;
+double tclCurrentCodeBytes = 0.0;
+
+int tclSourceCount[32];
+int tclByteCodeCount[32];
+#endif /* TCL_COMPILE_STATS */
+
+/*
+ * A table describing the Tcl bytecode instructions. The entries in this
+ * table must correspond to the list of instructions in tclInt.h. The names
+ * "op1" and "op4" refer to an instruction's one or four byte first operand.
+ * Similarly, "stktop" and "stknext" refer to the topmost and next to
+ * topmost stack elements.
+ *
+ * Note that the load, store, and incr instructions do not distinguish local
+ * from global variables; the bytecode interpreter at runtime uses the
+ * existence of a procedure call frame to distinguish these.
+ */
+
+InstructionDesc instructionTable[] = {
+   /* Name	      Bytes #Opnds Operand types        Stack top, next   */
+    {"done",	          1,   0,   {OPERAND_NONE}},
+        /* Finish ByteCode execution and return stktop (top stack item) */
+    {"push1",	          2,   1,   {OPERAND_UINT1}},
+        /* Push object at ByteCode objArray[op1] */
+    {"push4",	          5,   1,   {OPERAND_UINT4}},
+        /* Push object at ByteCode objArray[op4] */
+    {"pop",	          1,   0,   {OPERAND_NONE}},
+        /* Pop the topmost stack object */
+    {"dup",	          1,   0,   {OPERAND_NONE}},
+        /* Duplicate the topmost stack object and push the result */
+    {"concat1",	          2,   1,   {OPERAND_UINT1}},
+        /* Concatenate the top op1 items and push result */
+    {"invokeStk1",        2,   1,   {OPERAND_UINT1}},
+        /* Invoke command named objv[0]; <objc,objv> = <op1,top op1> */
+    {"invokeStk4",        5,   1,   {OPERAND_UINT4}},
+        /* Invoke command named objv[0]; <objc,objv> = <op4,top op4> */
+    {"evalStk",           1,   0,   {OPERAND_NONE}},
+        /* Evaluate command in stktop using Tcl_EvalObj. */
+    {"exprStk",           1,   0,   {OPERAND_NONE}},
+        /* Execute expression in stktop using Tcl_ExprStringObj. */
+    
+    {"loadScalar1",       2,   1,   {OPERAND_UINT1}},
+        /* Load scalar variable at index op1 <= 255 in call frame */
+    {"loadScalar4",       5,   1,   {OPERAND_UINT4}},
+        /* Load scalar variable at index op1 >= 256 in call frame */
+    {"loadScalarStk",     1,   0,   {OPERAND_NONE}},
+        /* Load scalar variable; scalar's name is stktop */
+    {"loadArray1",        2,   1,   {OPERAND_UINT1}},
+        /* Load array element; array at slot op1<=255, element is stktop */
+    {"loadArray4",        5,   1,   {OPERAND_UINT4}},
+        /* Load array element; array at slot op1 > 255, element is stktop */
+    {"loadArrayStk",      1,   0,   {OPERAND_NONE}},
+        /* Load array element; element is stktop, array name is stknext */
+    {"loadStk",           1,   0,   {OPERAND_NONE}},
+        /* Load general variable; unparsed variable name is stktop */
+    {"storeScalar1",      2,   1,   {OPERAND_UINT1}},
+        /* Store scalar variable at op1<=255 in frame; value is stktop */
+    {"storeScalar4",      5,   1,   {OPERAND_UINT4}},
+        /* Store scalar variable at op1 > 255 in frame; value is stktop */
+    {"storeScalarStk",    1,   0,   {OPERAND_NONE}},
+        /* Store scalar; value is stktop, scalar name is stknext */
+    {"storeArray1",       2,   1,   {OPERAND_UINT1}},
+        /* Store array element; array at op1<=255, value is top then elem */
+    {"storeArray4",       5,   1,   {OPERAND_UINT4}},
+        /* Store array element; array at op1>=256, value is top then elem */
+    {"storeArrayStk",     1,   0,   {OPERAND_NONE}},
+        /* Store array element; value is stktop, then elem, array names */
+    {"storeStk",          1,   0,   {OPERAND_NONE}},
+        /* Store general variable; value is stktop, then unparsed name */
+    
+    {"incrScalar1",       2,   1,   {OPERAND_UINT1}},
+        /* Incr scalar at index op1<=255 in frame; incr amount is stktop */
+    {"incrScalarStk",     1,   0,   {OPERAND_NONE}},
+        /* Incr scalar; incr amount is stktop, scalar's name is stknext */
+    {"incrArray1",        2,   1,   {OPERAND_UINT1}},
+        /* Incr array elem; arr at slot op1<=255, amount is top then elem */
+    {"incrArrayStk",      1,   0,   {OPERAND_NONE}},
+        /* Incr array element; amount is top then elem then array names */
+    {"incrStk",           1,   0,   {OPERAND_NONE}},
+        /* Incr general variable; amount is stktop then unparsed var name */
+    {"incrScalar1Imm",    3,   2,   {OPERAND_UINT1, OPERAND_INT1}},
+        /* Incr scalar at slot op1 <= 255; amount is 2nd operand byte */
+    {"incrScalarStkImm",  2,   1,   {OPERAND_INT1}},
+        /* Incr scalar; scalar name is stktop; incr amount is op1 */
+    {"incrArray1Imm",     3,   2,   {OPERAND_UINT1, OPERAND_INT1}},
+        /* Incr array elem; array at slot op1 <= 255, elem is stktop,
+	 * amount is 2nd operand byte */
+    {"incrArrayStkImm",   2,   1,   {OPERAND_INT1}},
+        /* Incr array element; elem is top then array name, amount is op1 */
+    {"incrStkImm",        2,   1,   {OPERAND_INT1}},
+        /* Incr general variable; unparsed name is top, amount is op1 */
+    
+    {"jump1",             2,   1,   {OPERAND_INT1}},
+        /* Jump relative to (pc + op1) */
+    {"jump4",             5,   1,   {OPERAND_INT4}},
+        /* Jump relative to (pc + op4) */
+    {"jumpTrue1",         2,   1,   {OPERAND_INT1}},
+        /* Jump relative to (pc + op1) if stktop expr object is true */
+    {"jumpTrue4",         5,   1,   {OPERAND_INT4}},
+        /* Jump relative to (pc + op4) if stktop expr object is true */
+    {"jumpFalse1",        2,   1,   {OPERAND_INT1}},
+        /* Jump relative to (pc + op1) if stktop expr object is false */
+    {"jumpFalse4",        5,   1,   {OPERAND_INT4}},
+        /* Jump relative to (pc + op4) if stktop expr object is false */
+
+    {"lor",               1,   0,   {OPERAND_NONE}},
+        /* Logical or:	push (stknext || stktop) */
+    {"land",              1,   0,   {OPERAND_NONE}},
+        /* Logical and:	push (stknext && stktop) */
+    {"bitor",             1,   0,   {OPERAND_NONE}},
+        /* Bitwise or:	push (stknext | stktop) */
+    {"bitxor",            1,   0,   {OPERAND_NONE}},
+        /* Bitwise xor	push (stknext ^ stktop) */
+    {"bitand",            1,   0,   {OPERAND_NONE}},
+        /* Bitwise and:	push (stknext & stktop) */
+    {"eq",                1,   0,   {OPERAND_NONE}},
+        /* Equal:	push (stknext == stktop) */
+    {"neq",               1,   0,   {OPERAND_NONE}},
+        /* Not equal:	push (stknext != stktop) */
+    {"lt",                1,   0,   {OPERAND_NONE}},
+        /* Less:	push (stknext < stktop) */
+    {"gt",                1,   0,   {OPERAND_NONE}},
+        /* Greater:	push (stknext || stktop) */
+    {"le",                1,   0,   {OPERAND_NONE}},
+        /* Logical or:	push (stknext || stktop) */
+    {"ge",                1,   0,   {OPERAND_NONE}},
+        /* Logical or:	push (stknext || stktop) */
+    {"lshift",            1,   0,   {OPERAND_NONE}},
+        /* Left shift:	push (stknext << stktop) */
+    {"rshift",            1,   0,   {OPERAND_NONE}},
+        /* Right shift:	push (stknext >> stktop) */
+    {"add",               1,   0,   {OPERAND_NONE}},
+        /* Add:		push (stknext + stktop) */
+    {"sub",               1,   0,   {OPERAND_NONE}},
+        /* Sub:		push (stkext - stktop) */
+    {"mult",              1,   0,   {OPERAND_NONE}},
+        /* Multiply:	push (stknext * stktop) */
+    {"div",               1,   0,   {OPERAND_NONE}},
+        /* Divide:	push (stknext / stktop) */
+    {"mod",               1,   0,   {OPERAND_NONE}},
+        /* Mod:		push (stknext % stktop) */
+    {"uplus",             1,   0,   {OPERAND_NONE}},
+        /* Unary plus:	push +stktop */
+    {"uminus",            1,   0,   {OPERAND_NONE}},
+        /* Unary minus:	push -stktop */
+    {"bitnot",            1,   0,   {OPERAND_NONE}},
+        /* Bitwise not:	push ~stktop */
+    {"not",               1,   0,   {OPERAND_NONE}},
+        /* Logical not:	push !stktop */
+    {"callBuiltinFunc1",  2,   1,   {OPERAND_UINT1}},
+        /* Call builtin math function with index op1; any args are on stk */
+    {"callFunc1",         2,   1,   {OPERAND_UINT1}},
+        /* Call non-builtin func objv[0]; <objc,objv>=<op1,top op1>  */
+    {"tryCvtToNumeric",   1,   0,   {OPERAND_NONE}},
+        /* Try converting stktop to first int then double if possible. */
+
+    {"break",             1,   0,   {OPERAND_NONE}},
+        /* Abort closest enclosing loop; if none, return TCL_BREAK code. */
+    {"continue",          1,   0,   {OPERAND_NONE}},
+        /* Skip to next iteration of closest enclosing loop; if none,
+	 * return TCL_CONTINUE code. */
+
+    {"foreach_start4",    5,   1,   {OPERAND_UINT4}},
+        /* Initialize execution of a foreach loop. Operand is aux data index
+	 * of the ForeachInfo structure for the foreach command. */
+    {"foreach_step4",     5,   1,   {OPERAND_UINT4}},
+        /* "Step" or begin next iteration of foreach loop. Push 0 if to
+	 *  terminate loop, else push 1. */
+
+    {"beginCatch4",	  5,   1,   {OPERAND_UINT4}},
+        /* Record start of catch with the operand's exception range index.
+	 * Push the current stack depth onto a special catch stack. */
+    {"endCatch",	  1,   0,   {OPERAND_NONE}},
+        /* End of last catch. Pop the bytecode interpreter's catch stack. */
+    {"pushResult",	  1,   0,   {OPERAND_NONE}},
+        /* Push the interpreter's object result onto the stack. */
+    {"pushReturnCode",	  1,   0,   {OPERAND_NONE}},
+        /* Push interpreter's return code (e.g. TCL_OK or TCL_ERROR) as
+	 * a new object onto the stack. */
+    {0}
+};
+
+/*
+ * The following table assigns a type to each character. Only types
+ * meaningful to Tcl parsing are represented here. The table is
+ * designed to be referenced with either signed or unsigned characters,
+ * so it has 384 entries. The first 128 entries correspond to negative
+ * character values, the next 256 correspond to positive character
+ * values. The last 128 entries are identical to the first 128. The
+ * table is always indexed with a 128-byte offset (the 128th entry
+ * corresponds to a 0 character value).
+ */
+
+unsigned char tclTypeTable[] = {
+    /*
+     * Negative character values, from -128 to -1:
+     */
+
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+
+    /*
+     * Positive character values, from 0-127:
+     */
+
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_SPACE,         TCL_COMMAND_END,   TCL_SPACE,
+    TCL_SPACE,         TCL_SPACE,         TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_SPACE,         TCL_NORMAL,        TCL_QUOTE,         TCL_NORMAL,
+    TCL_DOLLAR,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_COMMAND_END,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_OPEN_BRACKET,
+    TCL_BACKSLASH,     TCL_COMMAND_END,   TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_OPEN_BRACE,
+    TCL_NORMAL,        TCL_CLOSE_BRACE,   TCL_NORMAL,        TCL_NORMAL,
+
+    /*
+     * Large unsigned character values, from 128-255:
+     */
+
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+    TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
+};
+
+/*
+ * Table of all AuxData types.
+ */
+
+static Tcl_HashTable auxDataTypeTable;
+static int auxDataTypeTableInitialized = 0;    /* 0 means not yet
+                                                * initialized. */
+
+/*
+ * Prototypes for procedures defined later in this file:
+ */
+
+static void		AdvanceToNextWord _ANSI_ARGS_((char *string,
+			    CompileEnv *envPtr));
+static int		CollectArgInfo _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, char *lastChar, int flags,
+			    ArgInfo *argInfoPtr));
+static int		CompileBraces _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, char *lastChar, int flags,
+			    CompileEnv *envPtr));
+static int		CompileCmdWordInline _ANSI_ARGS_((
+    			    Tcl_Interp *interp, char *string,
+			    char *lastChar, int flags, CompileEnv *envPtr));
+static int		CompileExprWord _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, char *lastChar, int flags, 
+			    CompileEnv *envPtr));
+static int		CompileMultipartWord _ANSI_ARGS_((
+    			    Tcl_Interp *interp, char *string,
+			    char *lastChar, int flags, CompileEnv *envPtr));
+static int		CompileWord _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, char *lastChar, int flags, 
+			    CompileEnv *envPtr));
+static int		CreateExceptionRange _ANSI_ARGS_((
+			    ExceptionRangeType type, CompileEnv *envPtr));
+static void		DupByteCodeInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
+			    Tcl_Obj *copyPtr));
+static ClientData	DupForeachInfo _ANSI_ARGS_((ClientData clientData));
+static unsigned char *	EncodeCmdLocMap _ANSI_ARGS_((
+			    CompileEnv *envPtr, ByteCode *codePtr,
+			    unsigned char *startPtr));
+static void		EnterCmdExtentData _ANSI_ARGS_((
+    			    CompileEnv *envPtr, int cmdNumber,
+			    int numSrcChars, int numCodeBytes));
+static void		EnterCmdStartData _ANSI_ARGS_((
+    			    CompileEnv *envPtr, int cmdNumber,
+			    int srcOffset, int codeOffset));
+static void		ExpandObjectArray _ANSI_ARGS_((CompileEnv *envPtr));
+static void		FreeForeachInfo _ANSI_ARGS_((
+			    ClientData clientData));
+static void		FreeByteCodeInternalRep _ANSI_ARGS_((
+    			    Tcl_Obj *objPtr));
+static void		FreeArgInfo _ANSI_ARGS_((ArgInfo *argInfoPtr));
+static int		GetCmdLocEncodingSize _ANSI_ARGS_((
+			    CompileEnv *envPtr));
+static void		InitArgInfo _ANSI_ARGS_((ArgInfo *argInfoPtr));
+static int		IsLocalScalar  _ANSI_ARGS_((char *name, int len));
+static int		LookupCompiledLocal _ANSI_ARGS_((
+        		    char *name, int nameChars, int createIfNew,
+			    int flagsIfCreated, Proc *procPtr));
+static int		SetByteCodeFromAny _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr));
+static void		UpdateStringOfByteCode _ANSI_ARGS_((Tcl_Obj *objPtr));
+
+/*
+ * The structure below defines the bytecode Tcl object type by
+ * means of procedures that can be invoked by generic object code.
+ */
+
+Tcl_ObjType tclByteCodeType = {
+    "bytecode",			/* name */
+    FreeByteCodeInternalRep,	/* freeIntRepProc */
+    DupByteCodeInternalRep,	/* dupIntRepProc */
+    UpdateStringOfByteCode,	/* updateStringProc */
+    SetByteCodeFromAny		/* setFromAnyProc */
+};
+
+/*
+ * The structures below define the AuxData types defined in this file.
+ */
+
+AuxDataType tclForeachInfoType = {
+    "ForeachInfo",				/* name */
+    DupForeachInfo,				/* dupProc */
+    FreeForeachInfo				/* freeProc */
+};
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclPrintByteCodeObj --
+ *
+ *	This procedure prints ("disassembles") the instructions of a
+ *	bytecode object to stdout.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclPrintByteCodeObj(interp, objPtr)
+    Tcl_Interp *interp;		/* Used only for Tcl_GetStringFromObj. */
+    Tcl_Obj *objPtr;		/* The bytecode object to disassemble. */
+{
+    ByteCode* codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
+    unsigned char *codeStart, *codeLimit, *pc;
+    unsigned char *codeDeltaNext, *codeLengthNext;
+    unsigned char *srcDeltaNext, *srcLengthNext;
+    int codeOffset, codeLen, srcOffset, srcLen;
+    int numCmds, numObjs, delta, objBytes, i;
+
+    if (codePtr->refCount <= 0) {
+	return;			/* already freed */
+    }
+
+    codeStart = codePtr->codeStart;
+    codeLimit = (codeStart + codePtr->numCodeBytes);
+    numCmds = codePtr->numCommands;
+    numObjs = codePtr->numObjects;
+
+    objBytes = (numObjs * sizeof(Tcl_Obj));
+    for (i = 0;  i < numObjs;  i++) {
+	Tcl_Obj *litObjPtr = codePtr->objArrayPtr[i];
+	if (litObjPtr->bytes != NULL) {
+	    objBytes += litObjPtr->length;
+	}
+    }
+
+    /*
+     * Print header lines describing the ByteCode.
+     */
+
+    fprintf(stdout, "\nByteCode 0x%x, ref ct %u, epoch %u, interp 0x%x(epoch %u)\n",
+	    (unsigned int) codePtr, codePtr->refCount,
+	    codePtr->compileEpoch, (unsigned int) codePtr->iPtr,
+	    codePtr->iPtr->compileEpoch);
+    fprintf(stdout, "  Source ");
+    TclPrintSource(stdout, codePtr->source,
+	    TclMin(codePtr->numSrcChars, 70));
+    fprintf(stdout, "\n  Cmds %d, chars %d, inst %d, objs %u, aux %d, stk depth %u, code/src %.2f\n",
+	    numCmds, codePtr->numSrcChars, codePtr->numCodeBytes, numObjs,
+	    codePtr->numAuxDataItems, codePtr->maxStackDepth,
+	    (codePtr->numSrcChars?
+	            ((float)codePtr->totalSize)/((float)codePtr->numSrcChars) : 0.0));
+    fprintf(stdout, "  Code %zu = %u(header)+%d(inst)+%d(objs)+%u(exc)+%u(aux)+%d(cmd map)\n",
+	    codePtr->totalSize, sizeof(ByteCode), codePtr->numCodeBytes,
+	    objBytes, (codePtr->numExcRanges * sizeof(ExceptionRange)),
+	    (codePtr->numAuxDataItems * sizeof(AuxData)),
+	    codePtr->numCmdLocBytes);
+
+    /*
+     * If the ByteCode is the compiled body of a Tcl procedure, print
+     * information about that procedure. Note that we don't know the
+     * procedure's name since ByteCode's can be shared among procedures.
+     */
+    
+    if (codePtr->procPtr != NULL) {
+	Proc *procPtr = codePtr->procPtr;
+	int numCompiledLocals = procPtr->numCompiledLocals;
+	fprintf(stdout,
+	        "  Proc 0x%x, ref ct %d, args %d, compiled locals %d\n",
+		(unsigned int) procPtr, procPtr->refCount, procPtr->numArgs,
+		numCompiledLocals);
+	if (numCompiledLocals > 0) {
+	    CompiledLocal *localPtr = procPtr->firstLocalPtr;
+	    for (i = 0;  i < numCompiledLocals;  i++) {
+		fprintf(stdout, "      %d: slot %d%s%s%s%s%s%s",
+			i, localPtr->frameIndex,
+			((localPtr->flags & VAR_SCALAR)?  ", scalar"  : ""),
+			((localPtr->flags & VAR_ARRAY)?  ", array"  : ""),
+			((localPtr->flags & VAR_LINK)?  ", link"  : ""),
+			((localPtr->flags & VAR_ARGUMENT)?  ", arg"  : ""),
+			((localPtr->flags & VAR_TEMPORARY)? ", temp" : ""),
+			((localPtr->flags & VAR_RESOLVED)? ", resolved" : ""));
+		if (TclIsVarTemporary(localPtr)) {
+		    fprintf(stdout,	"\n");
+		} else {
+		    fprintf(stdout,	", name=\"%s\"\n", localPtr->name);
+		}
+		localPtr = localPtr->nextPtr;
+	    }
+	}
+    }
+
+    /*
+     * Print the ExceptionRange array.
+     */
+
+    if (codePtr->numExcRanges > 0) {
+	fprintf(stdout, "  Exception ranges %d, depth %d:\n",
+	        codePtr->numExcRanges, codePtr->maxExcRangeDepth);
+	for (i = 0;  i < codePtr->numExcRanges;  i++) {
+	    ExceptionRange *rangePtr = &(codePtr->excRangeArrayPtr[i]);
+	    fprintf(stdout, "      %d: level %d, %s, pc %d-%d, ",
+		    i, rangePtr->nestingLevel,
+		    ((rangePtr->type == LOOP_EXCEPTION_RANGE)? "loop":"catch"),
+		    rangePtr->codeOffset,
+		    (rangePtr->codeOffset + rangePtr->numCodeBytes - 1));
+	    switch (rangePtr->type) {
+	    case LOOP_EXCEPTION_RANGE:
+		fprintf(stdout,	"continue %d, break %d\n",
+		        rangePtr->continueOffset, rangePtr->breakOffset);
+		break;
+	    case CATCH_EXCEPTION_RANGE:
+		fprintf(stdout,	"catch %d\n", rangePtr->catchOffset);
+		break;
+	    default:
+		panic("TclPrintSource: unrecognized ExceptionRange type %d\n",
+		        rangePtr->type);
+	    }
+	}
+    }
+    
+    /*
+     * If there were no commands (e.g., an expression or an empty string
+     * was compiled), just print all instructions and return.
+     */
+
+    if (numCmds == 0) {
+	pc = codeStart;
+	while (pc < codeLimit) {
+	    fprintf(stdout, "    ");
+	    pc += TclPrintInstruction(codePtr, pc);
+	}
+	return;
+    }
+    
+    /*
+     * Print table showing the code offset, source offset, and source
+     * length for each command. These are encoded as a sequence of bytes.
+     */
+
+    fprintf(stdout, "  Commands %d:", numCmds);
+    codeDeltaNext = codePtr->codeDeltaStart;
+    codeLengthNext = codePtr->codeLengthStart;
+    srcDeltaNext  = codePtr->srcDeltaStart;
+    srcLengthNext = codePtr->srcLengthStart;
+    codeOffset = srcOffset = 0;
+    for (i = 0;  i < numCmds;  i++) {
+	if ((unsigned int) (*codeDeltaNext) == (unsigned int) 0xFF) {
+	    codeDeltaNext++;
+	    delta = TclGetInt4AtPtr(codeDeltaNext);
+	    codeDeltaNext += 4;
+	} else {
+	    delta = TclGetInt1AtPtr(codeDeltaNext);
+	    codeDeltaNext++;
+	}
+	codeOffset += delta;
+
+	if ((unsigned int) (*codeLengthNext) == (unsigned int) 0xFF) {
+	    codeLengthNext++;
+	    codeLen = TclGetInt4AtPtr(codeLengthNext);
+	    codeLengthNext += 4;
+	} else {
+	    codeLen = TclGetInt1AtPtr(codeLengthNext);
+	    codeLengthNext++;
+	}
+	
+	if ((unsigned int) (*srcDeltaNext) == (unsigned int) 0xFF) {
+	    srcDeltaNext++;
+	    delta = TclGetInt4AtPtr(srcDeltaNext);
+	    srcDeltaNext += 4;
+	} else {
+	    delta = TclGetInt1AtPtr(srcDeltaNext);
+	    srcDeltaNext++;
+	}
+	srcOffset += delta;
+
+	if ((unsigned int) (*srcLengthNext) == (unsigned int) 0xFF) {
+	    srcLengthNext++;
+	    srcLen = TclGetInt4AtPtr(srcLengthNext);
+	    srcLengthNext += 4;
+	} else {
+	    srcLen = TclGetInt1AtPtr(srcLengthNext);
+	    srcLengthNext++;
+	}
+	
+	fprintf(stdout,	"%s%4d: pc %d-%d, source %d-%d",
+		((i % 2)? "	" : "\n   "),
+		(i+1), codeOffset, (codeOffset + codeLen - 1),
+		srcOffset, (srcOffset + srcLen - 1));
+    }
+    if ((numCmds > 0) && ((numCmds % 2) != 0)) {
+	fprintf(stdout,	"\n");
+    }
+    
+    /*
+     * Print each instruction. If the instruction corresponds to the start
+     * of a command, print the command's source. Note that we don't need
+     * the code length here.
+     */
+
+    codeDeltaNext = codePtr->codeDeltaStart;
+    srcDeltaNext  = codePtr->srcDeltaStart;
+    srcLengthNext = codePtr->srcLengthStart;
+    codeOffset = srcOffset = 0;
+    pc = codeStart;
+    for (i = 0;  i < numCmds;  i++) {
+	if ((unsigned int) (*codeDeltaNext) == (unsigned int) 0xFF) {
+	    codeDeltaNext++;
+	    delta = TclGetInt4AtPtr(codeDeltaNext);
+	    codeDeltaNext += 4;
+	} else {
+	    delta = TclGetInt1AtPtr(codeDeltaNext);
+	    codeDeltaNext++;
+	}
+	codeOffset += delta;
+
+	if ((unsigned int) (*srcDeltaNext) == (unsigned int) 0xFF) {
+	    srcDeltaNext++;
+	    delta = TclGetInt4AtPtr(srcDeltaNext);
+	    srcDeltaNext += 4;
+	} else {
+	    delta = TclGetInt1AtPtr(srcDeltaNext);
+	    srcDeltaNext++;
+	}
+	srcOffset += delta;
+
+	if ((unsigned int) (*srcLengthNext) == (unsigned int) 0xFF) {
+	    srcLengthNext++;
+	    srcLen = TclGetInt4AtPtr(srcLengthNext);
+	    srcLengthNext += 4;
+	} else {
+	    srcLen = TclGetInt1AtPtr(srcLengthNext);
+	    srcLengthNext++;
+	}
+
+	/*
+	 * Print instructions before command i.
+	 */
+	
+	while ((pc-codeStart) < codeOffset) {
+	    fprintf(stdout, "    ");
+	    pc += TclPrintInstruction(codePtr, pc);
+	}
+
+	fprintf(stdout, "  Command %d: ", (i+1));
+	TclPrintSource(stdout, (codePtr->source + srcOffset),
+	        TclMin(srcLen, 70));
+	fprintf(stdout, "\n");
+    }
+    if (pc < codeLimit) {
+	/*
+	 * Print instructions after the last command.
+	 */
+
+	while (pc < codeLimit) {
+	    fprintf(stdout, "    ");
+	    pc += TclPrintInstruction(codePtr, pc);
+	}
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclPrintInstruction --
+ *
+ *	This procedure prints ("disassembles") one instruction from a
+ *	bytecode object to stdout.
+ *
+ * Results:
+ *	Returns the length in bytes of the current instruiction.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclPrintInstruction(codePtr, pc)
+    ByteCode* codePtr;		/* Bytecode containing the instruction. */
+    unsigned char *pc;		/* Points to first byte of instruction. */
+{
+    Proc *procPtr = codePtr->procPtr;
+    unsigned char opCode = *pc;
+    register InstructionDesc *instDesc = &instructionTable[opCode];
+    unsigned char *codeStart = codePtr->codeStart;
+    unsigned int pcOffset = (pc - codeStart);
+    int opnd, elemLen, i, j;
+    Tcl_Obj *elemPtr;
+    char *string;
+    
+    fprintf(stdout, "(%u) %s ", pcOffset, instDesc->name);
+    for (i = 0;  i < instDesc->numOperands;  i++) {
+	switch (instDesc->opTypes[i]) {
+	case OPERAND_INT1:
+	    opnd = TclGetInt1AtPtr(pc+1+i);
+	    if ((i == 0) && ((opCode == INST_JUMP1)
+			     || (opCode == INST_JUMP_TRUE1)
+		             || (opCode == INST_JUMP_FALSE1))) {
+		fprintf(stdout, "%d  	# pc %u", opnd, (pcOffset + opnd));
+	    } else {
+		fprintf(stdout, "%d", opnd);
+	    }
+	    break;
+	case OPERAND_INT4:
+	    opnd = TclGetInt4AtPtr(pc+1+i);
+	    if ((i == 0) && ((opCode == INST_JUMP4)
+			     || (opCode == INST_JUMP_TRUE4)
+		             || (opCode == INST_JUMP_FALSE4))) {
+		fprintf(stdout, "%d  	# pc %u", opnd, (pcOffset + opnd));
+	    } else {
+		fprintf(stdout, "%d", opnd);
+	    }
+	    break;
+	case OPERAND_UINT1:
+	    opnd = TclGetUInt1AtPtr(pc+1+i);
+	    if ((i == 0) && (opCode == INST_PUSH1)) {
+		elemPtr = codePtr->objArrayPtr[opnd];
+		string = Tcl_GetStringFromObj(elemPtr, &elemLen);
+		fprintf(stdout, "%u  	# ", (unsigned int) opnd);
+		TclPrintSource(stdout, string, TclMin(elemLen, 40));
+	    } else if ((i == 0) && ((opCode == INST_LOAD_SCALAR1)
+				    || (opCode == INST_LOAD_ARRAY1)
+				    || (opCode == INST_STORE_SCALAR1)
+				    || (opCode == INST_STORE_ARRAY1))) {
+		int localCt = procPtr->numCompiledLocals;
+		CompiledLocal *localPtr = procPtr->firstLocalPtr;
+		if (opnd >= localCt) {
+		    panic("TclPrintInstruction: bad local var index %u (%u locals)\n",
+			     (unsigned int) opnd, localCt);
+		    return instDesc->numBytes;
+		}
+		for (j = 0;  j < opnd;  j++) {
+		    localPtr = localPtr->nextPtr;
+		}
+		if (TclIsVarTemporary(localPtr)) {
+		    fprintf(stdout, "%u	# temp var %u",
+			    (unsigned int) opnd, (unsigned int) opnd);
+		} else {
+		    fprintf(stdout, "%u	# var ", (unsigned int) opnd);
+		    TclPrintSource(stdout, localPtr->name, 40);
+		}
+	    } else {
+		fprintf(stdout, "%u ", (unsigned int) opnd);
+	    }
+	    break;
+	case OPERAND_UINT4:
+	    opnd = TclGetUInt4AtPtr(pc+1+i);
+	    if (opCode == INST_PUSH4) {
+		elemPtr = codePtr->objArrayPtr[opnd];
+		string = Tcl_GetStringFromObj(elemPtr, &elemLen);
+		fprintf(stdout, "%u  	# ", opnd);
+		TclPrintSource(stdout, string, TclMin(elemLen, 40));
+	    } else if ((i == 0) && ((opCode == INST_LOAD_SCALAR4)
+				    || (opCode == INST_LOAD_ARRAY4)
+				    || (opCode == INST_STORE_SCALAR4)
+				    || (opCode == INST_STORE_ARRAY4))) {
+		int localCt = procPtr->numCompiledLocals;
+		CompiledLocal *localPtr = procPtr->firstLocalPtr;
+		if (opnd >= localCt) {
+		    panic("TclPrintInstruction: bad local var index %u (%u locals)\n",
+			     (unsigned int) opnd, localCt);
+		    return instDesc->numBytes;
+		}
+		for (j = 0;  j < opnd;  j++) {
+		    localPtr = localPtr->nextPtr;
+		}
+		if (TclIsVarTemporary(localPtr)) {
+		    fprintf(stdout, "%u	# temp var %u",
+			    (unsigned int) opnd, (unsigned int) opnd);
+		} else {
+		    fprintf(stdout, "%u	# var ", (unsigned int) opnd);
+		    TclPrintSource(stdout, localPtr->name, 40);
+		}
+	    } else {
+		fprintf(stdout, "%u ", (unsigned int) opnd);
+	    }
+	    break;
+	case OPERAND_NONE:
+	default:
+	    break;
+	}
+    }
+    fprintf(stdout, "\n");
+    return instDesc->numBytes;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclPrintSource --
+ *
+ *	This procedure prints up to a specified number of characters from
+ *	the argument string to a specified file. It tries to produce legible
+ *	output by adding backslashes as necessary.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Outputs characters to the specified file.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclPrintSource(outFile, string, maxChars)
+    FILE *outFile;		/* The file to print the source to. */
+    char *string;		/* The string to print. */
+    int maxChars;		/* Maximum number of chars to print. */
+{
+    register char *p;
+    register int i = 0;
+
+    if (string == NULL) {
+	fprintf(outFile, "\"\"");
+	return;
+    }
+
+    fprintf(outFile, "\"");
+    p = string;
+    for (;  (*p != '\0') && (i < maxChars);  p++, i++) {
+	switch (*p) {
+	    case '"':
+		fprintf(outFile, "\\\"");
+		continue;
+	    case '\f':
+		fprintf(outFile, "\\f");
+		continue;
+	    case '\n':
+		fprintf(outFile, "\\n");
+		continue;
+            case '\r':
+		fprintf(outFile, "\\r");
+		continue;
+	    case '\t':
+		fprintf(outFile, "\\t");
+		continue;
+            case '\v':
+		fprintf(outFile, "\\v");
+		continue;
+	    default:
+		fprintf(outFile, "%c", *p);
+		continue;
+	}
+    }
+    fprintf(outFile, "\"");
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeByteCodeInternalRep --
+ *
+ *	Part of the bytecode Tcl object type implementation. Frees the
+ *	storage associated with a bytecode object's internal representation
+ *	unless its code is actively being executed.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The bytecode object's internal rep is marked invalid and its
+ *	code gets freed unless the code is actively being executed.
+ *	In that case the cleanup is delayed until the last execution
+ *	of the code completes.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeByteCodeInternalRep(objPtr)
+    register Tcl_Obj *objPtr;	/* Object whose internal rep to free. */
+{
+    register ByteCode *codePtr =
+	    (ByteCode *) objPtr->internalRep.otherValuePtr;
+
+    codePtr->refCount--;
+    if (codePtr->refCount <= 0) {
+	TclCleanupByteCode(codePtr);
+    }
+    objPtr->typePtr = NULL;
+    objPtr->internalRep.otherValuePtr = NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCleanupByteCode --
+ *
+ *	This procedure does all the real work of freeing up a bytecode
+ *	object's ByteCode structure. It's called only when the structure's
+ *	reference count becomes zero.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Frees objPtr's bytecode internal representation and sets
+ *	its type and objPtr->internalRep.otherValuePtr NULL. Also
+ *	decrements the ref counts on each object in its object array,
+ *	and frees its auxiliary data items.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclCleanupByteCode(codePtr)
+    ByteCode *codePtr;		/* ByteCode to free. */
+{
+    Tcl_Obj **objArrayPtr = codePtr->objArrayPtr;
+    int numObjects = codePtr->numObjects;
+    int numAuxDataItems = codePtr->numAuxDataItems;
+    register AuxData *auxDataPtr;
+    register Tcl_Obj *elemPtr;
+    register int i;
+
+#ifdef TCL_COMPILE_STATS    
+    tclCurrentSourceBytes -= (double) codePtr->numSrcChars;
+    tclCurrentCodeBytes -= (double) codePtr->totalSize;
+#endif /* TCL_COMPILE_STATS */
+
+    /*
+     * A single heap object holds the ByteCode structure and its code,
+     * object, command location, and auxiliary data arrays. This means we
+     * only need to 1) decrement the ref counts on the objects in its
+     * object array, 2) call the free procs for the auxiliary data items,
+     * and 3) free the ByteCode structure's heap object.
+     */
+
+    for (i = 0;  i < numObjects;  i++) {
+	elemPtr = objArrayPtr[i];
+	TclDecrRefCount(elemPtr);
+    }
+
+    auxDataPtr = codePtr->auxDataArrayPtr;
+    for (i = 0;  i < numAuxDataItems;  i++) {
+	if (auxDataPtr->type->freeProc != NULL) {
+	    auxDataPtr->type->freeProc(auxDataPtr->clientData);
+	}
+	auxDataPtr++;
+    }
+    
+    ckfree((char *) codePtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupByteCodeInternalRep --
+ *
+ *	Part of the bytecode Tcl object type implementation. However, it
+ *	does not copy the internal representation of a bytecode Tcl_Obj, but
+ *	instead leaves the new object untyped (with a NULL type pointer).
+ *	Code will be compiled for the new object only if necessary.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DupByteCodeInternalRep(srcPtr, copyPtr)
+    Tcl_Obj *srcPtr;		/* Object with internal rep to copy. */
+    Tcl_Obj *copyPtr;		/* Object with internal rep to set. */
+{
+    return;
+}
+
+
+/*
+ *-----------------------------------------------------------------------
+ *
+ * SetByteCodeFromAny --
+ *
+ *	Part of the bytecode Tcl object type implementation. Attempts to
+ *	generate an byte code internal form for the Tcl object "objPtr" by
+ *	compiling its string representation.
+ *
+ * Results:
+ *	The return value is a standard Tcl object result. If an error occurs
+ *	during compilation, an error message is left in the interpreter's
+ *	result unless "interp" is NULL.
+ *
+ * Side effects:
+ *	Frees the old internal representation. If no error occurs, then the
+ *	compiled code is stored as "objPtr"s bytecode representation.
+ *	Also, if debugging, initializes the "tcl_traceCompile" Tcl variable
+ *	used to trace compilations.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetByteCodeFromAny(interp, objPtr)
+    Tcl_Interp *interp;		/* The interpreter for which the code is
+				 * compiled. */
+    Tcl_Obj *objPtr;		/* The object to convert. */
+{
+    Interp *iPtr = (Interp *) interp;
+    char *string;
+    CompileEnv compEnv;		/* Compilation environment structure
+				 * allocated in frame. */
+    AuxData *auxDataPtr;
+    register int i;
+    int length, result;
+
+    if (!traceInitialized) {
+        if (Tcl_LinkVar(interp, "tcl_traceCompile",
+	            (char *) &tclTraceCompile,  TCL_LINK_INT) != TCL_OK) {
+            panic("SetByteCodeFromAny: unable to create link for tcl_traceCompile variable");
+        }
+        traceInitialized = 1;
+    }
+    
+    string = Tcl_GetStringFromObj(objPtr, &length);
+    TclInitCompileEnv(interp, &compEnv, string);
+    result = TclCompileString(interp, string, string+length,
+	    iPtr->evalFlags, &compEnv);
+    if (result == TCL_OK) {
+	/*
+	 * Add a "done" instruction at the end of the instruction sequence.
+	 */
+    
+	TclEmitOpcode(INST_DONE, &compEnv);
+	
+	/*
+	 * Convert the object to a ByteCode object.
+	 */
+
+	TclInitByteCodeObj(objPtr, &compEnv);
+    } else {
+	/*
+	 * Compilation errors. Decrement the ref counts on any objects in
+	 * the object array and free any aux data items prior to freeing
+	 * the compilation environment.
+	 */
+	
+	for (i = 0;  i < compEnv.objArrayNext;  i++) {
+	    Tcl_Obj *elemPtr = compEnv.objArrayPtr[i];
+	    Tcl_DecrRefCount(elemPtr);
+	}
+
+	auxDataPtr = compEnv.auxDataArrayPtr;
+	for (i = 0;  i < compEnv.auxDataArrayNext;  i++) {
+	    if (auxDataPtr->type->freeProc != NULL) {
+            auxDataPtr->type->freeProc(auxDataPtr->clientData);
+	    }
+	    auxDataPtr++;
+	}
+    }
+    TclFreeCompileEnv(&compEnv);
+
+    if (result == TCL_OK) {
+	if (tclTraceCompile == 2) {
+	    TclPrintByteCodeObj(interp, objPtr);
+	}
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateStringOfByteCode --
+ *
+ *	Part of the bytecode Tcl object type implementation. Called to
+ *	update the string representation for a byte code object.
+ *	Note: This procedure does not free an existing old string rep
+ *	so storage will be lost if this has not already been done.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Generates a panic. 
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateStringOfByteCode(objPtr)
+    register Tcl_Obj *objPtr;	/* ByteCode object with string rep that 
+				 * needs updating. */
+{
+    /*
+     * This procedure is never invoked since the internal representation of
+     * a bytecode object is never modified.
+     */
+
+    panic("UpdateStringOfByteCode should never be called.");
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInitCompileEnv --
+ *
+ *	Initializes a CompileEnv compilation environment structure for the
+ *	compilation of a string in an interpreter.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The CompileEnv structure is initialized.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclInitCompileEnv(interp, envPtr, string)
+    Tcl_Interp *interp;		 /* The interpreter for which a CompileEnv
+				  * structure is initialized. */
+    register CompileEnv *envPtr; /* Points to the CompileEnv structure to
+				  * initialize. */
+    char *string;		 /* The source string to be compiled. */
+{
+    Interp *iPtr = (Interp *) interp;
+    
+    envPtr->iPtr = iPtr;
+    envPtr->source = string;
+    envPtr->procPtr = iPtr->compiledProcPtr;
+    envPtr->numCommands = 0;
+    envPtr->excRangeDepth = 0;
+    envPtr->maxExcRangeDepth = 0;
+    envPtr->maxStackDepth = 0;
+    Tcl_InitHashTable(&(envPtr->objTable), TCL_STRING_KEYS);
+    envPtr->pushSimpleWords = 1;
+    envPtr->wordIsSimple = 0;
+    envPtr->numSimpleWordChars = 0;
+    envPtr->exprIsJustVarRef = 0;
+    envPtr->exprIsComparison = 0;
+    envPtr->termOffset = 0;
+
+    envPtr->codeStart = envPtr->staticCodeSpace;
+    envPtr->codeNext = envPtr->codeStart;
+    envPtr->codeEnd = (envPtr->codeStart + COMPILEENV_INIT_CODE_BYTES);
+    envPtr->mallocedCodeArray = 0;
+
+    envPtr->objArrayPtr = envPtr->staticObjArraySpace;
+    envPtr->objArrayNext = 0;
+    envPtr->objArrayEnd = COMPILEENV_INIT_NUM_OBJECTS;
+    envPtr->mallocedObjArray = 0;
+    
+    envPtr->excRangeArrayPtr = envPtr->staticExcRangeArraySpace;
+    envPtr->excRangeArrayNext = 0;
+    envPtr->excRangeArrayEnd = COMPILEENV_INIT_EXCEPT_RANGES;
+    envPtr->mallocedExcRangeArray = 0;
+    
+    envPtr->cmdMapPtr = envPtr->staticCmdMapSpace;
+    envPtr->cmdMapEnd = COMPILEENV_INIT_CMD_MAP_SIZE;
+    envPtr->mallocedCmdMap = 0;
+    
+    envPtr->auxDataArrayPtr = envPtr->staticAuxDataArraySpace;
+    envPtr->auxDataArrayNext = 0;
+    envPtr->auxDataArrayEnd = COMPILEENV_INIT_AUX_DATA_SIZE;
+    envPtr->mallocedAuxDataArray = 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFreeCompileEnv --
+ *
+ *	Free the storage allocated in a CompileEnv compilation environment
+ *	structure.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Allocated storage in the CompileEnv structure is freed. Note that
+ *	ref counts for Tcl objects in its object table are not decremented.
+ *	In addition, any storage referenced by any auxiliary data items
+ *	in the CompileEnv structure are not freed either. The expectation
+ *	is that when compilation is successful, "ownership" (i.e., the
+ *	pointers to) these objects and aux data items will just be handed
+ *	over to the corresponding ByteCode structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclFreeCompileEnv(envPtr)
+    register CompileEnv *envPtr; /* Points to the CompileEnv structure. */
+{
+    Tcl_DeleteHashTable(&(envPtr->objTable));
+    if (envPtr->mallocedCodeArray) {
+	ckfree((char *) envPtr->codeStart);
+    }
+    if (envPtr->mallocedObjArray) {
+	ckfree((char *) envPtr->objArrayPtr);
+    }
+    if (envPtr->mallocedExcRangeArray) {
+	ckfree((char *) envPtr->excRangeArrayPtr);
+    }
+    if (envPtr->mallocedCmdMap) {
+	ckfree((char *) envPtr->cmdMapPtr);
+    }
+    if (envPtr->mallocedAuxDataArray) {
+	ckfree((char *) envPtr->auxDataArrayPtr);
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInitByteCodeObj --
+ *
+ *	Create a ByteCode structure and initialize it from a CompileEnv
+ *	compilation environment structure. The ByteCode structure is
+ *	smaller and contains just that information needed to execute
+ *	the bytecode instructions resulting from compiling a Tcl script.
+ *	The resulting structure is placed in the specified object.
+ *
+ * Results:
+ *	A newly constructed ByteCode object is stored in the internal
+ *	representation of the objPtr.
+ *
+ * Side effects:
+ *	A single heap object is allocated to hold the new ByteCode structure
+ *	and its code, object, command location, and aux data arrays. Note
+ *	that "ownership" (i.e., the pointers to) the Tcl objects and aux
+ *	data items will be handed over to the new ByteCode structure from
+ *	the CompileEnv structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclInitByteCodeObj(objPtr, envPtr)
+    Tcl_Obj *objPtr;		 /* Points object that should be
+				  * initialized, and whose string rep
+				  * contains the source code. */
+    register CompileEnv *envPtr; /* Points to the CompileEnv structure from
+				  * which to create a ByteCode structure. */
+{
+    register ByteCode *codePtr;
+    size_t codeBytes, objArrayBytes, exceptArrayBytes, cmdLocBytes;
+    size_t auxDataArrayBytes;
+    register size_t size, objBytes, totalSize;
+    register unsigned char *p;
+    unsigned char *nextPtr;
+    int srcLen = envPtr->termOffset;
+    int numObjects, i;
+    Namespace *namespacePtr;
+#ifdef TCL_COMPILE_STATS
+    int srcLenLog2, sizeLog2;
+#endif /*TCL_COMPILE_STATS*/
+
+    codeBytes = (envPtr->codeNext - envPtr->codeStart);
+    numObjects = envPtr->objArrayNext;
+    objArrayBytes = (envPtr->objArrayNext * sizeof(Tcl_Obj *));
+    exceptArrayBytes = (envPtr->excRangeArrayNext * sizeof(ExceptionRange));
+    auxDataArrayBytes = (envPtr->auxDataArrayNext * sizeof(AuxData));
+    cmdLocBytes = GetCmdLocEncodingSize(envPtr);
+    
+    size = sizeof(ByteCode);
+    size += TCL_ALIGN(codeBytes);       /* align object array */
+    size += TCL_ALIGN(objArrayBytes);   /* align exception range array */
+    size += TCL_ALIGN(exceptArrayBytes); /* align AuxData array */
+    size += auxDataArrayBytes;
+    size += cmdLocBytes;
+
+    /*
+     * Compute the total number of bytes needed for this bytecode
+     * including the storage for the Tcl objects in its object array.
+     */
+
+    objBytes = (numObjects * sizeof(Tcl_Obj));
+    for (i = 0;  i < numObjects;  i++) {
+	Tcl_Obj *litObjPtr = envPtr->objArrayPtr[i];
+	if (litObjPtr->bytes != NULL) {
+	    objBytes += litObjPtr->length;
+	}
+    }
+    totalSize = (size + objBytes);
+
+#ifdef TCL_COMPILE_STATS
+    tclNumCompilations++;
+    tclTotalSourceBytes += (double) srcLen;
+    tclTotalCodeBytes += (double) totalSize;
+    
+    tclTotalInstBytes += (double) codeBytes;
+    tclTotalObjBytes += (double) objBytes;
+    tclTotalExceptBytes += exceptArrayBytes;
+    tclTotalAuxBytes += (double) auxDataArrayBytes;
+    tclTotalCmdMapBytes += (double) cmdLocBytes;
+
+    tclCurrentSourceBytes += (double) srcLen;
+    tclCurrentCodeBytes += (double) totalSize;
+
+    srcLenLog2 = TclLog2(srcLen);
+    sizeLog2 = TclLog2((int) totalSize);
+    if ((srcLenLog2 > 31) || (sizeLog2 > 31)) {
+	panic("TclInitByteCodeObj: bad source or code sizes\n");
+    }
+    tclSourceCount[srcLenLog2]++;
+    tclByteCodeCount[sizeLog2]++;
+#endif /* TCL_COMPILE_STATS */    
+
+    if (envPtr->iPtr->varFramePtr != NULL) {
+        namespacePtr = envPtr->iPtr->varFramePtr->nsPtr;
+    } else {
+        namespacePtr = envPtr->iPtr->globalNsPtr;
+    }
+    
+    p = (unsigned char *) ckalloc(size);
+    codePtr = (ByteCode *) p;
+    codePtr->iPtr = envPtr->iPtr;
+    codePtr->compileEpoch = envPtr->iPtr->compileEpoch;
+    codePtr->nsPtr = namespacePtr;
+    codePtr->nsEpoch = namespacePtr->resolverEpoch;
+    codePtr->refCount = 1;
+    codePtr->flags = 0;
+    codePtr->source = envPtr->source;
+    codePtr->procPtr = envPtr->procPtr;
+    codePtr->totalSize = totalSize;
+    codePtr->numCommands = envPtr->numCommands;
+    codePtr->numSrcChars = srcLen;
+    codePtr->numCodeBytes = codeBytes;
+    codePtr->numObjects = numObjects;
+    codePtr->numExcRanges = envPtr->excRangeArrayNext;
+    codePtr->numAuxDataItems = envPtr->auxDataArrayNext;
+    codePtr->auxDataArrayPtr = NULL;
+    codePtr->numCmdLocBytes = cmdLocBytes;
+    codePtr->maxExcRangeDepth = envPtr->maxExcRangeDepth;
+    codePtr->maxStackDepth = envPtr->maxStackDepth;
+    
+    p += sizeof(ByteCode);
+    codePtr->codeStart = p;
+    memcpy((VOID *) p, (VOID *) envPtr->codeStart, codeBytes);
+    
+    p += TCL_ALIGN(codeBytes);	      /* align object array */
+    codePtr->objArrayPtr = (Tcl_Obj **) p;
+    memcpy((VOID *) p, (VOID *) envPtr->objArrayPtr, objArrayBytes);
+
+    p += TCL_ALIGN(objArrayBytes);    /* align exception range array */
+    if (exceptArrayBytes > 0) {
+	codePtr->excRangeArrayPtr = (ExceptionRange *) p;
+	memcpy((VOID *) p, (VOID *) envPtr->excRangeArrayPtr,
+	        exceptArrayBytes);
+    }
+    
+    p += TCL_ALIGN(exceptArrayBytes); /* align AuxData array */
+    if (auxDataArrayBytes > 0) {
+	codePtr->auxDataArrayPtr = (AuxData *) p;
+	memcpy((VOID *) p, (VOID *) envPtr->auxDataArrayPtr,
+	        auxDataArrayBytes);
+    }
+
+    p += auxDataArrayBytes;
+    nextPtr = EncodeCmdLocMap(envPtr, codePtr, (unsigned char *) p);
+    if (((size_t)(nextPtr - p)) != cmdLocBytes) {	
+	panic("TclInitByteCodeObj: encoded cmd location bytes %d != expected size %d\n", (nextPtr - p), cmdLocBytes);
+    }
+    
+    /*
+     * Free the old internal rep then convert the object to a
+     * bytecode object by making its internal rep point to the just
+     * compiled ByteCode.
+     */
+	    
+    if ((objPtr->typePtr != NULL) &&
+	    (objPtr->typePtr->freeIntRepProc != NULL)) {
+	objPtr->typePtr->freeIntRepProc(objPtr);
+    }
+    objPtr->internalRep.otherValuePtr = (VOID *) codePtr;
+    objPtr->typePtr = &tclByteCodeType;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetCmdLocEncodingSize --
+ *
+ *	Computes the total number of bytes needed to encode the command
+ *	location information for some compiled code.
+ *
+ * Results:
+ *	The byte count needed to encode the compiled location information.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetCmdLocEncodingSize(envPtr)
+     CompileEnv *envPtr;	/* Points to compilation environment
+				 * structure containing the CmdLocation
+				 * structure to encode. */
+{
+    register CmdLocation *mapPtr = envPtr->cmdMapPtr;
+    int numCmds = envPtr->numCommands;
+    int codeDelta, codeLen, srcDelta, srcLen;
+    int codeDeltaNext, codeLengthNext, srcDeltaNext, srcLengthNext;
+				/* The offsets in their respective byte
+				 * sequences where the next encoded offset
+				 * or length should go. */
+    int prevCodeOffset, prevSrcOffset, i;
+
+    codeDeltaNext = codeLengthNext = srcDeltaNext = srcLengthNext = 0;
+    prevCodeOffset = prevSrcOffset = 0;
+    for (i = 0;  i < numCmds;  i++) {
+	codeDelta = (mapPtr[i].codeOffset - prevCodeOffset);
+	if (codeDelta < 0) {
+	    panic("GetCmdLocEncodingSize: bad code offset");
+	} else if (codeDelta <= 127) {
+	    codeDeltaNext++;
+	} else {
+	    codeDeltaNext += 5;	 /* 1 byte for 0xFF, 4 for positive delta */
+	}
+	prevCodeOffset = mapPtr[i].codeOffset;
+
+	codeLen = mapPtr[i].numCodeBytes;
+	if (codeLen < 0) {
+	    panic("GetCmdLocEncodingSize: bad code length");
+	} else if (codeLen <= 127) {
+	    codeLengthNext++;
+	} else {
+	    codeLengthNext += 5; /* 1 byte for 0xFF, 4 for length */
+	}
+
+	srcDelta = (mapPtr[i].srcOffset - prevSrcOffset);
+	if ((-127 <= srcDelta) && (srcDelta <= 127)) {
+	    srcDeltaNext++;
+	} else {
+	    srcDeltaNext += 5;	 /* 1 byte for 0xFF, 4 for delta */
+	}
+	prevSrcOffset = mapPtr[i].srcOffset;
+
+	srcLen = mapPtr[i].numSrcChars;
+	if (srcLen < 0) {
+	    panic("GetCmdLocEncodingSize: bad source length");
+	} else if (srcLen <= 127) {
+	    srcLengthNext++;
+	} else {
+	    srcLengthNext += 5;	 /* 1 byte for 0xFF, 4 for length */
+	}
+    }
+
+    return (codeDeltaNext + codeLengthNext + srcDeltaNext + srcLengthNext);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EncodeCmdLocMap --
+ *
+ *	Encode the command location information for some compiled code into
+ *	a ByteCode structure. The encoded command location map is stored as
+ *	three adjacent byte sequences.
+ *
+ * Results:
+ *	Pointer to the first byte after the encoded command location
+ *	information.
+ *
+ * Side effects:
+ *	The encoded information is stored into the block of memory headed
+ *	by codePtr. Also records pointers to the start of the four byte
+ *	sequences in fields in codePtr's ByteCode header structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static unsigned char *
+EncodeCmdLocMap(envPtr, codePtr, startPtr)
+     CompileEnv *envPtr;	/* Points to compilation environment
+				 * structure containing the CmdLocation
+				 * structure to encode. */
+     ByteCode *codePtr;		/* ByteCode in which to encode envPtr's
+				 * command location information. */
+     unsigned char *startPtr;	/* Points to the first byte in codePtr's
+				 * memory block where the location
+				 * information is to be stored. */
+{
+    register CmdLocation *mapPtr = envPtr->cmdMapPtr;
+    int numCmds = envPtr->numCommands;
+    register unsigned char *p = startPtr;
+    int codeDelta, codeLen, srcDelta, srcLen, prevOffset;
+    register int i;
+    
+    /*
+     * Encode the code offset for each command as a sequence of deltas.
+     */
+
+    codePtr->codeDeltaStart = p;
+    prevOffset = 0;
+    for (i = 0;  i < numCmds;  i++) {
+	codeDelta = (mapPtr[i].codeOffset - prevOffset);
+	if (codeDelta < 0) {
+	    panic("EncodeCmdLocMap: bad code offset");
+	} else if (codeDelta <= 127) {
+	    TclStoreInt1AtPtr(codeDelta, p);
+	    p++;
+	} else {
+	    TclStoreInt1AtPtr(0xFF, p);
+	    p++;
+	    TclStoreInt4AtPtr(codeDelta, p);
+	    p += 4;
+	}
+	prevOffset = mapPtr[i].codeOffset;
+    }
+
+    /*
+     * Encode the code length for each command.
+     */
+
+    codePtr->codeLengthStart = p;
+    for (i = 0;  i < numCmds;  i++) {
+	codeLen = mapPtr[i].numCodeBytes;
+	if (codeLen < 0) {
+	    panic("EncodeCmdLocMap: bad code length");
+	} else if (codeLen <= 127) {
+	    TclStoreInt1AtPtr(codeLen, p);
+	    p++;
+	} else {
+	    TclStoreInt1AtPtr(0xFF, p);
+	    p++;
+	    TclStoreInt4AtPtr(codeLen, p);
+	    p += 4;
+	}
+    }
+
+    /*
+     * Encode the source offset for each command as a sequence of deltas.
+     */
+
+    codePtr->srcDeltaStart = p;
+    prevOffset = 0;
+    for (i = 0;  i < numCmds;  i++) {
+	srcDelta = (mapPtr[i].srcOffset - prevOffset);
+	if ((-127 <= srcDelta) && (srcDelta <= 127)) {
+	    TclStoreInt1AtPtr(srcDelta, p);
+	    p++;
+	} else {
+	    TclStoreInt1AtPtr(0xFF, p);
+	    p++;
+	    TclStoreInt4AtPtr(srcDelta, p);
+	    p += 4;
+	}
+	prevOffset = mapPtr[i].srcOffset;
+    }
+
+    /*
+     * Encode the source length for each command.
+     */
+
+    codePtr->srcLengthStart = p;
+    for (i = 0;  i < numCmds;  i++) {
+	srcLen = mapPtr[i].numSrcChars;
+	if (srcLen < 0) {
+	    panic("EncodeCmdLocMap: bad source length");
+	} else if (srcLen <= 127) {
+	    TclStoreInt1AtPtr(srcLen, p);
+	    p++;
+	} else {
+	    TclStoreInt1AtPtr(0xFF, p);
+	    p++;
+	    TclStoreInt4AtPtr(srcLen, p);
+	    p += 4;
+	}
+    }
+    
+    return p;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileString --
+ *
+ *	Compile a Tcl script in a null-terminated binary string.
+ *
+ * Results:
+ *	The return value is TCL_OK on a successful compilation and TCL_ERROR
+ *	on failure. If TCL_ERROR is returned, then the interpreter's result
+ *	contains an error message.
+ *
+ *	envPtr->termOffset and interp->termOffset are filled in with the
+ *	offset of the character in the string just after the last one
+ *	successfully processed; this might be the offset of the ']' (if
+ *	flags & TCL_BRACKET_TERM), or the offset of the '\0' at the end of
+ *	the string. Also updates envPtr->maxStackDepth with the maximum
+ *	number of stack elements needed to execute the string's commands.
+ *
+ * Side effects:
+ *	Adds instructions to envPtr to evaluate the string at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileString(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    char *string;		/* The source string to compile. */
+    char *lastChar;		/* Pointer to terminating character of
+				 * string. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    Interp *iPtr = (Interp *) interp;
+    register char *src = string;/* Points to current source char. */
+    register char c = *src;	/* The current char. */
+    register int type;		/* Current char's CHAR_TYPE type. */
+    char termChar = (char)((flags & TCL_BRACKET_TERM)? ']' : '\0');
+				/* Return when this character is found
+				 * (either ']' or '\0'). Zero means newlines
+				 * terminate cmds. */
+    int isFirstCmd = 1;		/* 1 if compiling the first cmd. */
+    char *cmdSrcStart = NULL;	/* Points to first non-blank char in each
+ 				 * command. Initialized to avoid compiler
+ 				 * warning. */
+    int cmdIndex;		/* The index of the current command in the
+ 				 * compilation environment's command
+ 				 * location table. */
+    int lastTopLevelCmdIndex = -1;
+    				/* Index of most recent toplevel command in
+ 				 * the command location table. Initialized
+				 * to avoid compiler warning. */
+    int cmdCodeOffset = -1;	/* Offset of first byte of current command's
+ 				 * code. Initialized to avoid compiler
+ 				 * warning. */
+    int cmdWords;		/* Number of words in current command. */
+    Tcl_Command cmd;		/* Used to search for commands. */
+    Command *cmdPtr;		/* Points to command's Command structure if
+				 * first word is simple and command was
+				 * found; else NULL. */
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute all cmds. */
+    char *termPtr;		/* Points to char that terminated word. */
+    char savedChar;		/* Holds the character from string
+				 * termporarily replaced by a null character
+				 * during processing of words. */
+    int objIndex = -1;		/* The object array index for a pushed
+ 				 * object holding a word or word part
+ 				 * Initialized to avoid compiler warning. */
+    unsigned char *entryCodeNext = envPtr->codeNext;
+    				/* Value of envPtr's current instruction
+				 * pointer at entry. Used to tell if any
+				 * instructions generated. */
+    char *ellipsis = "";	/* Used to set errorInfo variable; "..."
+				 * indicates that not all of offending
+				 * command is included in errorInfo. ""
+				 * means that the command is all there. */
+    Tcl_Obj *objPtr;
+    int numChars;
+    int result = TCL_OK;
+    int savePushSimpleWords = envPtr->pushSimpleWords;
+
+    /*
+     * commands: command {(';' | '\n') command}
+     */
+
+    while ((src != lastChar) && (c != termChar)) {
+	/*
+	 * Skip white space, semicolons, backslash-newlines (treated as
+	 * spaces), and comments before command.
+	 */
+
+	type = CHAR_TYPE(src, lastChar);
+	while ((type & (TCL_SPACE | TCL_BACKSLASH))
+	        || (c == '\n') || (c == ';')) {
+	    if (type == TCL_BACKSLASH) {
+		if (src[1] == '\n') {
+		    src += 2;
+		} else {
+		    break;
+		}
+	    } else {
+		src++;
+	    }
+	    c = *src;
+	    type = CHAR_TYPE(src, lastChar);
+	}
+
+	if (c == '#') {
+	    while (src != lastChar) {
+		if (c == '\\') {
+		    int numRead;
+		    Tcl_Backslash(src, &numRead);
+		    src += numRead;
+		} else if (c == '\n') {
+		    src++;
+		    c = *src;
+		    envPtr->termOffset = (src - string);
+		    break;
+		} else {
+		    src++;
+		}
+		c = *src;
+	    }
+	    continue;	/* end of comment, restart outer command loop */
+	}
+
+	/*
+	 * Compile one command: zero or more words terminated by a '\n',
+	 * ';', ']' (if command is terminated by close bracket), or
+	 * the end of string.
+	 *
+	 * command: word*
+	 */
+
+	type = CHAR_TYPE(src, lastChar);
+	if ((type == TCL_COMMAND_END) 
+	        && ((c != ']') || (flags & TCL_BRACKET_TERM))) {
+	    continue;  /* empty command; restart outer cmd loop */
+	}
+
+	/*
+	 * If not the first command, discard the previous command's result.
+	 */
+	
+	if (!isFirstCmd) {
+	    TclEmitOpcode(INST_POP, envPtr);
+	    if (!(flags & TCL_BRACKET_TERM)) {
+		/*
+		 * We are compiling a top level command. Update the number
+		 * of code bytes for the last command to account for the pop
+		 * instruction.
+		 */
+		
+	        (envPtr->cmdMapPtr[lastTopLevelCmdIndex]).numCodeBytes =
+		    (envPtr->codeNext-envPtr->codeStart) - cmdCodeOffset;
+	    }
+	}
+
+	/*
+	 * Compile the words of the command. Process the first word
+	 * specially, since it is the name of a command. If it is a "simple"
+	 * string (just a sequence of characters), look it up in the table
+	 * of compilation procedures. If a word other than the first is
+	 * simple and represents an integer whose formatted representation
+	 * is the same as the word, just push an integer object. Also record
+	 * starting source and object information for the command.
+	 */
+
+	envPtr->numCommands++;
+	cmdIndex = (envPtr->numCommands - 1);
+	if (!(flags & TCL_BRACKET_TERM)) {
+	    lastTopLevelCmdIndex = cmdIndex;
+	}
+	
+	cmdSrcStart = src;
+	cmdCodeOffset = (envPtr->codeNext - envPtr->codeStart);
+	cmdWords = 0;
+	EnterCmdStartData(envPtr, cmdIndex, src-envPtr->source,
+		cmdCodeOffset);
+	    
+	if ((!(flags & TCL_BRACKET_TERM))
+	        && (tclTraceCompile >= 1) && (envPtr->procPtr == NULL)) {
+	    /*
+	     * Display a line summarizing the top level command we are about
+	     * to compile.
+	     */
+	    
+	    char *p = cmdSrcStart;
+	    int numChars, complete;
+	    
+	    while ((CHAR_TYPE(p, lastChar) != TCL_COMMAND_END)
+		   || ((*p == ']') && !(flags & TCL_BRACKET_TERM))) {
+		p++;
+	    }
+	    numChars = (p - cmdSrcStart);
+	    complete = 1;
+	    if (numChars > 60) {
+		numChars = 60;
+		complete = 0;
+	    } else if ((numChars >= 2) && (*p == '\n') && (*(p-1) == '{')) {
+		complete = 0;
+	    }
+	    fprintf(stdout, "Compiling: %.*s%s\n",
+		    numChars, cmdSrcStart, (complete? "" : " ..."));
+	}
+	
+	while ((type != TCL_COMMAND_END)
+	        || ((c == ']') && !(flags & TCL_BRACKET_TERM))) {
+	    /*
+	     * Skip any leading white space at the start of a word. Note
+	     * that a backslash-newline is treated as a space.
+	     */
+
+	    while (type & (TCL_SPACE | TCL_BACKSLASH)) {
+		if (type == TCL_BACKSLASH) {
+		    if (src[1] == '\n') {
+			src += 2;
+		    } else {
+			break;
+		    }
+		} else {
+		    src++;
+		}
+		c = *src;
+		type = CHAR_TYPE(src, lastChar);
+	    }
+	    if ((type == TCL_COMMAND_END) 
+	            && ((c != ']') || (flags & TCL_BRACKET_TERM))) {
+		break;		/* no words remain for command. */
+	    }
+
+	    /*
+	     * Compile one word. We use an inline version of CompileWord to
+	     * avoid an extra procedure call.
+	     */
+
+	    envPtr->pushSimpleWords = 0;
+	    if (type & (TCL_QUOTE | TCL_OPEN_BRACE)) {
+		src++;
+		if (type == TCL_QUOTE) {
+		    result = TclCompileQuotes(interp, src, lastChar,
+			    '"', flags, envPtr);
+		} else {
+		    result = CompileBraces(interp, src, lastChar,
+			    flags, envPtr);
+		}
+		termPtr = (src + envPtr->termOffset);
+		if (result != TCL_OK) {
+		    src = termPtr;
+		    goto done;
+		}
+
+		/*
+		 * Make sure terminating character of the quoted or braced
+		 * string is the end of word.
+		 */
+		
+		c = *termPtr;
+		if ((c == '\\') && (*(termPtr+1) == '\n')) {
+		    /*
+		     * Line is continued on next line; the backslash-
+		     * newline turns into space, which terminates the word.
+		     */
+		} else {
+		    type = CHAR_TYPE(termPtr, lastChar);
+		    if ((type != TCL_SPACE) && (type != TCL_COMMAND_END)) {
+			Tcl_ResetResult(interp);
+			if (*(src-1) == '"') {
+			    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+				    "extra characters after close-quote", -1);
+			} else {
+			    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+				    "extra characters after close-brace", -1);
+			}
+			result = TCL_ERROR;
+		    }
+		}
+	    } else {
+		result = CompileMultipartWord(interp, src, lastChar,
+			flags, envPtr);
+		termPtr = (src + envPtr->termOffset);
+	    }
+	    if (result != TCL_OK) {
+		ellipsis = "...";
+		src = termPtr;
+		goto done;
+	    }
+	    
+	    if (envPtr->wordIsSimple) {
+		/*
+		 * A simple word. Temporarily replace the terminating
+		 * character with a null character.
+		 */
+		
+		numChars = envPtr->numSimpleWordChars;
+		savedChar = src[numChars];
+		src[numChars] = '\0';
+
+		if ((cmdWords == 0)
+		        && (!(iPtr->flags & DONT_COMPILE_CMDS_INLINE))) {
+		    /*
+		     * The first word of a command and inline command
+		     * compilation has not been disabled (e.g., by command
+		     * traces). Look up the first word in the interpreter's
+		     * hashtable of commands. If a compilation procedure is
+		     * found, let it compile the command after resetting
+		     * error logging information. Note that if we are
+		     * compiling a procedure, we must look up the command
+		     * in the procedure's namespace and not the current
+		     * namespace.
+		     */
+
+		    Namespace *cmdNsPtr;
+
+		    if (envPtr->procPtr != NULL) {
+			cmdNsPtr = envPtr->procPtr->cmdPtr->nsPtr;
+		    } else {
+			cmdNsPtr = NULL;
+		    }
+
+		    cmdPtr = NULL;
+		    cmd = Tcl_FindCommand(interp, src,
+			    (Tcl_Namespace *) cmdNsPtr, /*flags*/ 0);
+                    if (cmd != (Tcl_Command) NULL) {
+                        cmdPtr = (Command *) cmd;
+                    }
+		    if ((cmdPtr != NULL) && (cmdPtr->compileProc != NULL)) {
+			char *firstArg = termPtr;
+			src[numChars] = savedChar;
+			iPtr->flags &= ~(ERR_ALREADY_LOGGED | ERR_IN_PROGRESS
+					 | ERROR_CODE_SET);
+			result = (*(cmdPtr->compileProc))(interp,
+				firstArg, lastChar, flags, envPtr);
+			if (result == TCL_OK) {
+			    src = (firstArg + envPtr->termOffset);
+			    maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
+			    goto finishCommand;
+			} else if (result == TCL_OUT_LINE_COMPILE) {
+			    result = TCL_OK;
+			    src[numChars] = '\0';
+			} else {
+			    src = firstArg;
+			    goto done;           /* an error */
+			}
+		    }
+
+		    /*
+		     * No compile procedure was found for the command: push
+		     * the word and continue to compile the remaining
+		     * words. If a hashtable entry was found for the
+		     * command, push a CmdName object instead to avoid
+		     * runtime lookups. If necessary, convert the pushed
+		     * object to be a CmdName object. If this is the first
+		     * CmdName object in this code unit that refers to the
+		     * command, increment the reference count in the
+		     * Command structure to reflect the new reference from
+		     * the CmdName object and, if the command is deleted
+		     * later, to keep the Command structure from being freed
+		     * until TclExecuteByteCode has a chance to recognize
+		     * that the command was deleted.
+		     */
+
+		    objIndex = TclObjIndexForString(src, numChars,
+			    /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr);
+		    if (cmdPtr != NULL) {
+			objPtr = envPtr->objArrayPtr[objIndex];
+			if ((objPtr->typePtr != &tclCmdNameType)
+			        && (objPtr->bytes != NULL)) {
+			    ResolvedCmdName *resPtr = (ResolvedCmdName *)
+                                    ckalloc(sizeof(ResolvedCmdName));
+                            Namespace *nsPtr = (Namespace *) 
+				    Tcl_GetCurrentNamespace(interp);
+
+                            resPtr->cmdPtr = cmdPtr;
+                            resPtr->refNsPtr = nsPtr;
+			    resPtr->refNsId = nsPtr->nsId;
+                            resPtr->refNsCmdEpoch = nsPtr->cmdRefEpoch;
+                            resPtr->cmdEpoch = cmdPtr->cmdEpoch;
+                            resPtr->refCount = 1;
+			    objPtr->internalRep.twoPtrValue.ptr1 =
+				(VOID *) resPtr;
+			    objPtr->internalRep.twoPtrValue.ptr2 = NULL;
+                            objPtr->typePtr = &tclCmdNameType;
+			    cmdPtr->refCount++;
+			}
+		    }
+		} else {
+		    /*
+		     * See if the word represents an integer whose formatted
+		     * representation is the same as the word (e.g., this is
+		     * true for 123 and -1 but not for 00005). If so, just
+		     * push an integer object.
+		     */
+
+		    int isCompilableInt = 0;
+		    long n;
+		    char buf[40];
+		    
+		    if (TclLooksLikeInt(src)) {
+			int code = TclGetLong(interp, src, &n);
+			if (code == TCL_OK) {
+			    TclFormatInt(buf, n);
+			    if (strcmp(src, buf) == 0) {
+				isCompilableInt = 1;
+				objIndex = TclObjIndexForString(src,
+					numChars, /*allocStrRep*/ 0,
+					/*inHeap*/ 0, envPtr);
+				objPtr = envPtr->objArrayPtr[objIndex];
+
+				Tcl_InvalidateStringRep(objPtr);
+				objPtr->internalRep.longValue = n;
+				objPtr->typePtr = &tclIntType;
+			    }
+			} else {
+			    Tcl_ResetResult(interp);
+			}
+		    }
+		    if (!isCompilableInt) {
+			objIndex = TclObjIndexForString(src, numChars,
+			        /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr);
+		    }
+		}
+		src[numChars] = savedChar;
+		TclEmitPush(objIndex, envPtr);
+		maxDepth = TclMax((cmdWords + 1), maxDepth);
+	    } else {		/* not a simple word */
+		maxDepth = TclMax((cmdWords + envPtr->maxStackDepth),
+			       maxDepth);
+	    }
+	    src = termPtr;
+	    c = *src;
+	    type = CHAR_TYPE(src, lastChar);
+	    cmdWords++;
+	}
+	
+	/*
+	 * Emit an invoke instruction for the command. If a compile command
+	 * was found for the command we called it and skipped this.
+	 */
+
+	if (cmdWords > 0) {
+	    if (cmdWords <= 255) {
+	        TclEmitInstUInt1(INST_INVOKE_STK1, cmdWords, envPtr);
+            } else {
+	        TclEmitInstUInt4(INST_INVOKE_STK4, cmdWords, envPtr);
+            }
+	}
+
+	/*
+	 * Update the compilation environment structure. Record
+	 * source/object information for the command.
+	 */
+
+        finishCommand:
+	EnterCmdExtentData(envPtr, cmdIndex, src-cmdSrcStart,
+	        (envPtr->codeNext-envPtr->codeStart) - cmdCodeOffset);
+	
+	isFirstCmd = 0;
+	envPtr->termOffset = (src - string);
+	c = *src;
+    }
+
+    done:
+    if (result == TCL_OK) {
+	/*
+	 * If the source string yielded no instructions (e.g., if it was
+	 * empty), push an empty string object as the command's result.
+	 */
+    
+	if (entryCodeNext == envPtr->codeNext) {
+	    int objIndex = TclObjIndexForString("", 0, /*allocStrRep*/ 0,
+                                                /*inHeap*/ 0, envPtr);
+	    TclEmitPush(objIndex, envPtr);
+	    maxDepth = 1;
+	}
+    } else {
+	/*
+	 * Add additional error information. First compute the line number
+	 * where the error occurred.
+	 */
+
+	register char *p;
+	int numChars;
+	char buf[200];
+
+	iPtr->errorLine = 1;
+	for (p = string;  p != cmdSrcStart;  p++) {
+	    if (*p == '\n') {
+		iPtr->errorLine++;
+	    }
+	}
+	for (  ; isspace(UCHAR(*p)) || (*p == ';');  p++) {
+	    if (*p == '\n') {
+		iPtr->errorLine++;
+	    }
+	}
+
+	/*
+	 * Figure out how much of the command to print (up to a certain
+	 * number of characters, or up to the end of the command).
+	 */
+
+	p = cmdSrcStart;
+	while ((CHAR_TYPE(p, lastChar) != TCL_COMMAND_END)
+		|| ((*p == ']') && !(flags & TCL_BRACKET_TERM))) {
+	    p++;
+	}
+	numChars = (p - cmdSrcStart);
+	if (numChars > 150) {
+	    numChars = 150;
+	    ellipsis = " ...";
+	} else if ((numChars >= 2) && (*p == '\n') && (*(p-1) == '{')) {
+	    ellipsis = " ...";
+	}
+	
+	sprintf(buf, "\n    while compiling\n\"%.*s%s\"",
+		numChars, cmdSrcStart, ellipsis);
+	Tcl_AddObjErrorInfo(interp, buf, -1);
+    } 
+	
+    envPtr->termOffset = (src - string);
+    iPtr->termOffset = envPtr->termOffset;
+    envPtr->maxStackDepth = maxDepth;
+    envPtr->pushSimpleWords = savePushSimpleWords;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileWord --
+ *
+ *	This procedure compiles one word from a command string. It skips
+ *	any leading white space.
+ *
+ *	Ordinarily, callers set envPtr->pushSimpleWords to 1 and this
+ *	procedure emits push and other instructions to compute the
+ *	word on the Tcl evaluation stack at execution time. If a caller sets
+ *	envPtr->pushSimpleWords to 0, CompileWord will _not_ compile
+ *	"simple" words: words that are just a sequence of characters without
+ *	backslashes. It will leave their compilation up to the caller.
+ *
+ *	As an important special case, if the word is simple, this procedure
+ *	sets envPtr->wordIsSimple to 1 and envPtr->numSimpleWordChars to the
+ *	number of characters in the simple word. This allows the caller to
+ *	process these words specially.
+ *
+ * Results:
+ *	The return value is a standard Tcl result. If an error occurs, an
+ *	error message is left in the interpreter's result.
+ *	
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one successfully processed in the last
+ *	word. This is normally the character just after the last one in a
+ *	word (perhaps the command terminator), or the vicinity of an error
+ *	(if the result is not TCL_OK).
+ *
+ *	envPtr->wordIsSimple is set 1 if the word is simple: just a
+ *	sequence of characters without backslashes. If so, the word's
+ *	characters are the envPtr->numSimpleWordChars characters starting 
+ *	at string.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to evaluate the word. This is not changed if
+ *	the word is simple and envPtr->pushSimpleWords was 0 (false).
+ *
+ * Side effects:
+ *	Instructions are added to envPtr to compute and push the word
+ *	at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileWord(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		/* Interpreter to use for nested command
+				 * evaluations and error messages. */
+    char *string;		/* First character of word. */
+    char *lastChar;		 /* Pointer to terminating character of
+				  * string. */
+    int flags;			/* Flags to control compilation (same values
+				 * passed to Tcl_EvalObj). */
+    CompileEnv *envPtr;		/* Holds the resulting instructions. */
+{
+    /*
+     * Compile one word: approximately
+     *
+     * word:             quoted_string | braced_string | multipart_word
+     * quoted_string:    '"' char* '"'
+     * braced_string:    '{' char* '}'
+     * multipart_word    (see CompileMultipartWord below)
+     */
+    
+    register char *src = string; /* Points to current source char. */
+    register int type = CHAR_TYPE(src, lastChar);
+				 /* Current char's CHAR_TYPE type. */
+    int maxDepth = 0;		 /* Maximum number of stack elements needed
+				  * to compute and push the word. */
+    char *termPtr = src;	 /* Points to the character that terminated
+				  * the word. */
+    int result = TCL_OK;
+
+    /*
+     * Skip any leading white space at the start of a word. Note that a
+     * backslash-newline is treated as a space.
+     */
+
+    while (type & (TCL_SPACE | TCL_BACKSLASH)) {
+	if (type == TCL_BACKSLASH) {
+	    if (src[1] == '\n') {
+		src += 2;
+	    } else {
+		break;		/* no longer white space */
+	    }
+	} else {
+	    src++;
+	}
+	type = CHAR_TYPE(src, lastChar);
+    }
+    if (type == TCL_COMMAND_END) {
+	goto done;
+    }
+
+    /*
+     * Compile the word. Handle quoted and braced string words here in order
+     * to avoid an extra procedure call.
+     */
+
+    if (type & (TCL_QUOTE | TCL_OPEN_BRACE)) {
+	src++;
+	if (type == TCL_QUOTE) {
+	    result = TclCompileQuotes(interp, src, lastChar, '"', flags,
+		    envPtr);
+	} else {
+	    result = CompileBraces(interp, src, lastChar, flags, envPtr);
+	}
+	termPtr = (src + envPtr->termOffset);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	
+	/*
+	 * Make sure terminating character of the quoted or braced string is
+	 * the end of word.
+	 */
+	
+	if ((*termPtr == '\\') && (*(termPtr+1) == '\n')) {
+	    /*
+	     * Line is continued on next line; the backslash-newline turns
+	     * into space, which terminates the word.
+	     */
+	} else {
+	    type = CHAR_TYPE(termPtr, lastChar);
+	    if (!(type & (TCL_SPACE | TCL_COMMAND_END))) {
+		Tcl_ResetResult(interp);
+		if (*(src-1) == '"') {
+		    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		            "extra characters after close-quote", -1);
+		} else {
+		    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+			    "extra characters after close-brace", -1);
+		}
+		result = TCL_ERROR;
+		goto done;
+	    }
+	}
+	maxDepth = envPtr->maxStackDepth;
+    } else {
+	result = CompileMultipartWord(interp, src, lastChar, flags, envPtr);
+	termPtr = (src + envPtr->termOffset);
+	maxDepth = envPtr->maxStackDepth;
+    }
+
+    /*
+     * Done processing the word. The values of envPtr->wordIsSimple and
+     * envPtr->numSimpleWordChars are left at the values returned by
+     * TclCompileQuotes/Braces/MultipartWord.
+     */
+    
+    done:
+    envPtr->termOffset = (termPtr - string);
+    envPtr->maxStackDepth = maxDepth;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileMultipartWord --
+ *
+ *	This procedure compiles one multipart word: a word comprised of some
+ *	number of nested commands, variable references, or arbitrary
+ *	characters. This procedure assumes that quoted string and braced
+ *	string words and the end of command have already been handled by its
+ *	caller. It also assumes that any leading white space has already
+ *	been consumed.
+ *
+ *	Ordinarily, callers set envPtr->pushSimpleWords to 1 and this
+ *	procedure emits push and other instructions to compute the word on
+ *	the Tcl evaluation stack at execution time. If a caller sets
+ *	envPtr->pushSimpleWords to 0, it will _not_ compile "simple" words:
+ *	words that are just a sequence of characters without backslashes.
+ *	It will leave their compilation up to the caller. This is done, for
+ *	example, to provide special support for the first word of commands,
+ *	which are almost always the (simple) name of a command.
+ *
+ *	As an important special case, if the word is simple, this procedure
+ *	sets envPtr->wordIsSimple to 1 and envPtr->numSimpleWordChars to the
+ *	number of characters in the simple word. This allows the caller to
+ *	process these words specially.
+ *
+ * Results:
+ *	The return value is a standard Tcl result. If an error occurs, an
+ *	error message is left in the interpreter's result.
+ *	
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one successfully processed in the last
+ *	word. This is normally the character just after the last one in a
+ *	word (perhaps the command terminator), or the vicinity of an error
+ *	(if the result is not TCL_OK).
+ *
+ *	envPtr->wordIsSimple is set 1 if the word is simple: just a
+ *	sequence of characters without backslashes. If so, the word's
+ *	characters are the envPtr->numSimpleWordChars characters starting 
+ *	at string.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to evaluate the word. This is not changed if
+ *	the word is simple and envPtr->pushSimpleWords was 0 (false).
+ *
+ * Side effects:
+ *	Instructions are added to envPtr to compute and push the word
+ *	at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileMultipartWord(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		/* Interpreter to use for nested command
+				 * evaluations and error messages. */
+    char *string;		/* First character of word. */
+    char *lastChar;		 /* Pointer to terminating character of
+				  * string. */
+    int flags;			/* Flags to control compilation (same values
+				 * passed to Tcl_EvalObj). */
+    CompileEnv *envPtr;		/* Holds the resulting instructions. */
+{
+    /*
+     * Compile one multi_part word:
+     *
+     * multi_part_word:  word_part+
+     * word_part:        nested_cmd | var_reference | char+
+     * nested_cmd:       '[' command ']'
+     * var_reference:    '$' name | '$' name '(' index_string ')' |
+     *                   '$' '{' braced_name '}')
+     * name:             (letter | digit | underscore)+
+     * braced_name:      (non_close_brace_char)*
+     * index_string:     (non_close_paren_char)*
+     */
+    
+    register char *src = string; /* Points to current source char. */
+    register char c = *src;	/* The current char. */
+    register int type;		/* Current char's CHAR_TYPE type. */
+    int bracketNormal = !(flags & TCL_BRACKET_TERM);
+    int simpleWord = 0;		/* Set 1 if word is simple. */
+    int numParts = 0;		/* Count of word_part objs pushed. */
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to compute and push the word. */
+    char *start;		/* Starting position of char+ word_part. */
+    int hasBackslash;		/* Nonzero if '\' in char+ word_part. */
+    int numChars;		/* Number of chars in char+ word_part. */
+    char savedChar;		/* Holds the character from string
+				 * termporarily replaced by a null character
+				 * during word_part processing. */
+    int objIndex;		/* The object array index for a pushed
+				 * object holding a word_part. */
+    int savePushSimpleWords = envPtr->pushSimpleWords;
+    int result = TCL_OK;
+    int numRead;
+
+    type = CHAR_TYPE(src, lastChar);
+    while (1) {
+	/*
+	 * Process a word_part: a sequence of chars, a var reference, or
+	 * a nested command.
+	 */
+
+	if ((type & (TCL_NORMAL | TCL_CLOSE_BRACE | TCL_BACKSLASH |
+		     TCL_QUOTE | TCL_OPEN_BRACE)) ||
+	    ((c == ']') && bracketNormal)) {
+	    /*
+	     * A char+ word part. Scan first looking for any backslashes.
+	     * Note that a backslash-newline must be treated as a word
+	     * separator, as if the backslash-newline had been collapsed
+	     * before command parsing began.
+	     */
+	    
+	    start = src;
+	    hasBackslash = 0;
+	    do {
+		if (type == TCL_BACKSLASH) {
+		    hasBackslash = 1;
+		    Tcl_Backslash(src, &numRead);
+		    if (src[1] == '\n') {
+			src += numRead;
+			type = TCL_SPACE; /* force word end */
+			break;
+		    }
+		    src += numRead;
+		} else {
+		    src++;
+		}
+		c = *src;
+		type = CHAR_TYPE(src, lastChar);
+	    } while (type & (TCL_NORMAL | TCL_BACKSLASH | TCL_QUOTE |
+			    TCL_OPEN_BRACE | TCL_CLOSE_BRACE)
+			    || ((c == ']') && bracketNormal));
+
+	    if ((numParts == 0) && !hasBackslash
+		    && (type & (TCL_SPACE | TCL_COMMAND_END))) {
+		/*
+		 * The word is "simple": just a sequence of characters
+		 * without backslashes terminated by a TCL_SPACE or
+		 * TCL_COMMAND_END. Just return if we are not to compile
+		 * simple words.
+		 */
+
+		simpleWord = 1;
+		if (!envPtr->pushSimpleWords) {
+		    envPtr->wordIsSimple = 1;
+		    envPtr->numSimpleWordChars = (src - string);
+		    envPtr->termOffset = envPtr->numSimpleWordChars;
+		    envPtr->pushSimpleWords = savePushSimpleWords;
+		    return TCL_OK;
+		}
+	    }
+
+	    /*
+	     * Create and push a string object for the char+ word_part,
+	     * which starts at "start" and ends at the char just before
+	     * src. If backslashes were found, copy the word_part's
+	     * characters with substituted backslashes into a heap-allocated
+	     * buffer and use it to create the string object. Temporarily
+	     * replace the terminating character with a null character.
+	     */
+
+	    numChars = (src - start);
+	    savedChar = start[numChars];
+	    start[numChars] = '\0';
+	    if ((numChars > 0) && (hasBackslash)) {
+		char *buffer = ckalloc((unsigned) numChars + 1);
+		register char *dst = buffer;
+		register char *p = start;
+		while (p < src) {
+		    if (*p == '\\') {	
+			*dst = Tcl_Backslash(p, &numRead);
+			if (p[1] == '\n') {
+			    break;
+			}
+			p += numRead;
+			dst++;
+		    } else {
+			*dst++ = *p++;
+		    }
+		}
+		*dst = '\0';
+		objIndex = TclObjIndexForString(buffer, dst-buffer,
+			/*allocStrRep*/ 1, /*inHeap*/ 1, envPtr);
+	    } else {
+		objIndex = TclObjIndexForString(start, numChars,
+			/*allocStrRep*/ 1, /*inHeap*/ 0, envPtr);
+	    }
+	    start[numChars] = savedChar;
+	    TclEmitPush(objIndex, envPtr);
+	    maxDepth = TclMax((numParts + 1), maxDepth);
+	} else if (type == TCL_DOLLAR) {
+	    result = TclCompileDollarVar(interp, src, lastChar,
+		    flags, envPtr);
+	    src += envPtr->termOffset;
+	    if (result != TCL_OK) {
+		goto done;
+	    }
+	    maxDepth = TclMax((numParts + envPtr->maxStackDepth), maxDepth);
+	    c = *src;
+	    type = CHAR_TYPE(src, lastChar);
+	} else if (type == TCL_OPEN_BRACKET) {
+	    char *termPtr;
+	    envPtr->pushSimpleWords = 1;
+	    src++;
+	    result = TclCompileString(interp, src, lastChar,
+				      (flags | TCL_BRACKET_TERM), envPtr);
+	    termPtr = (src + envPtr->termOffset);
+	    if (*termPtr == ']') {
+		termPtr++;
+	    } else if (*termPtr == '\0') {
+		/*
+		 * Missing ] at end of nested command.
+		 */
+		
+		Tcl_ResetResult(interp);
+		Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		        "missing close-bracket", -1);
+		result = TCL_ERROR;
+	    }
+	    src = termPtr;
+	    if (result != TCL_OK) {
+		goto done;
+	    }
+	    maxDepth = TclMax((numParts + envPtr->maxStackDepth), maxDepth);
+	    c = *src;
+	    type = CHAR_TYPE(src, lastChar);
+	} else if (type & (TCL_SPACE | TCL_COMMAND_END)) {
+	    goto wordEnd;
+	}
+	numParts++;
+    } /* end of infinite loop */
+
+    wordEnd:
+    /*
+     * End of a non-simple word: TCL_SPACE, TCL_COMMAND_END, or
+     * backslash-newline. Concatenate the word_parts if necessary.
+     */
+
+    while (numParts > 255) {
+	TclEmitInstUInt1(INST_CONCAT1, 255, envPtr);
+	numParts -= 254;  /* concat pushes 1 obj, the result */
+    }
+    if (numParts > 1) {
+	TclEmitInstUInt1(INST_CONCAT1, numParts, envPtr);
+    }
+
+    done:
+    if (simpleWord) {
+	envPtr->wordIsSimple = 1;
+	envPtr->numSimpleWordChars = (src - string);
+    } else {
+	envPtr->wordIsSimple = 0;
+	envPtr->numSimpleWordChars = 0;
+    }
+    envPtr->termOffset = (src - string);
+    envPtr->maxStackDepth = maxDepth;
+    envPtr->pushSimpleWords = savePushSimpleWords;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileQuotes --
+ *
+ *	This procedure compiles a double-quoted string such as a quoted Tcl
+ *	command argument or a quoted value in a Tcl expression. This
+ *	procedure is also used to compile array element names within
+ *	parentheses (where the termChar will be ')' instead of '"'), or
+ *	anything else that needs the substitutions that happen in quotes.
+ *
+ *	Ordinarily, callers set envPtr->pushSimpleWords to 1 and
+ *	TclCompileQuotes always emits push and other instructions to compute
+ *	the word on the Tcl evaluation stack at execution time. If a caller
+ *	sets envPtr->pushSimpleWords to 0, TclCompileQuotes will not compile
+ *	"simple" words: words that are just a sequence of characters without
+ *	backslashes. It will leave their compilation up to the caller. This
+ *	is done to provide special support for the first word of commands,
+ *	which are almost always the (simple) name of a command.
+ *
+ *	As an important special case, if the word is simple, this procedure
+ *	sets envPtr->wordIsSimple to 1 and envPtr->numSimpleWordChars to the
+ *	number of characters in the simple word. This allows the caller to
+ *	process these words specially.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is TCL_OK unless
+ *	there was an error while parsing the quoted string. If an error
+ *	occurs then the interpreter's result contains a standard error
+ *	message.
+ *
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one successfully processed; this is
+ *	usually the character just after the matching close-quote.
+ *
+ *	envPtr->wordIsSimple is set 1 if the word is simple: just a
+ *	sequence of characters without backslashes. If so, the word's
+ *	characters are the envPtr->numSimpleWordChars characters starting 
+ *	at string.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to evaluate the word. This is not changed if
+ *	the word is simple and envPtr->pushSimpleWords was 0 (false).
+ *
+ * Side effects:
+ *	Instructions are added to envPtr to push the quoted-string
+ *	at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileQuotes(interp, string, lastChar, termChar, flags, envPtr)
+    Tcl_Interp *interp;		 /* Interpreter to use for nested command
+				  * evaluations and error messages. */
+    char *string;		 /* Points to the character just after
+				  * the opening '"' or '('. */
+    char *lastChar;		 /* Pointer to terminating character of
+				  * string. */
+    int termChar;		 /* Character that terminates the "quoted"
+				  * string (usually double-quote, but might
+				  * be right-paren or something else). */
+    int flags;			 /* Flags to control compilation (same 
+				  * values passed to Tcl_Eval). */
+    CompileEnv *envPtr;		 /* Holds the resulting instructions. */
+{
+    register char *src = string; /* Points to current source char. */
+    register char c = *src;	 /* The current char. */
+    int simpleWord = 0;		 /* Set 1 if a simple quoted string word. */
+    char *start;		 /* Start position of char+ string_part. */
+    int hasBackslash; 	         /* 1 if '\' found in char+ string_part. */
+    int numRead;		 /* Count of chars read by Tcl_Backslash. */
+    int numParts = 0;	         /* Count of string_part objs pushed. */
+    int maxDepth = 0;		 /* Maximum number of stack elements needed
+				  * to compute and push the string. */
+    char savedChar;		 /* Holds the character from string
+				  * termporarily replaced by a null 
+				  * char during string_part processing. */
+    int objIndex;		 /* The object array index for a pushed
+				  * object holding a string_part. */
+    int numChars;		 /* Number of chars in string_part. */
+    int savePushSimpleWords = envPtr->pushSimpleWords;
+    int result = TCL_OK;
+    
+    /*
+     * quoted_string: '"' string_part* '"'   (or termChar instead of ")
+     * string_part:   var_reference | nested_cmd | char+
+     */
+
+
+    while ((src != lastChar) && (c != termChar)) {
+	if (c == '$') {
+	    result = TclCompileDollarVar(interp, src, lastChar, flags,
+		    envPtr);
+	    src += envPtr->termOffset;
+	    if (result != TCL_OK) {
+		goto done;
+	    }
+	    maxDepth = TclMax((numParts + envPtr->maxStackDepth), maxDepth);
+	    c = *src;
+        } else if (c == '[') {
+	    char *termPtr;
+	    envPtr->pushSimpleWords = 1;
+	    src++;
+	    result = TclCompileString(interp, src, lastChar,
+				      (flags | TCL_BRACKET_TERM), envPtr);
+	    termPtr = (src + envPtr->termOffset);
+	    if (*termPtr == ']') {
+		termPtr++;
+	    }
+	    src = termPtr;
+	    if (result != TCL_OK) {
+		goto done;
+	    }
+	    if (termPtr == lastChar) {
+		/*
+		 * Missing ] at end of nested command.
+		 */
+		
+		Tcl_ResetResult(interp);
+		Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		        "missing close-bracket", -1);
+		result = TCL_ERROR;
+		goto done;
+	    }
+	    maxDepth = TclMax((numParts + envPtr->maxStackDepth), maxDepth);
+	    c = *src;
+        } else {
+	    /*
+	     * Start of a char+ string_part. Scan first looking for any
+	     * backslashes.
+	     */
+
+	    start = src;
+	    hasBackslash = 0;
+	    do {
+		if (c == '\\') {
+		    hasBackslash = 1;
+		    Tcl_Backslash(src, &numRead);
+		    src += numRead;
+		} else {
+		    src++;
+		}
+		c = *src;
+            } while ((src != lastChar) && (c != '$') && (c != '[')
+		    && (c != termChar));
+	    
+	    if ((numParts == 0) && !hasBackslash
+		    && ((src == lastChar) && (c == termChar))) {
+		/*
+		 * The quoted string is "simple": just a sequence of
+		 * characters without backslashes terminated by termChar or
+		 * a null character. Just return if we are not to compile
+		 * simple words.
+		 */
+
+		simpleWord = 1;
+		if (!envPtr->pushSimpleWords) {
+		    if ((src == lastChar) && (termChar != '\0')) {
+			char buf[40];
+			sprintf(buf, "missing %c", termChar);
+			Tcl_ResetResult(interp);
+			Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
+			result = TCL_ERROR;
+		    } else {
+			src++;
+		    }
+		    envPtr->wordIsSimple = 1;
+		    envPtr->numSimpleWordChars = (src - string - 1);
+		    envPtr->termOffset = (src - string);
+		    envPtr->pushSimpleWords = savePushSimpleWords;
+		    return result;
+		}
+	    }
+
+	    /*
+	     * Create and push a string object for the char+ string_part
+	     * that starts at "start" and ends at the char just before
+	     * src. If backslashes were found, copy the string_part's
+	     * characters with substituted backslashes into a heap-allocated
+	     * buffer and use it to create the string object. Temporarily
+	     * replace the terminating character with a null character.
+	     */
+	    
+	    numChars = (src - start);
+	    savedChar = start[numChars];
+	    start[numChars] = '\0';
+	    if ((numChars > 0) && (hasBackslash)) {
+		char *buffer = ckalloc((unsigned) numChars + 1);
+		register char *dst = buffer;
+		register char *p = start;
+		while (p < src) {
+		    if (*p == '\\') {
+			*dst++ = Tcl_Backslash(p, &numRead);
+			p += numRead;
+		    } else {
+			*dst++ = *p++;
+		    }
+		}
+		*dst = '\0';
+		objIndex = TclObjIndexForString(buffer, (dst - buffer),
+			/*allocStrRep*/ 1, /*inHeap*/ 1, envPtr);
+	    } else {
+		objIndex = TclObjIndexForString(start, numChars,
+			/*allocStrRep*/ 1, /*inHeap*/ 0, envPtr);
+	    }
+	    start[numChars] = savedChar;
+	    TclEmitPush(objIndex, envPtr);
+	    maxDepth = TclMax((numParts + 1), maxDepth);
+        }
+	numParts++;
+    } 
+	    
+    /*
+     * End of the quoted string: src points at termChar or '\0'. If
+     * necessary, concatenate the string_part objects on the stack.
+     */
+
+    if ((src == lastChar) && (termChar != '\0')) {
+	char buf[40];
+	sprintf(buf, "missing %c", termChar);
+	Tcl_ResetResult(interp);
+	Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
+	result = TCL_ERROR;
+	goto done;
+    } else {
+	src++;
+    }
+
+    if (numParts == 0) {
+	/*
+	 * The quoted string was empty. Push an empty string object.
+	 */
+
+	int objIndex = TclObjIndexForString("", 0, /*allocStrRep*/ 0,
+                                            /*inHeap*/ 0, envPtr);
+	TclEmitPush(objIndex, envPtr);
+    } else {
+	/*
+	 * Emit any needed concat instructions.
+	 */
+	
+	while (numParts > 255) {
+	    TclEmitInstUInt1(INST_CONCAT1, 255, envPtr);
+	    numParts -= 254;  /* concat pushes 1 obj, the result */
+	}
+	if (numParts > 1) {
+	    TclEmitInstUInt1(INST_CONCAT1, numParts, envPtr);
+	}
+    }
+
+    done:
+    if (simpleWord) {
+	envPtr->wordIsSimple = 1;
+	envPtr->numSimpleWordChars = (src - string - 1);
+    } else {
+	envPtr->wordIsSimple = 0;
+	envPtr->numSimpleWordChars = 0;
+    }
+    envPtr->termOffset = (src - string);
+    envPtr->maxStackDepth = maxDepth;
+    envPtr->pushSimpleWords = savePushSimpleWords;
+    return result;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CompileBraces --
+ *
+ *	This procedure compiles characters between matching curly braces.
+ *
+ *	Ordinarily, callers set envPtr->pushSimpleWords to 1 and
+ *	CompileBraces always emits a push instruction to compute the word on
+ *	the Tcl evaluation stack at execution time. However, if a caller
+ *	sets envPtr->pushSimpleWords to 0, CompileBraces will _not_ compile
+ *	"simple" words: words that are just a sequence of characters without
+ *	backslash-newlines. It will leave their compilation up to the
+ *	caller.
+ *
+ *	As an important special case, if the word is simple, this procedure
+ *	sets envPtr->wordIsSimple to 1 and envPtr->numSimpleWordChars to the
+ *	number of characters in the simple word. This allows the caller to
+ *	process these words specially.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is TCL_OK unless
+ *	there was an error while parsing string. If an error occurs then
+ *	the interpreter's result contains a standard error message.
+ *
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one successfully processed. This is
+ *	usually the character just after the matching close-brace.
+ *
+ *	envPtr->wordIsSimple is set 1 if the word is simple: just a
+ *	sequence of characters without backslash-newlines. If so, the word's
+ *	characters are the envPtr->numSimpleWordChars characters starting 
+ *	at string.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to evaluate the word. This is not changed if
+ *	the word is simple and envPtr->pushSimpleWords was 0 (false).
+ *
+ * Side effects:
+ *	Instructions are added to envPtr to push the braced string
+ *	at runtime.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+CompileBraces(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		 /* Interpreter to use for nested command
+				  * evaluations and error messages. */
+    char *string;		 /* Character just after opening bracket. */
+    char *lastChar;		 /* Pointer to terminating character of
+				  * string. */
+    int flags;			 /* Flags to control compilation (same 
+				  * values passed to Tcl_Eval). */
+    CompileEnv *envPtr;		 /* Holds the resulting instructions. */
+{
+    register char *src = string; /* Points to current source char. */
+    register char c;		 /* The current char. */
+    int simpleWord = 0;		 /* Set 1 if a simple braced string word. */
+    int level = 1;		 /* {} nesting level. Initially 1 since {
+				  * was parsed before we were called. */
+    int hasBackslashNewline = 0; /* Nonzero if '\' found. */
+    char *last;			 /* Points just before terminating '}'. */
+    int numChars;		 /* Number of chars in braced string. */
+    char savedChar;		 /* Holds the character from string
+				  * termporarily replaced by a null 
+				  * char during braced string processing. */
+    int objIndex;		 /* The object array index for a pushed
+				  * object holding a braced string. */
+    int numRead;
+    int result = TCL_OK;
+
+    /*
+     * Check for any backslash-newlines, since we must treat
+     * backslash-newlines specially (they must be replaced by spaces).
+     */
+
+    while (1) {
+	c = *src;
+	if (src == lastChar) {
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		    "missing close-brace", -1);
+	    result = TCL_ERROR;
+	    goto done;
+	}
+	if (CHAR_TYPE(src, lastChar) != TCL_NORMAL) {
+	    if (c == '{') {
+		level++;
+	    } else if (c == '}') {
+		--level;
+		if (level == 0) {
+		    src++;
+		    last = (src - 2); /* point just before terminating } */
+		    break;
+		}
+	    } else if (c == '\\') {
+		if (*(src+1) == '\n') {
+		    hasBackslashNewline = 1;
+		}
+		(void) Tcl_Backslash(src, &numRead);
+		src += numRead - 1;
+	    }
+	}
+	src++;
+    }
+
+    if (!hasBackslashNewline) {
+	/*
+	 * The braced word is "simple": just a sequence of characters
+	 * without backslash-newlines. Just return if we are not to compile
+	 * simple words.
+	 */
+
+	simpleWord = 1;
+	if (!envPtr->pushSimpleWords) {
+	    envPtr->wordIsSimple = 1;
+	    envPtr->numSimpleWordChars = (src - string - 1);
+	    envPtr->termOffset = (src - string);
+	    return TCL_OK;
+	}
+    }
+
+    /*
+     * Create and push a string object for the braced string. This starts at
+     * "string" and ends just after "last" (which points to the final
+     * character before the terminating '}'). If backslash-newlines were
+     * found, we copy characters one at a time into a heap-allocated buffer
+     * and do backslash-newline substitutions.
+     */
+
+    numChars = (last - string + 1);
+    savedChar = string[numChars];
+    string[numChars] = '\0';
+    if ((numChars > 0) && (hasBackslashNewline)) {
+	char *buffer = ckalloc((unsigned) numChars + 1);
+	register char *dst = buffer;
+	register char *p = string;
+	while (p <= last) {
+	    c = *dst++ = *p++;
+	    if (c == '\\') {
+		if (*p == '\n') {
+		    dst[-1] = Tcl_Backslash(p-1, &numRead);
+		    p += numRead - 1;
+		} else {
+		    (void) Tcl_Backslash(p-1, &numRead);
+		    while (numRead > 1) {
+			*dst++ = *p++;
+			numRead--;
+		    }
+		}
+	    }
+	}
+	*dst = '\0';
+	objIndex = TclObjIndexForString(buffer, (dst - buffer),
+		/*allocStrRep*/ 1, /*inHeap*/ 1, envPtr);
+    } else {
+	objIndex = TclObjIndexForString(string, numChars, /*allocStrRep*/ 1,
+                                        /*inHeap*/ 0, envPtr);
+    }
+    string[numChars] = savedChar;
+    TclEmitPush(objIndex, envPtr);
+
+    done:
+    if (simpleWord) {
+	envPtr->wordIsSimple = 1;
+	envPtr->numSimpleWordChars = (src - string - 1);
+    } else {
+	envPtr->wordIsSimple = 0;
+	envPtr->numSimpleWordChars = 0;
+    }
+    envPtr->termOffset = (src - string);
+    envPtr->maxStackDepth = 1;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileDollarVar --
+ *
+ *	Given a string starting with a $ sign, parse a variable name
+ *	and compile instructions to push its value. If the variable
+ *	reference is just a '$' (i.e. the '$' isn't followed by anything
+ *	that could possibly be a variable name), just push a string object
+ *	containing '$'.
+ *
+ * Results:
+ *	The return value is a standard Tcl result. If an error occurs
+ *	then an error message is left in the interpreter's result.
+ *
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one in the variable reference.
+ *
+ *	envPtr->wordIsSimple is set 0 (false) because the word is not
+ *	simple: it is not just a sequence of characters without backslashes.
+ *	For the same reason, envPtr->numSimpleWordChars is set 0.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the string's commands.
+ *
+ * Side effects:
+ *	Instructions are added to envPtr to look up the variable and
+ *	push its value at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+    
+int
+TclCompileDollarVar(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		 /* Interpreter to use for nested command
+				  * evaluations and error messages. */
+    char *string;		 /* First char (i.e. $) of var reference. */
+    char *lastChar;		 /* Pointer to terminating character of
+				  * string. */
+    int flags;			 /* Flags to control compilation (same
+				  * values passed to Tcl_Eval). */
+    CompileEnv *envPtr;		 /* Holds the resulting instructions. */
+{
+    register char *src = string; /* Points to current source char. */
+    register char c;		 /* The current char. */
+    char *name;			 /* Start of 1st part of variable name. */
+    int nameChars;		 /* Count of chars in name. */
+    int nameHasNsSeparators = 0; /* Set 1 if name contains "::"s. */
+    char savedChar;		 /* Holds the character from string
+				  * termporarily replaced by a null 
+				  * char during name processing. */
+    int objIndex;		 /* The object array index for a pushed
+				  * object holding a name part. */
+    int isArrayRef = 0;		 /* 1 if reference to array element. */
+    int localIndex = -1;	 /* Frame index of local if found.  */
+    int maxDepth = 0;		 /* Maximum number of stack elements needed
+				  * to push the variable. */
+    int savePushSimpleWords = envPtr->pushSimpleWords;
+    int result = TCL_OK;
+
+    /*
+     * var_reference: '$' '{' braced_name '}' |
+     *                '$' name ['(' index_string ')']
+     *
+     * There are three cases:
+     * 1. The $ sign is followed by an open curly brace. Then the variable
+     *    name is everything up to the next close curly brace, and the
+     *    variable is a scalar variable.
+     * 2. The $ sign is not followed by an open curly brace. Then the
+     *    variable name is everything up to the next character that isn't
+     *    a letter, digit, underscore, or a "::" namespace separator. If the
+     *    following character is an open parenthesis, then the information
+     *    between parentheses is the array element name, which can include
+     *    any of the substitutions permissible between quotes.
+     * 3. The $ sign is followed by something that isn't a letter, digit,
+     *    underscore, or a "::" namespace separator: in this case,
+     *    there is no variable name, and "$" is pushed.
+     */
+
+    src++;			/* advance over the '$'. */
+
+    /*
+     * Collect the first part of the variable's name into "name" and
+     * determine if it is an array reference and if it contains any
+     * namespace separator (::'s).
+     */
+    
+    if (*src == '{') {
+        /*
+	 * A scalar name in braces.
+	 */
+
+	char *p;
+
+	src++;
+        name = src;
+        c = *src;
+	while (c != '}') {
+	    if (src == lastChar) {
+		Tcl_ResetResult(interp);
+		Tcl_AppendToObj(Tcl_GetObjResult(interp),
+			"missing close-brace for variable name", -1);
+		result = TCL_ERROR;
+		goto done;
+	    }
+	    src++;
+	    c = *src;
+	}
+	nameChars = (src - name);
+	for (p = name;  p < src;  p++) {
+	    if ((*p == ':') && (*(p+1) == ':')) {
+		nameHasNsSeparators = 1;
+		break;
+	    }
+	}
+	src++;			/* advance over the '}'. */
+    } else {
+	/*
+	 * Scalar name or array reference not in braces.
+	 */
+	
+        name = src;
+        c = *src;
+        while (isalnum(UCHAR(c)) || (c == '_') || (c == ':')) {
+	    if (c == ':') {
+                if (*(src+1) == ':') {
+		    nameHasNsSeparators = 1;
+                    src += 2;
+		    while (*src == ':') {
+			src++;
+		    }
+                    c = *src;
+                } else {
+                    break;	/* : by itself */
+                }
+            } else {
+                src++;
+                c = *src;
+            }
+	}
+	if (src == name) {
+	    /*
+	     * A '$' by itself, not a name reference. Push a "$" string.
+	     */
+
+	    objIndex = TclObjIndexForString("$", 1, /*allocStrRep*/ 1,
+                                            /*inHeap*/ 0, envPtr);
+	    TclEmitPush(objIndex, envPtr);
+	    maxDepth = 1;
+	    goto done;
+	}
+	nameChars = (src - name);
+	isArrayRef = (c == '(');
+    }
+
+    /*
+     * Now emit instructions to load the variable. First either push the
+     * name of the scalar or array, or determine its index in the array of
+     * local variables in a procedure frame. Push the name if we are not
+     * compiling a procedure body or if the name has namespace
+     * qualifiers ("::"s).
+     */
+    
+    if (!isArrayRef) {		/* scalar reference */
+	if ((envPtr->procPtr == NULL) || nameHasNsSeparators) {
+	    savedChar = name[nameChars];
+	    name[nameChars] = '\0';
+	    objIndex = TclObjIndexForString(name, nameChars,
+		    /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr);
+	    name[nameChars] = savedChar;
+	    TclEmitPush(objIndex, envPtr);
+	    TclEmitOpcode(INST_LOAD_SCALAR_STK, envPtr);
+	    maxDepth = 1;
+	} else {
+	    localIndex = LookupCompiledLocal(name, nameChars,
+	            /*createIfNew*/ 0, /*flagsIfCreated*/ 0,
+		    envPtr->procPtr);
+	    if (localIndex >= 0) {
+		if (localIndex <= 255) {
+		    TclEmitInstUInt1(INST_LOAD_SCALAR1, localIndex, envPtr);
+		} else {
+		    TclEmitInstUInt4(INST_LOAD_SCALAR4, localIndex, envPtr);
+		}
+		maxDepth = 0;
+	    } else {
+		savedChar = name[nameChars];
+		name[nameChars] = '\0';
+		objIndex = TclObjIndexForString(name, nameChars,
+			/*allocStrRep*/ 1, /*inHeap*/ 0, envPtr);
+		name[nameChars] = savedChar;
+		TclEmitPush(objIndex, envPtr); 
+		TclEmitOpcode(INST_LOAD_SCALAR_STK, envPtr);
+		maxDepth = 1;
+	    }
+	}
+    } else {			/* array reference */
+	if ((envPtr->procPtr == NULL) || nameHasNsSeparators) {
+	    savedChar = name[nameChars];
+	    name[nameChars] = '\0';
+	    objIndex = TclObjIndexForString(name, nameChars,
+		    /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr);
+	    name[nameChars] = savedChar;
+	    TclEmitPush(objIndex, envPtr);
+	    maxDepth = 1;
+	} else {
+	    localIndex = LookupCompiledLocal(name, nameChars,
+	            /*createIfNew*/ 0, /*flagsIfCreated*/ 0,
+		    envPtr->procPtr);
+	    if (localIndex < 0) {
+		savedChar = name[nameChars];
+		name[nameChars] = '\0';
+		objIndex = TclObjIndexForString(name, nameChars,
+			/*allocStrRep*/ 1, /*inHeap*/ 0, envPtr);
+		name[nameChars] = savedChar;
+		TclEmitPush(objIndex, envPtr);
+		maxDepth = 1;
+	    }
+	}
+
+	/*
+	 * Parse and push the array element. Perform substitutions on it,
+	 * just as is done for quoted strings.
+	 */
+
+	src++;
+	envPtr->pushSimpleWords = 1;
+	result = TclCompileQuotes(interp, src, lastChar, ')', flags,
+		envPtr);
+	src += envPtr->termOffset;
+	if (result != TCL_OK) {
+	    char msg[200];
+	    sprintf(msg, "\n    (parsing index for array \"%.*s\")",
+		    (nameChars > 100? 100 : nameChars), name);
+	    Tcl_AddObjErrorInfo(interp, msg, -1);
+	    goto done;
+	}
+	maxDepth += envPtr->maxStackDepth;
+
+	/*
+	 * Now emit the appropriate load instruction for the array element.
+	 */
+
+	if (localIndex < 0) {	/* a global or an unknown local */
+	    TclEmitOpcode(INST_LOAD_ARRAY_STK, envPtr);
+	} else {
+	    if (localIndex <= 255) {
+		TclEmitInstUInt1(INST_LOAD_ARRAY1, localIndex, envPtr);
+	    } else {
+		TclEmitInstUInt4(INST_LOAD_ARRAY4, localIndex, envPtr);
+	    }
+	}
+    }
+
+    done:
+    envPtr->termOffset = (src - string);
+    envPtr->wordIsSimple = 0;
+    envPtr->numSimpleWordChars = 0;
+    envPtr->maxStackDepth = maxDepth;
+    envPtr->pushSimpleWords = savePushSimpleWords;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * IsLocalScalar --
+ *
+ *	Checks to see if a variable name refers to a local scalar.
+ *
+ * Results:
+ *	Returns 1 if the variable is a local scalar.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+IsLocalScalar(varName, length)
+    char *varName;		/* The name to check. */
+    int length;		/* The number of characters in the string.  */
+{
+    char *p;
+    char *lastChar = varName + (length - 1);
+
+    for (p = varName; p <= lastChar; p++) {
+	if ((CHAR_TYPE(p, lastChar) != TCL_NORMAL) &&
+	    (CHAR_TYPE(p, lastChar) != TCL_COMMAND_END)) {
+	    /*
+	     * TCL_COMMAND_END is returned for the last character
+	     * of the string.  By this point we know it isn't
+	     * an array or namespace reference.
+	     */
+
+	    return 0;
+	}
+	if  (*p == '(') {
+	    if (*lastChar == ')') { /* we have an array element */
+		return 0;
+	    }
+	} else if (*p == ':') {
+	    if ((p != lastChar) && *(p+1) == ':') { /* qualified name */
+		return 0;
+	    }
+	}
+    }
+	
+    return 1;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileBreakCmd --
+ *
+ *	Procedure called to compile the "break" command.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is TCL_OK unless
+ *	there was an error while parsing string. If an error occurs then
+ *	the interpreter's result contains a standard error message.
+ *
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one successfully processed.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the command.
+ *
+ * Side effects:
+ *	Instructions are added to envPtr to evaluate the "break" command
+ *	at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileBreakCmd(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    char *string;		/* The source string to compile. */
+    char *lastChar;		/* Pointer to terminating character of
+				 * string. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    register char *src = string;/* Points to current source char. */
+    register int type;		/* Current char's CHAR_TYPE type. */
+    int result = TCL_OK;
+    
+    /*
+     * There should be no argument after the "break".
+     */
+
+    type = CHAR_TYPE(src, lastChar);
+    if (type != TCL_COMMAND_END) {
+	AdvanceToNextWord(src, envPtr);
+	src += envPtr->termOffset;
+	type = CHAR_TYPE(src, lastChar);
+	if (type != TCL_COMMAND_END) {
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	            "wrong # args: should be \"break\"", -1);
+	    result = TCL_ERROR;
+	    goto done;
+	}
+    }
+
+    /*
+     * Emit a break instruction.
+     */
+
+    TclEmitOpcode(INST_BREAK, envPtr);
+
+    done:
+    envPtr->termOffset = (src - string);
+    envPtr->maxStackDepth = 0;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileCatchCmd --
+ *
+ *	Procedure called to compile the "catch" command.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is TCL_OK if
+ *	compilation was successful. If an error occurs then the
+ *	interpreter's result contains a standard error message and TCL_ERROR
+ *	is returned. If compilation failed because the command is too
+ *	complex for TclCompileCatchCmd, TCL_OUT_LINE_COMPILE is returned
+ *	indicating that the catch command should be compiled "out of line"
+ *	by emitting code to invoke its command procedure at runtime.
+ *
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one successfully processed.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the command.
+ *
+ * Side effects:
+ *	Instructions are added to envPtr to evaluate the "catch" command
+ *	at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileCatchCmd(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    char *string;		/* The source string to compile. */
+    char *lastChar;		/* Pointer to terminating character of
+				 * string. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    Proc *procPtr = envPtr->procPtr;
+    				/* Points to structure describing procedure
+				 * containing the catch cmd, else NULL. */
+    int maxDepth = 0;           /* Maximum number of stack elements needed
+				 * to execute cmd. */
+    ArgInfo argInfo;		/* Structure holding information about the
+				 * start and end of each argument word. */
+    int range = -1;		/* If we compile the catch command, the
+				 * index for its catch range record in the
+				 * ExceptionRange array. -1 if we are not
+				 * compiling the command. */
+    char *name;			/* If a var name appears for a scalar local
+				 * to a procedure, this points to the name's
+				 * 1st char and nameChars is its length. */
+    int nameChars;		/* Length of the variable name, if any. */
+    int localIndex = -1;        /* Index of the variable in the current
+				 * procedure's array of local variables.
+				 * Otherwise -1 if not in a procedure or
+				 * the variable wasn't found. */
+    char savedChar;		/* Holds the character from string
+				 * termporarily replaced by a null character
+				 * during processing of words. */
+    JumpFixup jumpFixup;	/* Used to emit the jump after the "no
+				 * errors" epilogue code. */
+    int numWords, objIndex, jumpDist, result;
+    char *bodyStart, *bodyEnd;
+    Tcl_Obj *objPtr;
+    int savePushSimpleWords = envPtr->pushSimpleWords;
+
+    /*
+     * Scan the words of the command and record the start and finish of
+     * each argument word.
+     */
+
+    InitArgInfo(&argInfo);
+    result = CollectArgInfo(interp, string, lastChar, flags, &argInfo);
+    numWords = argInfo.numArgs;	  /* i.e., the # after the command name */
+    if (result != TCL_OK) {
+	goto done;
+    }
+    if ((numWords != 1) && (numWords != 2)) {
+	Tcl_ResetResult(interp);
+	Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	        "wrong # args: should be \"catch command ?varName?\"", -1);
+        result = TCL_ERROR;
+	goto done;
+    }
+
+    /*
+     * If a variable was specified and the catch command is at global level
+     * (not in a procedure), don't compile it inline: the payoff is
+     * too small.
+     */
+
+    if ((numWords == 2) && (procPtr == NULL)) {
+	result = TCL_OUT_LINE_COMPILE;
+        goto done;
+    }
+
+    /*
+     * Make sure the variable name, if any, has no substitutions and just
+     * refers to a local scaler.
+     */
+
+    if (numWords == 2) {
+	char *firstChar = argInfo.startArray[1];
+	char *lastChar  = argInfo.endArray[1];
+	
+	if (*firstChar == '{') {
+	    if (*lastChar != '}') {
+		Tcl_ResetResult(interp);
+		Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		        "extra characters after close-brace", -1);
+		result = TCL_ERROR;
+		goto done;
+	    }
+	    firstChar++;
+	    lastChar--;
+	}
+
+	nameChars = (lastChar - firstChar + 1);
+	if (!IsLocalScalar(firstChar, nameChars)) {
+	    result = TCL_OUT_LINE_COMPILE;
+	    goto done;
+	}
+
+	name = firstChar;
+	localIndex = LookupCompiledLocal(name, nameChars,
+                    /*createIfNew*/ 1, /*flagsIfCreated*/ VAR_SCALAR,
+		    procPtr);
+    }
+
+    /*
+     *==== At this point we believe we can compile the catch command ====
+     */
+
+    /*
+     * Create and initialize a ExceptionRange record to hold information
+     * about this catch command.
+     */
+    
+    envPtr->excRangeDepth++;
+    envPtr->maxExcRangeDepth =
+	TclMax(envPtr->excRangeDepth, envPtr->maxExcRangeDepth);
+    range = CreateExceptionRange(CATCH_EXCEPTION_RANGE, envPtr);
+
+    /*
+     * Emit the instruction to mark the start of the catch command.
+     */
+    
+    TclEmitInstUInt4(INST_BEGIN_CATCH4, range, envPtr);
+    
+    /*
+     * Inline compile the catch's body word: the command it controls. Also
+     * register the body's starting PC offset and byte length in the
+     * ExceptionRange record.
+     */
+
+    envPtr->excRangeArrayPtr[range].codeOffset = TclCurrCodeOffset();
+
+    bodyStart = argInfo.startArray[0];
+    bodyEnd   = argInfo.endArray[0];
+    savedChar = *(bodyEnd+1);
+    *(bodyEnd+1) = '\0';
+    result = CompileCmdWordInline(interp, bodyStart, (bodyEnd+1),
+	    flags, envPtr);
+    *(bodyEnd+1) = savedChar;
+    
+    if (result != TCL_OK) {
+	if (result == TCL_ERROR) {
+	    char msg[60];
+	    sprintf(msg, "\n    (\"catch\" body line %d)",
+		    interp->errorLine);
+            Tcl_AddObjErrorInfo(interp, msg, -1);
+        }
+	goto done;
+    }
+    maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
+    envPtr->excRangeArrayPtr[range].numCodeBytes =
+	TclCurrCodeOffset() - envPtr->excRangeArrayPtr[range].codeOffset;
+
+    /*
+     * Now emit the "no errors" epilogue code for the catch. First, if a
+     * variable was specified, store the body's result into the
+     * variable; otherwise, just discard the body's result. Then push
+     * a "0" object as the catch command's "no error" TCL_OK result,
+     * and jump around the "error case" epilogue code.
+     */
+
+    if (localIndex != -1) {
+	if (localIndex <= 255) {
+	    TclEmitInstUInt1(INST_STORE_SCALAR1, localIndex, envPtr);
+	} else {
+	    TclEmitInstUInt4(INST_STORE_SCALAR4, localIndex, envPtr);
+	}
+    }
+    TclEmitOpcode(INST_POP, envPtr);
+
+    objIndex = TclObjIndexForString("0", 1, /*allocStrRep*/ 0, /*inHeap*/ 0,
+	    envPtr);
+    objPtr = envPtr->objArrayPtr[objIndex];
+    
+    Tcl_InvalidateStringRep(objPtr);
+    objPtr->internalRep.longValue = 0;
+    objPtr->typePtr = &tclIntType;
+    
+    TclEmitPush(objIndex, envPtr);
+    if (maxDepth == 0) {
+	maxDepth = 1;	/* since we just pushed one object */
+    }
+    
+    TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup);
+
+    /*
+     * Now emit the "error case" epilogue code. First, if a variable was
+     * specified, emit instructions to push the interpreter's object result
+     * and store it into the variable. Then emit an instruction to push the
+     * nonzero error result. Note that the initial PC offset here is the
+     * catch's error target.
+     */
+
+    envPtr->excRangeArrayPtr[range].catchOffset = TclCurrCodeOffset();
+    if (localIndex != -1) {
+	TclEmitOpcode(INST_PUSH_RESULT, envPtr);
+	if (localIndex <= 255) {
+	    TclEmitInstUInt1(INST_STORE_SCALAR1, localIndex, envPtr);
+	} else {
+	    TclEmitInstUInt4(INST_STORE_SCALAR4, localIndex, envPtr);
+	}
+	TclEmitOpcode(INST_POP, envPtr);
+    }
+    TclEmitOpcode(INST_PUSH_RETURN_CODE, envPtr);
+
+    /*
+     * Now that we know the target of the jump after the "no errors"
+     * epilogue, update it with the correct distance. This is less
+     * than 127 bytes.
+     */
+
+    jumpDist = (TclCurrCodeOffset() - jumpFixup.codeOffset);
+    if (TclFixupForwardJump(envPtr, &jumpFixup, jumpDist, 127)) {
+	panic("TclCompileCatchCmd: bad jump distance %d\n", jumpDist);
+    }
+
+    /*
+     * Emit the instruction to mark the end of the catch command.
+     */
+
+    TclEmitOpcode(INST_END_CATCH, envPtr);
+
+    done:
+    if (numWords == 0) {
+	envPtr->termOffset = 0;
+    } else {
+	envPtr->termOffset = (argInfo.endArray[numWords-1] + 1 - string);
+    }
+    if (range != -1) {		/* we compiled the catch command */
+	envPtr->excRangeDepth--;
+    }
+    envPtr->pushSimpleWords = savePushSimpleWords;
+    envPtr->maxStackDepth = maxDepth;
+    FreeArgInfo(&argInfo);
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileContinueCmd --
+ *
+ *	Procedure called to compile the "continue" command.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is TCL_OK unless
+ *	there was an error while parsing string. If an error occurs then
+ *	the interpreter's result contains a standard error message.
+ *
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one successfully processed.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the command.
+ *
+ * Side effects:
+ *	Instructions are added to envPtr to evaluate the "continue" command
+ *	at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileContinueCmd(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    char *string;		/* The source string to compile. */
+    char *lastChar;		/* Pointer to terminating character of
+				 * string. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    register char *src = string;/* Points to current source char. */
+    register int type;		/* Current char's CHAR_TYPE type. */
+    int result = TCL_OK;
+    
+    /*
+     * There should be no argument after the "continue".
+     */
+
+    type = CHAR_TYPE(src, lastChar);
+    if (type != TCL_COMMAND_END) {
+	AdvanceToNextWord(src, envPtr);
+	src += envPtr->termOffset;
+	type = CHAR_TYPE(src, lastChar);
+	if (type != TCL_COMMAND_END) {
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	            "wrong # args: should be \"continue\"", -1);
+	    result = TCL_ERROR;
+	    goto done;
+	}
+    }
+
+    /*
+     * Emit a continue instruction.
+     */
+
+    TclEmitOpcode(INST_CONTINUE, envPtr);
+
+    done:
+    envPtr->termOffset = (src - string);
+    envPtr->maxStackDepth = 0;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileExprCmd --
+ *
+ *	Procedure called to compile the "expr" command.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is TCL_OK
+ *	unless there was an error while parsing string. If an error occurs
+ *	then the interpreter's result contains a standard error message.
+ *
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one successfully processed.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the "expr" command.
+ *
+ * Side effects:
+ *	Instructions are added to envPtr to evaluate the "expr" command
+ *	at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileExprCmd(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    char *string;		/* The source string to compile. */
+    char *lastChar;		/* Pointer to terminating character of
+				 * string. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute cmd. */
+    ArgInfo argInfo;		/* Structure holding information about the
+				 * start and end of each argument word. */
+    Tcl_DString buffer;		/* Holds the concatenated expr command
+				 * argument words. */
+    int firstWord;		/* 1 if processing the first word; 0 if
+				 * processing subsequent words. */
+    char *first, *last;		/* Points to the first and last significant
+				 * chars of the concatenated expression. */
+    int inlineCode;		/* 1 if inline "optimistic" code is
+				 * emitted for the expression; else 0. */
+    int range = -1;		/* If we inline compile the concatenated
+				 * expression, the index for its catch range
+				 * record in the ExceptionRange array.
+				 * Initialized to avoid compile warning. */
+    JumpFixup jumpFixup;	/* Used to emit the "success" jump after
+				 * the inline concat. expression's code. */
+    char savedChar;		/* Holds the character termporarily replaced
+				 * by a null character during compilation
+				 * of the concatenated expression. */
+    int numWords, objIndex, i, result;
+    char *wordStart, *wordEnd, *p;
+    char c;
+    int savePushSimpleWords = envPtr->pushSimpleWords;
+    int saveExprIsJustVarRef = envPtr->exprIsJustVarRef;
+    int saveExprIsComparison = envPtr->exprIsComparison;
+
+    /*
+     * Scan the words of the command and record the start and finish of
+     * each argument word.
+     */
+
+    InitArgInfo(&argInfo);
+    result = CollectArgInfo(interp, string, lastChar, flags, &argInfo);
+    numWords = argInfo.numArgs;	  /* i.e., the # after the command name */
+    if (result != TCL_OK) {
+	goto done;
+    }
+    if (numWords == 0) {
+	Tcl_ResetResult(interp);
+	Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	        "wrong # args: should be \"expr arg ?arg ...?\"", -1);
+        result = TCL_ERROR;
+	goto done;
+    }
+
+    /*
+     * If there is a single argument word and it is enclosed in {}s, we may
+     * strip them off and safely compile the expr command into an inline
+     * sequence of instructions using TclCompileExpr. We know these
+     * instructions will have the right Tcl7.x expression semantics.
+     *
+     * Otherwise, if the word is not enclosed in {}s, or there are multiple
+     * words, we may need to call the expr command (Tcl_ExprObjCmd) at
+     * runtime. This recompiles the expression each time (typically) and so
+     * is slow. However, there are some circumstances where we can still
+     * compile inline instructions "optimistically" and check, during their
+     * execution, for double substitutions (these appear as nonnumeric
+     * operands). We check for any backslash or command substitutions. If
+     * none appear, and only variable substitutions are found, we generate
+     * inline instructions. If there is a compilation error, we must emit
+     * instructions that return the error at runtime, since this is when
+     * scripts in Tcl7.x would "see" the error.
+     *
+     * For now, if there are multiple words, or the single argument word is
+     * not in {}s, we concatenate the argument words and strip off any
+     * enclosing {}s or ""s. We call the expr command at runtime if
+     * either command or backslash substitutions appear (but not if
+     * only variable substitutions appear).
+     */
+
+    if (numWords == 1) {
+	wordStart = argInfo.startArray[0]; /* start of 1st arg word */
+	wordEnd   = argInfo.endArray[0];   /* last char of 1st arg word */
+	if ((*wordStart == '{') && (*wordEnd == '}')) {
+	    /*
+	     * Simple case: a single argument word in {}'s. 
+	     */
+
+	    *wordEnd = '\0';
+	    result = TclCompileExpr(interp, (wordStart + 1), wordEnd,
+		    flags, envPtr);
+	    *wordEnd = '}';
+	    
+	    envPtr->termOffset = (wordEnd + 1) - string;
+	    envPtr->pushSimpleWords = savePushSimpleWords;
+	    FreeArgInfo(&argInfo);
+	    return result;
+	}
+    }
+	
+    /*
+     * There are multiple words or no braces around the single word.
+     * Concatenate the expression's argument words while stripping off
+     * any enclosing {}s or ""s.
+     */
+    
+    Tcl_DStringInit(&buffer);
+    firstWord = 1;
+    for (i = 0;  i < numWords;  i++) {
+	wordStart = argInfo.startArray[i];
+	wordEnd   = argInfo.endArray[i];
+	if (((*wordStart == '{') && (*wordEnd == '}'))
+	        || ((*wordStart == '"') && (*wordEnd == '"'))) {
+	    wordStart++;
+	    wordEnd--;
+	}
+	if (!firstWord) {
+	    Tcl_DStringAppend(&buffer, " ", 1);
+	}
+	firstWord = 0;
+	if (wordEnd >= wordStart) {
+	    Tcl_DStringAppend(&buffer, wordStart, (wordEnd-wordStart+1));
+	}
+    }
+
+    /*
+     * Scan the concatenated expression's characters looking for any
+     * '['s or '\'s or '$'s. If any are found, just call the expr cmd
+     * at runtime.
+     */
+    
+    inlineCode = 1;
+    first = Tcl_DStringValue(&buffer);
+    last = first + (Tcl_DStringLength(&buffer) - 1);
+    for (p = first;  p <= last;  p++) {
+	c = *p;
+	if ((c == '[') || (c == '\\') || (c == '$')) {
+	    inlineCode = 0;
+	    break;
+	}
+    }
+
+    if (inlineCode) {
+	/*
+	 * Inline compile the concatenated expression inside a "catch"
+	 * so that a runtime error will back off to a (slow) call on expr.
+	 */
+	
+	int startCodeOffset = (envPtr->codeNext - envPtr->codeStart);
+	int startRangeNext = envPtr->excRangeArrayNext;
+	
+	/*
+	 * Create a ExceptionRange record to hold information about the
+	 * "catch" range for the expression's inline code. Also emit the
+	 * instruction to mark the start of the range.
+	 */
+	
+	envPtr->excRangeDepth++;
+	envPtr->maxExcRangeDepth =
+	        TclMax(envPtr->excRangeDepth, envPtr->maxExcRangeDepth);
+	range = CreateExceptionRange(CATCH_EXCEPTION_RANGE, envPtr);
+	TclEmitInstUInt4(INST_BEGIN_CATCH4, range, envPtr);
+	
+	/*
+	 * Inline compile the concatenated expression.
+	 */
+	
+	envPtr->excRangeArrayPtr[range].codeOffset = TclCurrCodeOffset();
+	savedChar = *(last + 1);
+	*(last + 1) = '\0';
+	result = TclCompileExpr(interp, first, last + 1, flags, envPtr);
+	*(last + 1) = savedChar;
+	
+	maxDepth = envPtr->maxStackDepth;
+	envPtr->excRangeArrayPtr[range].numCodeBytes =
+	        TclCurrCodeOffset() - envPtr->excRangeArrayPtr[range].codeOffset;
+	
+	if ((result != TCL_OK) || (envPtr->exprIsJustVarRef)
+	        || (envPtr->exprIsComparison)) {
+	    /*
+	     * We must call the expr command at runtime. Either there was a
+	     * compilation error or the inline code might fail to give the
+	     * correct 2 level substitution semantics.
+	     *
+	     * The latter can happen if the expression consisted of just a
+	     * single variable reference or if the top-level operator in the
+	     * expr is a comparison (which might operate on strings). In the
+	     * latter case, the expression's code might execute (apparently)
+	     * successfully but produce the wrong result. We depend on its
+	     * execution failing if a second level of substitutions is
+	     * required. This causes the "catch" code we generate around the
+	     * inline code to back off to a call on the expr command at
+	     * runtime, and this always gives the right 2 level substitution
+	     * semantics.
+	     *
+	     * We delete the inline code by backing up the code pc and catch
+	     * index. Note that if there was a compilation error, we can't
+	     * report the error yet since the expression might be valid
+	     * after the second round of substitutions.
+	     */
+	    
+	    envPtr->codeNext = (envPtr->codeStart + startCodeOffset);
+	    envPtr->excRangeArrayNext = startRangeNext;
+	    inlineCode = 0;
+	} else {
+	    TclEmitOpcode(INST_END_CATCH, envPtr); /* for ok case */
+	    TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup);
+	    envPtr->excRangeArrayPtr[range].catchOffset = TclCurrCodeOffset();
+	    TclEmitOpcode(INST_END_CATCH, envPtr); /* for error case */
+	}
+    }
+	    
+    /*
+     * Emit code for the (slow) call on the expr command at runtime.
+     * Generate code to concatenate the (already substituted once)
+     * expression words with a space between each word.
+     */
+    
+    for (i = 0;  i < numWords;  i++) {
+	wordStart = argInfo.startArray[i];
+	wordEnd   = argInfo.endArray[i];
+	savedChar = *(wordEnd + 1);
+	*(wordEnd + 1) = '\0';
+	envPtr->pushSimpleWords = 1;
+	result = CompileWord(interp, wordStart, wordEnd+1, flags, envPtr);
+	*(wordEnd + 1) = savedChar;
+	if (result != TCL_OK) {
+	    break;
+	}
+	if (i != (numWords - 1)) {
+	    objIndex = TclObjIndexForString(" ", 1, /*allocStrRep*/ 1,
+					    /*inHeap*/ 0, envPtr);
+	    TclEmitPush(objIndex, envPtr);
+	    maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth);
+	} else {
+	    maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
+	}
+    }
+    if (result == TCL_OK) {
+	int concatItems = 2*numWords - 1;
+	while (concatItems > 255) {
+	    TclEmitInstUInt1(INST_CONCAT1, 255, envPtr);
+	    concatItems -= 254;  /* concat pushes 1 obj, the result */
+	}
+	if (concatItems > 1) {
+	    TclEmitInstUInt1(INST_CONCAT1, concatItems, envPtr);
+	}
+	TclEmitOpcode(INST_EXPR_STK, envPtr);
+    }
+    
+    /*
+     * If emitting inline code, update the target of the jump after
+     * that inline code.
+     */
+    
+    if (inlineCode) {
+	int jumpDist = (TclCurrCodeOffset() - jumpFixup.codeOffset);
+	if (TclFixupForwardJump(envPtr, &jumpFixup, jumpDist, 127)) {
+	    /*
+	     * Update the inline expression code's catch ExceptionRange
+	     * target since it, being after the jump, also moved down.
+	     */
+	    
+	    envPtr->excRangeArrayPtr[range].catchOffset += 3;
+	}
+    }
+    Tcl_DStringFree(&buffer);
+    
+    done:
+    if (numWords == 0) {
+	envPtr->termOffset = 0;
+    } else {
+	envPtr->termOffset = (argInfo.endArray[numWords-1] + 1 - string);
+    }
+    if (range != -1) {		/* we inline compiled the expr */
+	envPtr->excRangeDepth--;
+    }
+    envPtr->pushSimpleWords = savePushSimpleWords;
+    envPtr->exprIsJustVarRef = saveExprIsJustVarRef;
+    envPtr->exprIsComparison = saveExprIsComparison;
+    envPtr->maxStackDepth = maxDepth;
+    FreeArgInfo(&argInfo);
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileForCmd --
+ *
+ *	Procedure called to compile the "for" command.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is TCL_OK unless
+ *	there was an error while parsing string. If an error occurs then
+ *	the interpreter's result contains a standard error message.
+ *
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one successfully processed.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the command.
+ *
+ * Side effects:
+ *	Instructions are added to envPtr to evaluate the "for" command
+ *	at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileForCmd(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    char *string;		/* The source string to compile. */
+    char *lastChar;		/* Pointer to terminating character of
+				 * string. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute cmd. */
+    ArgInfo argInfo;		/* Structure holding information about the
+				 * start and end of each argument word. */
+    int range1 = -1, range2;	/* Indexes in the ExceptionRange array of
+				 * the loop ranges for this loop: one for
+				 * its body and one for its "next" cmd. */
+    JumpFixup jumpFalseFixup;	/* Used to update or replace the ifFalse
+				 * jump after the "for" test when its target
+				 * PC is determined. */
+    int jumpBackDist, jumpBackOffset, testCodeOffset, jumpDist, objIndex;
+    unsigned char *jumpPc;
+    int savePushSimpleWords = envPtr->pushSimpleWords;
+    int numWords, result;
+
+    /*
+     * Scan the words of the command and record the start and finish of
+     * each argument word.
+     */
+
+    InitArgInfo(&argInfo);
+    result = CollectArgInfo(interp, string, lastChar, flags, &argInfo);
+    numWords = argInfo.numArgs;	  /* i.e., the # after the command name */
+    if (result != TCL_OK) {
+	goto done;
+    }
+    if (numWords != 4) {
+	Tcl_ResetResult(interp);
+	Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	        "wrong # args: should be \"for start test next command\"", -1);
+	result = TCL_ERROR;
+	goto done;
+    }
+
+    /*
+     * If the test expression is not enclosed in braces, don't compile
+     * the for inline. As a result of Tcl's two level substitution
+     * semantics for expressions, the expression might have a constant
+     * value that results in the loop never executing, or executing forever.
+     * Consider "set x 0; for {} "$x > 5" {incr x} {}": the loop body 
+     * should never be executed.
+     * NOTE: This is an overly aggressive test, since there are legitimate
+     * literals that could be compiled but aren't in braces.  However, until
+     * the parser is integrated in 8.1, this is the simplest implementation.
+     */
+
+    if (*(argInfo.startArray[1]) != '{') {
+	result = TCL_OUT_LINE_COMPILE;
+	goto done;
+    }
+
+    /*
+     * Create a ExceptionRange record for the for loop's body. This is used
+     * to implement break and continue commands inside the body.
+     * Then create a second ExceptionRange record for the "next" command in 
+     * order to implement break (but not continue) inside it. The second,
+     * "next" ExceptionRange will always have a -1 continueOffset.
+     */
+
+    envPtr->excRangeDepth++;
+    envPtr->maxExcRangeDepth =
+	TclMax(envPtr->excRangeDepth, envPtr->maxExcRangeDepth);
+    range1 = CreateExceptionRange(LOOP_EXCEPTION_RANGE, envPtr);
+    range2 = CreateExceptionRange(LOOP_EXCEPTION_RANGE, envPtr);
+
+    /*
+     * Compile inline the next word: the initial command.
+     */
+
+    result = CompileCmdWordInline(interp, argInfo.startArray[0],
+	    (argInfo.endArray[0] + 1), flags, envPtr);
+    if (result != TCL_OK) {
+	if (result == TCL_ERROR) {
+            Tcl_AddObjErrorInfo(interp, "\n    (\"for\" initial command)", -1);
+        }
+	goto done;
+    }
+    maxDepth = envPtr->maxStackDepth;
+
+    /*
+     * Discard the start command's result.
+     */
+
+    TclEmitOpcode(INST_POP, envPtr);
+
+    /*
+     * Compile the next word: the test expression.
+     */
+
+    testCodeOffset = TclCurrCodeOffset();
+    envPtr->pushSimpleWords = 1;    /* process words normally */
+    result = CompileExprWord(interp, argInfo.startArray[1],
+	    (argInfo.endArray[1] + 1), flags, envPtr);
+    if (result != TCL_OK) {
+	if (result == TCL_ERROR) {
+            Tcl_AddObjErrorInfo(interp, "\n    (\"for\" test expression)", -1);
+        }
+	goto done;
+    }
+    maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
+
+    /*
+     * Emit the jump that terminates the for command if the test was
+     * false. We emit a one byte (relative) jump here, and replace it later
+     * with a four byte jump if the jump target is > 127 bytes away.
+     */
+
+    TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup);
+
+    /*
+     * Compile the loop body word inline. Also register the loop body's
+     * starting PC offset and byte length in the its ExceptionRange record.
+     */
+
+    envPtr->excRangeArrayPtr[range1].codeOffset = TclCurrCodeOffset();
+    result = CompileCmdWordInline(interp, argInfo.startArray[3],
+	    (argInfo.endArray[3] + 1), flags, envPtr);
+    if (result != TCL_OK) {
+	if (result == TCL_ERROR) {
+	    char msg[60];
+	    sprintf(msg, "\n    (\"for\" body line %d)", interp->errorLine);
+            Tcl_AddObjErrorInfo(interp, msg, -1);
+        }
+	goto done;
+    }
+    maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
+    envPtr->excRangeArrayPtr[range1].numCodeBytes =
+	(TclCurrCodeOffset() - envPtr->excRangeArrayPtr[range1].codeOffset);
+
+    /*
+     * Discard the loop body's result.
+     */
+
+    TclEmitOpcode(INST_POP, envPtr);
+
+    /*
+     * Finally, compile the "next" subcommand word inline.
+     */
+
+    envPtr->excRangeArrayPtr[range1].continueOffset = TclCurrCodeOffset();
+    envPtr->excRangeArrayPtr[range2].codeOffset = TclCurrCodeOffset();
+    result = CompileCmdWordInline(interp, argInfo.startArray[2],
+	    (argInfo.endArray[2] + 1), flags, envPtr);
+    if (result != TCL_OK) {
+	if (result == TCL_ERROR) {
+	    Tcl_AddObjErrorInfo(interp, "\n    (\"for\" loop-end command)", -1);
+	}
+	goto done;
+    }
+    maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
+    envPtr->excRangeArrayPtr[range2].numCodeBytes =
+	TclCurrCodeOffset() - envPtr->excRangeArrayPtr[range2].codeOffset;
+
+    /*
+     * Discard the "next" subcommand's result.
+     */
+
+    TclEmitOpcode(INST_POP, envPtr);
+	
+    /*
+     * Emit the unconditional jump back to the test at the top of the for
+     * loop. We generate a four byte jump if the distance to the test is
+     * greater than 120 bytes. This is conservative, and ensures that we
+     * won't have to replace this unconditional jump if we later need to
+     * replace the ifFalse jump with a four-byte jump.
+     */
+
+    jumpBackOffset = TclCurrCodeOffset();
+    jumpBackDist = (jumpBackOffset - testCodeOffset);
+    if (jumpBackDist > 120) {
+	TclEmitInstInt4(INST_JUMP4, /*offset*/ -jumpBackDist, envPtr);
+    } else {
+	TclEmitInstInt1(INST_JUMP1, /*offset*/ -jumpBackDist, envPtr);
+    }
+
+    /*
+     * Now that we know the target of the jumpFalse after the test, update
+     * it with the correct distance. If the distance is too great (more
+     * than 127 bytes), replace that jump with a four byte instruction and
+     * move the instructions after the jump down.
+     */
+
+    jumpDist = (TclCurrCodeOffset() - jumpFalseFixup.codeOffset);
+    if (TclFixupForwardJump(envPtr, &jumpFalseFixup, jumpDist, 127)) {
+	/*
+	 * Update the loop body's ExceptionRange record since it moved down:
+	 * i.e., increment both its start and continue PC offsets. Also,
+	 * update the "next" command's start PC offset in its ExceptionRange
+	 * record since it also moved down.
+	 */
+
+	envPtr->excRangeArrayPtr[range1].codeOffset += 3;
+	envPtr->excRangeArrayPtr[range1].continueOffset += 3;
+	envPtr->excRangeArrayPtr[range2].codeOffset += 3;
+
+	/*
+	 * Update the distance for the unconditional jump back to the test
+	 * at the top of the loop since it moved down 3 bytes too.
+	 */
+
+	jumpBackOffset += 3;
+	jumpPc = (envPtr->codeStart + jumpBackOffset);
+	if (jumpBackDist > 120) {
+	    jumpBackDist += 3;
+	    TclUpdateInstInt4AtPc(INST_JUMP4, /*offset*/ -jumpBackDist,
+				   jumpPc);
+	} else {
+	    jumpBackDist += 3;
+	    TclUpdateInstInt1AtPc(INST_JUMP1, /*offset*/ -jumpBackDist,
+				   jumpPc);
+	}
+    }
+    
+    /*
+     * The current PC offset (after the loop's body and "next" subcommand)
+     * is the loop's break target.
+     */
+
+    envPtr->excRangeArrayPtr[range1].breakOffset =
+	envPtr->excRangeArrayPtr[range2].breakOffset = TclCurrCodeOffset();
+    
+    /*
+     * Push an empty string object as the for command's result.
+     */
+
+    objIndex = TclObjIndexForString("", 0, /*allocStrRep*/ 0, /*inHeap*/ 0,
+				    envPtr);
+    TclEmitPush(objIndex, envPtr);
+    if (maxDepth == 0) {
+	maxDepth = 1;
+    }
+
+    done:
+    if (numWords == 0) {
+	envPtr->termOffset = 0;
+    } else {
+	envPtr->termOffset = (argInfo.endArray[numWords-1] + 1 - string);
+    }
+    envPtr->pushSimpleWords = savePushSimpleWords;
+    envPtr->maxStackDepth = maxDepth;
+    if (range1 != -1) {
+	envPtr->excRangeDepth--;
+    }
+    FreeArgInfo(&argInfo);
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileForeachCmd --
+ *
+ *	Procedure called to compile the "foreach" command.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is TCL_OK if
+ *	compilation was successful. If an error occurs then the
+ *	interpreter's result contains a standard error message and TCL_ERROR
+ *	is returned. If complation failed because the command is too complex
+ *	for TclCompileForeachCmd, TCL_OUT_LINE_COMPILE is returned
+ *	indicating that the foreach command should be compiled "out of line"
+ *	by emitting code to invoke its command procedure at runtime.
+ *
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one successfully processed.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the "while" command.
+ *
+ * Side effects:
+ *	Instructions are added to envPtr to evaluate the "foreach" command
+ *	at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileForeachCmd(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    char *string;		/* The source string to compile. */
+    char *lastChar;		/* Pointer to terminating character of
+				 * string. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    Proc *procPtr = envPtr->procPtr;
+    				/* Points to structure describing procedure
+				 * containing foreach command, else NULL. */
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute cmd. */
+    ArgInfo argInfo;		/* Structure holding information about the
+				 * start and end of each argument word. */
+    int numLists = 0;		/* Count of variable (and value) lists. */
+    int range = -1;		/* Index in the ExceptionRange array of the
+				 * ExceptionRange record for this loop. */
+    ForeachInfo *infoPtr;	/* Points to the structure describing this
+				 * foreach command. Stored in a AuxData
+				 * record in the ByteCode. */
+    JumpFixup jumpFalseFixup;	/* Used to update or replace the ifFalse
+				 * jump after test when its target PC is
+				 * determined. */
+    char savedChar;		/* Holds the char from string termporarily
+				 * replaced by a null character during
+				 * processing of argument words. */
+    int firstListTmp = -1;	/* If we decide to compile this foreach
+				 * command, this is the index or "slot
+				 * number" for the first temp var allocated
+				 * in the proc frame that holds a pointer to
+				 * a value list. Initialized to avoid a
+				 * compiler warning. */
+    int loopIterNumTmp;		/* If we decide to compile this foreach
+				 * command, the index for the temp var that
+				 * holds the current iteration count.  */
+    char *varListStart, *varListEnd, *valueListStart, *bodyStart, *bodyEnd;
+    unsigned char *jumpPc;
+    int jumpDist, jumpBackDist, jumpBackOffset;
+    int numWords, numVars, infoIndex, tmpIndex, objIndex, i, j, result;
+    int savePushSimpleWords = envPtr->pushSimpleWords;
+
+    /*
+     * We parse the variable list argument words and create two arrays:
+     *    varcList[i] gives the number of variables in the i-th var list
+     *    varvList[i] points to an array of the names in the i-th var list
+     * These are initially allocated on the stack, and are allocated on
+     * the heap if necessary.
+     */
+
+#define STATIC_VAR_LIST_SIZE 4
+    int varcListStaticSpace[STATIC_VAR_LIST_SIZE];
+    char **varvListStaticSpace[STATIC_VAR_LIST_SIZE];
+
+    int *varcList = varcListStaticSpace;
+    char ***varvList = varvListStaticSpace;
+
+    /*
+     * If the foreach command is at global level (not in a procedure),
+     * don't compile it inline: the payoff is too small.
+     */
+
+    if (procPtr == NULL) {
+	return TCL_OUT_LINE_COMPILE;
+    }
+
+    /*
+     * Scan the words of the command and record the start and finish of
+     * each argument word.
+     */
+
+    InitArgInfo(&argInfo);
+    result = CollectArgInfo(interp, string, lastChar, flags, &argInfo);
+    numWords = argInfo.numArgs;
+    if (result != TCL_OK) {
+	goto done;
+    }
+    if ((numWords < 3) || (numWords%2 != 1)) {
+	Tcl_ResetResult(interp);
+	Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	        "wrong # args: should be \"foreach varList list ?varList list ...? command\"", -1);
+        result = TCL_ERROR;
+	goto done;
+    }
+
+    /*
+     * Initialize the varcList and varvList arrays; allocate heap storage,
+     * if necessary, for them. Also make sure the variable names
+     * have no substitutions: that they're just "var" or "var(elem)"
+     */
+
+    numLists = (numWords - 1)/2;
+    if (numLists > STATIC_VAR_LIST_SIZE) {
+        varcList = (int *) ckalloc(numLists * sizeof(int));
+        varvList = (char ***) ckalloc(numLists * sizeof(char **));
+    }
+    for (i = 0;  i < numLists;  i++) {
+        varcList[i] = 0;
+        varvList[i] = (char **) NULL;
+    }
+    for (i = 0;  i < numLists;  i++) {
+	/*
+	 * Break each variable list into its component variables. If the
+	 * lists is enclosed in {}s or ""s, strip them off first.
+	 */
+
+	varListStart = argInfo.startArray[i*2];
+	varListEnd   = argInfo.endArray[i*2];
+	if ((*varListStart == '{') || (*varListStart == '"')) {
+	    if ((*varListEnd != '}') && (*varListEnd != '"')) {
+		Tcl_ResetResult(interp);
+		if (*varListStart == '"') {
+		    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+			    "extra characters after close-quote", -1);
+		} else {
+		    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		            "extra characters after close-brace", -1);
+		}
+		result = TCL_ERROR;
+		goto done;
+	    }
+	    varListStart++;
+	    varListEnd--;
+	}
+	    
+	/*
+	 * NOTE: THIS NEEDS TO BE CONVERTED TO AN OBJECT LIST.
+	 */
+
+	savedChar = *(varListEnd+1);
+	*(varListEnd+1) = '\0';
+	result = Tcl_SplitList(interp, varListStart,
+			       &varcList[i], &varvList[i]);
+	*(varListEnd+1) = savedChar;
+        if (result != TCL_OK) {
+            goto done;
+        }
+
+	/*
+	 * Check that each variable name has no substitutions and that
+	 * it is a local scalar name.
+	 */
+
+	numVars = varcList[i];
+	for (j = 0;  j < numVars;  j++) {
+	    char *varName = varvList[i][j];
+	    if (!IsLocalScalar(varName, (int) strlen(varName))) {
+		result = TCL_OUT_LINE_COMPILE;
+		goto done;
+	    }
+	}
+    }
+
+    /*
+     *==== At this point we believe we can compile the foreach command ====
+     */
+
+    /*
+     * Create and initialize a ExceptionRange record to hold information
+     * about this loop. This is used to implement break and continue.
+     */
+    
+    envPtr->excRangeDepth++;
+    envPtr->maxExcRangeDepth =
+	TclMax(envPtr->excRangeDepth, envPtr->maxExcRangeDepth);
+    range = CreateExceptionRange(LOOP_EXCEPTION_RANGE, envPtr);
+    
+    /*
+     * Reserve (numLists + 1) temporary variables:
+     *    - numLists temps for each value list
+     *    - a temp for the "next value" index into each value list
+     * At this time we don't try to reuse temporaries; if there are two
+     * nonoverlapping foreach loops, they don't share any temps.
+     */
+
+    for (i = 0;  i < numLists;  i++) {
+	tmpIndex = LookupCompiledLocal(NULL, /*nameChars*/ 0,
+		/*createIfNew*/ 1, /*flagsIfCreated*/ VAR_SCALAR, procPtr);
+	if (i == 0) {
+	    firstListTmp = tmpIndex;
+	}
+    }
+    loopIterNumTmp = LookupCompiledLocal(NULL, /*nameChars*/ 0,
+	    /*createIfNew*/ 1, /*flagsIfCreated*/ VAR_SCALAR, procPtr);
+    
+    /*
+     * Create and initialize the ForeachInfo and ForeachVarList data
+     * structures describing this command. Then create a AuxData record
+     * pointing to the ForeachInfo structure in the compilation environment.
+     */
+
+    infoPtr = (ForeachInfo *) ckalloc((unsigned)
+	    (sizeof(ForeachInfo) + (numLists * sizeof(ForeachVarList *))));
+    infoPtr->numLists = numLists;
+    infoPtr->firstListTmp = firstListTmp;
+    infoPtr->loopIterNumTmp = loopIterNumTmp;
+    for (i = 0;  i < numLists;  i++) {
+	ForeachVarList *varListPtr;
+	numVars = varcList[i];
+	varListPtr = (ForeachVarList *) ckalloc((unsigned)
+	        sizeof(ForeachVarList) + numVars*sizeof(int));
+	varListPtr->numVars = numVars;
+	for (j = 0;  j < numVars;  j++) {
+	    char *varName = varvList[i][j];
+	    int nameChars = strlen(varName);
+	    varListPtr->varIndexes[j] = LookupCompiledLocal(varName,
+		    nameChars, /*createIfNew*/ 1,
+                    /*flagsIfCreated*/ VAR_SCALAR, procPtr);
+	}
+	infoPtr->varLists[i] = varListPtr;
+    }
+    infoIndex = TclCreateAuxData((ClientData) infoPtr,
+            &tclForeachInfoType, envPtr);
+
+    /*
+     * Emit code to store each value list into the associated temporary.
+     */
+
+    for (i = 0;  i < numLists;  i++) {
+	valueListStart = argInfo.startArray[2*i + 1];
+	envPtr->pushSimpleWords = 1;
+	result = CompileWord(interp, valueListStart, lastChar, flags,
+		envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
+
+	tmpIndex = (firstListTmp + i);
+	if (tmpIndex <= 255) {
+	    TclEmitInstUInt1(INST_STORE_SCALAR1, tmpIndex, envPtr);
+	} else {
+	    TclEmitInstUInt4(INST_STORE_SCALAR4, tmpIndex, envPtr);
+	}
+	TclEmitOpcode(INST_POP, envPtr);
+    }
+
+    /*
+     * Emit the instruction to initialize the foreach loop's index temp var.
+     */
+
+    TclEmitInstUInt4(INST_FOREACH_START4, infoIndex, envPtr);
+    
+    /*
+     * Emit the top of loop code that assigns each loop variable and checks
+     * whether to terminate the loop.
+     */
+
+    envPtr->excRangeArrayPtr[range].continueOffset = TclCurrCodeOffset();
+    TclEmitInstUInt4(INST_FOREACH_STEP4, infoIndex, envPtr);
+
+    /*
+     * Emit the ifFalse jump that terminates the foreach if all value lists
+     * are exhausted. We emit a one byte (relative) jump here, and replace
+     * it later with a four byte jump if the jump target is more than
+     * 127 bytes away.
+     */
+
+    TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup);
+    
+    /*
+     * Compile the loop body word inline. Also register the loop body's
+     * starting PC offset and byte length in the ExceptionRange record.
+     */
+
+    bodyStart = argInfo.startArray[numWords - 1];
+    bodyEnd   = argInfo.endArray[numWords - 1];
+    savedChar = *(bodyEnd+1);
+    *(bodyEnd+1) = '\0';
+    envPtr->excRangeArrayPtr[range].codeOffset = TclCurrCodeOffset();
+    result = CompileCmdWordInline(interp, bodyStart, bodyEnd+1, flags,
+	    envPtr);
+    *(bodyEnd+1) = savedChar;
+    if (result != TCL_OK) {
+	if (result == TCL_ERROR) {
+	    char msg[60];
+	    sprintf(msg, "\n    (\"foreach\" body line %d)",
+		    interp->errorLine);
+            Tcl_AddObjErrorInfo(interp, msg, -1);
+        }
+	goto done;
+    }
+    maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
+    envPtr->excRangeArrayPtr[range].numCodeBytes =
+	TclCurrCodeOffset() - envPtr->excRangeArrayPtr[range].codeOffset;
+
+    /*
+     * Discard the loop body's result.
+     */
+
+    TclEmitOpcode(INST_POP, envPtr);
+	
+    /*
+     * Emit the unconditional jump back to the test at the top of the
+     * loop. We generate a four byte jump if the distance to the to of
+     * the foreach is greater than 120 bytes. This is conservative and
+     * ensures that we won't have to replace this unconditional jump if
+     * we later need to replace the ifFalse jump with a four-byte jump.
+     */
+
+    jumpBackOffset = TclCurrCodeOffset();
+    jumpBackDist =
+	(jumpBackOffset - envPtr->excRangeArrayPtr[range].continueOffset);
+    if (jumpBackDist > 120) {
+	TclEmitInstInt4(INST_JUMP4, /*offset*/ -jumpBackDist, envPtr);
+    } else {
+	TclEmitInstInt1(INST_JUMP1, /*offset*/ -jumpBackDist, envPtr);
+    }
+
+    /*
+     * Now that we know the target of the jumpFalse after the foreach_step
+     * test, update it with the correct distance. If the distance is too
+     * great (more than 127 bytes), replace that jump with a four byte
+     * instruction and move the instructions after the jump down.
+     */
+
+    jumpDist = (TclCurrCodeOffset() - jumpFalseFixup.codeOffset);
+    if (TclFixupForwardJump(envPtr, &jumpFalseFixup, jumpDist, 127)) {
+	/*
+	 * Update the loop body's starting PC offset since it moved down.
+	 */
+
+	envPtr->excRangeArrayPtr[range].codeOffset += 3;
+
+	/*
+	 * Update the distance for the unconditional jump back to the test
+	 * at the top of the loop since it moved down 3 bytes too.
+	 */
+
+	jumpBackOffset += 3;
+	jumpPc = (envPtr->codeStart + jumpBackOffset);
+	if (jumpBackDist > 120) {
+	    jumpBackDist += 3;
+	    TclUpdateInstInt4AtPc(INST_JUMP4, /*offset*/ -jumpBackDist,
+				   jumpPc);
+	} else {
+	    jumpBackDist += 3;
+	    TclUpdateInstInt1AtPc(INST_JUMP1, /*offset*/ -jumpBackDist,
+				   jumpPc);
+	}
+    }
+
+    /*
+     * The current PC offset (after the loop's body) is the loop's
+     * break target.
+     */
+
+    envPtr->excRangeArrayPtr[range].breakOffset = TclCurrCodeOffset();
+    
+    /*
+     * Push an empty string object as the foreach command's result.
+     */
+
+    objIndex = TclObjIndexForString("", 0, /*allocStrRep*/ 0, /*inHeap*/ 0,
+				    envPtr);
+    TclEmitPush(objIndex, envPtr);
+    if (maxDepth == 0) {
+	maxDepth = 1;
+    }
+
+    done:
+    for (i = 0;  i < numLists;  i++) {
+        if (varvList[i] != (char **) NULL) {
+            ckfree((char *) varvList[i]);
+        }
+    }
+    if (varcList != varcListStaticSpace) {
+	ckfree((char *) varcList);
+        ckfree((char *) varvList);
+    }
+    envPtr->termOffset = (argInfo.endArray[numWords-1] + 1 - string);
+    envPtr->pushSimpleWords = savePushSimpleWords;
+    envPtr->maxStackDepth = maxDepth;
+    if (range != -1) {
+	envPtr->excRangeDepth--;
+    }
+    FreeArgInfo(&argInfo);
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupForeachInfo --
+ *
+ *	This procedure duplicates a ForeachInfo structure created as
+ *	auxiliary data during the compilation of a foreach command.
+ *
+ * Results:
+ *	A pointer to a newly allocated copy of the existing ForeachInfo
+ *	structure is returned.
+ *
+ * Side effects:
+ *	Storage for the copied ForeachInfo record is allocated. If the
+ *	original ForeachInfo structure pointed to any ForeachVarList
+ *	records, these structures are also copied and pointers to them
+ *	are stored in the new ForeachInfo record.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static ClientData
+DupForeachInfo(clientData)
+    ClientData clientData;	/* The foreach command's compilation
+				 * auxiliary data to duplicate. */
+{
+    register ForeachInfo *srcPtr = (ForeachInfo *) clientData;
+    ForeachInfo *dupPtr;
+    register ForeachVarList *srcListPtr, *dupListPtr;
+    int numLists = srcPtr->numLists;
+    int numVars, i, j;
+    
+    dupPtr = (ForeachInfo *) ckalloc((unsigned)
+	    (sizeof(ForeachInfo) + (numLists * sizeof(ForeachVarList *))));
+    dupPtr->numLists = numLists;
+    dupPtr->firstListTmp = srcPtr->firstListTmp;
+    dupPtr->loopIterNumTmp = srcPtr->loopIterNumTmp;
+    
+    for (i = 0;  i < numLists;  i++) {
+	srcListPtr = srcPtr->varLists[i];
+	numVars = srcListPtr->numVars;
+	dupListPtr = (ForeachVarList *) ckalloc((unsigned)
+	        sizeof(ForeachVarList) + numVars*sizeof(int));
+	dupListPtr->numVars = numVars;
+	for (j = 0;  j < numVars;  j++) {
+	    dupListPtr->varIndexes[j] =	srcListPtr->varIndexes[j];
+	}
+	dupPtr->varLists[i] = dupListPtr;
+    }
+    return (ClientData) dupPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeForeachInfo --
+ *
+ *	Procedure to free a ForeachInfo structure created as auxiliary data
+ *	during the compilation of a foreach command.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Storage for the ForeachInfo structure pointed to by the ClientData
+ *	argument is freed as is any ForeachVarList record pointed to by the
+ *	ForeachInfo structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeForeachInfo(clientData)
+    ClientData clientData;	/* The foreach command's compilation
+				 * auxiliary data to free. */
+{
+    register ForeachInfo *infoPtr = (ForeachInfo *) clientData;
+    register ForeachVarList *listPtr;
+    int numLists = infoPtr->numLists;
+    register int i;
+
+    for (i = 0;  i < numLists;  i++) {
+	listPtr = infoPtr->varLists[i];
+	ckfree((char *) listPtr);
+    }
+    ckfree((char *) infoPtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileIfCmd --
+ *
+ *	Procedure called to compile the "if" command.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is TCL_OK unless
+ *	there was an error while parsing string. If an error occurs then
+ *	the interpreter's result contains a standard error message.
+ *
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one successfully processed.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the command.
+ *
+ * Side effects:
+ *	Instructions are added to envPtr to evaluate the "if" command
+ *	at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileIfCmd(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    char *string;		/* The source string to compile. */
+    char *lastChar;		/* Pointer to terminating character of
+				 * string. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    register char *src = string;/* Points to current source char. */
+    register int type;		/* Current char's CHAR_TYPE type. */
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute cmd. */
+    JumpFixupArray jumpFalseFixupArray;
+    				/* Used to fix up the ifFalse jump after
+				 * each "if"/"elseif" test when its target
+				 * PC is determined. */
+    JumpFixupArray jumpEndFixupArray;
+				/* Used to fix up the unconditional jump
+				 * after each "then" command to the end of
+				 * the "if" when that PC is determined. */
+    char *testSrcStart;
+    int jumpDist, jumpFalseDist, jumpIndex, objIndex, j, result;
+    unsigned char *ifFalsePc;
+    unsigned char opCode;
+    int savePushSimpleWords = envPtr->pushSimpleWords;
+
+    /*
+     * Loop compiling "expr then body" clauses after an "if" or "elseif".
+     */
+
+    TclInitJumpFixupArray(&jumpFalseFixupArray);
+    TclInitJumpFixupArray(&jumpEndFixupArray);
+    while (1) {	
+	/*
+	 * At this point in the loop, we have an expression to test, either
+	 * the main expression or an expression following an "elseif".
+	 * The arguments after the expression must be "then" (optional) and
+	 * a script to execute if the expression is true.
+	 */
+
+	AdvanceToNextWord(src, envPtr);
+	src += envPtr->termOffset;
+	type = CHAR_TYPE(src, lastChar);
+	if (type == TCL_COMMAND_END) {
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		    "wrong # args: no expression after \"if\" argument", -1);
+	    result = TCL_ERROR;
+	    goto done;
+	}
+
+	/*
+	 * Compile the "if"/"elseif" test expression.
+	 */
+	
+	testSrcStart = src;
+	envPtr->pushSimpleWords = 1;
+	result = CompileExprWord(interp, src, lastChar, flags, envPtr);
+	if (result != TCL_OK) {
+	    if (result == TCL_ERROR) {
+		Tcl_AddObjErrorInfo(interp,
+		        "\n    (\"if\" test expression)", -1);
+	    }
+	    goto done;
+	}
+	maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
+	src += envPtr->termOffset;
+
+	/*
+	 * Emit the ifFalse jump around the "then" part if the test was
+	 * false. We emit a one byte (relative) jump here, and replace it
+	 * later with a four byte jump if the jump target is more than 127
+	 * bytes away. 
+	 */
+
+	if (jumpFalseFixupArray.next >= jumpFalseFixupArray.end) {
+	    TclExpandJumpFixupArray(&jumpFalseFixupArray);
+	}
+	jumpIndex = jumpFalseFixupArray.next;
+	jumpFalseFixupArray.next++;
+	TclEmitForwardJump(envPtr, TCL_FALSE_JUMP,
+		&(jumpFalseFixupArray.fixup[jumpIndex]));
+	
+	/*
+	 * Skip over the optional "then" before the then clause.
+	 */
+
+	AdvanceToNextWord(src, envPtr);
+	src += envPtr->termOffset;
+	type = CHAR_TYPE(src, lastChar);
+	if (type == TCL_COMMAND_END) {
+	    char buf[100];
+	    sprintf(buf, "wrong # args: no script following \"%.20s\" argument", testSrcStart);
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
+	    result = TCL_ERROR;
+	    goto done;
+	}
+	if ((*src == 't') && (strncmp(src, "then", 4) == 0)) {
+	    type = CHAR_TYPE(src+4, lastChar);
+	    if ((type == TCL_SPACE) || (type == TCL_COMMAND_END)) {
+		src += 4;
+		AdvanceToNextWord(src, envPtr); 
+		src += envPtr->termOffset;
+		type = CHAR_TYPE(src, lastChar);
+		if (type == TCL_COMMAND_END) {
+		    Tcl_ResetResult(interp);
+		    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		            "wrong # args: no script following \"then\" argument", -1);
+		    result = TCL_ERROR;
+		    goto done;
+		}
+	    }
+	}
+
+	/*
+	 * Compile the "then" command word inline.
+	 */
+
+	result = CompileCmdWordInline(interp, src, lastChar, flags, envPtr);
+	if (result != TCL_OK) {
+	    if (result == TCL_ERROR) {
+		char msg[60];
+		sprintf(msg, "\n    (\"if\" then script line %d)",
+		        interp->errorLine);
+		Tcl_AddObjErrorInfo(interp, msg, -1);
+	    }
+	    goto done;
+	}
+	maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
+	src += envPtr->termOffset;
+
+	/*
+	 * Emit an unconditional jump to the end of the "if" command. We
+	 * emit a one byte jump here, and replace it later with a four byte
+	 * jump if the jump target is more than 127 bytes away. Note that
+	 * both the jumpFalseFixupArray and the jumpEndFixupArray are
+	 * indexed by the same index, "jumpIndex".
+	 */
+
+	if (jumpEndFixupArray.next >= jumpEndFixupArray.end) {
+	    TclExpandJumpFixupArray(&jumpEndFixupArray);
+	}
+	jumpEndFixupArray.next++;
+	TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP,
+		&(jumpEndFixupArray.fixup[jumpIndex]));
+
+ 	/*
+	 * Now that we know the target of the jumpFalse after the if test,
+         * update it with the correct distance. We generate a four byte
+	 * jump if the distance is greater than 120 bytes. This is
+	 * conservative, and ensures that we won't have to replace this
+	 * jump if we later also need to replace the preceeding
+	 * unconditional jump to the end of the "if" with a four-byte jump.
+         */
+
+	jumpDist = (TclCurrCodeOffset() - jumpFalseFixupArray.fixup[jumpIndex].codeOffset);
+	if (TclFixupForwardJump(envPtr,
+	        &(jumpFalseFixupArray.fixup[jumpIndex]), jumpDist, 120)) {
+	    /*
+	     * Adjust the code offset for the unconditional jump at the end
+	     * of the last "then" clause.
+	     */
+
+	    jumpEndFixupArray.fixup[jumpIndex].codeOffset += 3;
+	}
+
+	/*
+	 * Check now for a "elseif" word. If we find one, keep looping.
+	 */
+
+	AdvanceToNextWord(src, envPtr);
+	src += envPtr->termOffset;
+	type = CHAR_TYPE(src, lastChar);
+	if ((type != TCL_COMMAND_END)
+	        && ((*src == 'e') && (strncmp(src, "elseif", 6) == 0))) {
+	    type = CHAR_TYPE(src+6, lastChar);
+	    if ((type == TCL_SPACE) || (type == TCL_COMMAND_END)) {
+		src += 6;
+		AdvanceToNextWord(src, envPtr); 
+		src += envPtr->termOffset;
+		type = CHAR_TYPE(src, lastChar);
+		if (type == TCL_COMMAND_END) {
+		    Tcl_ResetResult(interp);
+		    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		            "wrong # args: no expression after \"elseif\" argument", -1);
+		    result = TCL_ERROR;
+		    goto done;
+		}
+		continue;	  /* continue the "expr then body" loop */
+	    }
+	}
+	break;
+    } /* end of the "expr then body" loop */
+
+    /*
+     * No more "elseif expr then body" clauses. Check now for an "else"
+     * clause. If there is another word, we are at its start.
+     */
+
+    if (type != TCL_COMMAND_END) {
+	if ((*src == 'e') && (strncmp(src, "else", 4) == 0)) {
+	    type = CHAR_TYPE(src+4, lastChar);
+	    if ((type == TCL_SPACE) || (type == TCL_COMMAND_END)) {
+		src += 4;
+		AdvanceToNextWord(src, envPtr); 
+		src += envPtr->termOffset;
+		type = CHAR_TYPE(src, lastChar);
+		if (type == TCL_COMMAND_END) {
+		    Tcl_ResetResult(interp);
+		    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		            "wrong # args: no script following \"else\" argument", -1);
+		    result = TCL_ERROR;
+		    goto done;
+		}
+	    }
+	}
+
+	/*
+	 * Compile the "else" command word inline.
+	 */
+
+	result = CompileCmdWordInline(interp, src, lastChar, flags, envPtr);
+	if (result != TCL_OK) {
+	    if (result == TCL_ERROR) {
+		char msg[60];
+		sprintf(msg, "\n    (\"if\" else script line %d)",
+		        interp->errorLine);
+		Tcl_AddObjErrorInfo(interp, msg, -1);
+	    }
+	    goto done;
+	}
+	maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
+	src += envPtr->termOffset;
+    
+	/*
+	 * Skip over white space until the end of the command.
+	 */
+	
+	type = CHAR_TYPE(src, lastChar);
+	if (type != TCL_COMMAND_END) {
+	    AdvanceToNextWord(src, envPtr);
+	    src += envPtr->termOffset;
+	    type = CHAR_TYPE(src, lastChar);
+	    if (type != TCL_COMMAND_END) {
+		Tcl_ResetResult(interp);
+		Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		        "wrong # args: extra words after \"else\" clause in \"if\" command", -1);
+		result = TCL_ERROR;
+		goto done;
+	    }
+	}
+    } else {
+	/*
+	 * The "if" command has no "else" clause: push an empty string
+	 * object as its result.
+	 */
+
+	objIndex = TclObjIndexForString("", 0, /*allocStrRep*/ 0,
+		/*inHeap*/ 0, envPtr);
+	TclEmitPush(objIndex, envPtr);
+	maxDepth = TclMax(1, maxDepth);
+    }
+
+    /*
+     * Now that we know the target of the unconditional jumps to the end of
+     * the "if" command, update them with the correct distance. If the
+     * distance is too great (> 127 bytes), replace the jump with a four
+     * byte instruction and move instructions after the jump down.
+     */
+    
+    for (j = jumpEndFixupArray.next;  j > 0;  j--) {
+	jumpIndex = (j - 1);	/* i.e. process the closest jump first */
+	jumpDist = (TclCurrCodeOffset() - jumpEndFixupArray.fixup[jumpIndex].codeOffset);
+	if (TclFixupForwardJump(envPtr,
+	        &(jumpEndFixupArray.fixup[jumpIndex]), jumpDist, 127)) {
+	    /*
+	     * Adjust the jump distance for the "ifFalse" jump that
+	     * immediately preceeds this jump. We've moved it's target
+	     * (just after this unconditional jump) three bytes down.
+	     */
+
+	    ifFalsePc = (envPtr->codeStart + jumpFalseFixupArray.fixup[jumpIndex].codeOffset);
+	    opCode = *ifFalsePc;
+	    if (opCode == INST_JUMP_FALSE1) {
+		jumpFalseDist = TclGetInt1AtPtr(ifFalsePc + 1);
+		jumpFalseDist += 3;
+		TclStoreInt1AtPtr(jumpFalseDist, (ifFalsePc + 1));
+	    } else if (opCode == INST_JUMP_FALSE4) {
+		jumpFalseDist = TclGetInt4AtPtr(ifFalsePc + 1);
+		jumpFalseDist += 3;
+		TclStoreInt4AtPtr(jumpFalseDist, (ifFalsePc + 1));
+	    } else {
+		panic("TclCompileIfCmd: unexpected opcode updating ifFalse jump");
+	    }
+	}
+    }
+	
+    /*
+     * Free the jumpFixupArray array if malloc'ed storage was used.
+     */
+
+    done:
+    TclFreeJumpFixupArray(&jumpFalseFixupArray);
+    TclFreeJumpFixupArray(&jumpEndFixupArray);
+    envPtr->termOffset = (src - string);
+    envPtr->maxStackDepth = maxDepth;
+    envPtr->pushSimpleWords = savePushSimpleWords;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileIncrCmd --
+ *
+ *	Procedure called to compile the "incr" command.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is TCL_OK unless
+ *	there was an error while parsing string. If an error occurs then
+ *	the interpreter's result contains a standard error message.
+ *
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one successfully processed.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the "incr" command.
+ *
+ * Side effects:
+ *	Instructions are added to envPtr to evaluate the "incr" command
+ *	at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileIncrCmd(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    char *string;		/* The source string to compile. */
+    char *lastChar;		/* Pointer to terminating character of
+				 * string. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    Proc *procPtr = envPtr->procPtr;
+    				/* Points to structure describing procedure
+				 * containing incr command, else NULL. */
+    register char *src = string;
+    				/* Points to current source char. */
+    register int type;		/* Current char's CHAR_TYPE type. */
+    int simpleVarName;		/* 1 if name is just sequence of chars with
+                                 * an optional element name in parens. */
+    char *name = NULL;		/* If simpleVarName, points to first char of
+				 * variable name and nameChars is length.
+				 * Otherwise NULL. */
+    char *elName = NULL;	/* If simpleVarName, points to first char of
+				 * element name and elNameChars is length.
+				 * Otherwise NULL. */
+    int nameChars = 0;		/* Length of the var name. Initialized to
+				 * avoid a compiler warning. */
+    int elNameChars = 0;	/* Length of array's element name, if any.
+				 * Initialized to avoid a compiler
+				 * warning. */
+    int incrementGiven;		/* 1 if an increment amount was given. */
+    int isImmIncrValue = 0;	/* 1 if increment amount is a literal
+				 * integer in [-127..127]. */
+    int immIncrValue = 0;	/* if isImmIncrValue is 1, the immediate
+				 * integer value. */
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute cmd. */
+    int localIndex = -1;	/* Index of the variable in the current
+				 * procedure's array of local variables.
+				 * Otherwise -1 if not in a procedure or
+				 * the variable wasn't found. */
+    char savedChar;		/* Holds the character from string
+				 * termporarily replaced by a null char
+				 * during name processing. */
+    int objIndex;		/* The object array index for a pushed
+				 * object holding a name part. */
+    int savePushSimpleWords = envPtr->pushSimpleWords;
+    char *p;
+    int i, result;
+
+    /*
+     * Parse the next word: the variable name. If it is "simple" (requires
+     * no substitutions at runtime), divide it up into a simple "name" plus
+     * an optional "elName". Otherwise, if not simple, just push the name.
+     */
+
+    AdvanceToNextWord(src, envPtr);
+    src += envPtr->termOffset;
+    type = CHAR_TYPE(src, lastChar);
+    if (type == TCL_COMMAND_END) {
+	badArgs:
+	Tcl_ResetResult(interp);
+	Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	        "wrong # args: should be \"incr varName ?increment?\"", -1);
+	result = TCL_ERROR;
+	goto done;
+    }
+    
+    envPtr->pushSimpleWords = 0;
+    result = CompileWord(interp, src, lastChar, flags, envPtr);
+    if (result != TCL_OK) {
+	goto done;
+    }
+    simpleVarName = envPtr->wordIsSimple;
+    if (simpleVarName) {
+	name = src;
+	nameChars = envPtr->numSimpleWordChars;
+	if (type & (TCL_QUOTE | TCL_OPEN_BRACE)) {
+	    name++;
+	}
+	elName = NULL;
+	elNameChars = 0;
+	p = name;
+	for (i = 0;  i < nameChars;  i++) {
+	    if (*p == '(') {
+		char *openParen = p;
+		p = (src + nameChars-1);	
+		if (*p == ')') { /* last char is ')' => array reference */
+		    nameChars = (openParen - name);
+		    elName = openParen+1;
+		    elNameChars = (p - elName);
+		}
+		break;
+	    }
+	    p++;
+	}
+    } else {
+        maxDepth = envPtr->maxStackDepth;
+    }
+    src += envPtr->termOffset;
+
+    /*
+     * See if there is a next word. If so, we are incrementing the variable
+     * by that value (which must be an integer).
+     */
+
+    incrementGiven = 0;
+    type = CHAR_TYPE(src, lastChar);
+    if (type != TCL_COMMAND_END) {
+	AdvanceToNextWord(src, envPtr);
+	src += envPtr->termOffset;
+	type = CHAR_TYPE(src, lastChar);
+	incrementGiven = (type != TCL_COMMAND_END);
+    }
+
+    /*
+     * Non-simple names have already been pushed. If this is a simple
+     * variable, either push its name (if a global or an unknown local
+     * variable) or look up the variable's local frame index. If a local is
+     * not found, push its name and do the lookup at runtime. If this is an
+     * array reference, also push the array element.
+     */
+
+    if (simpleVarName) {
+	if (procPtr == NULL) {
+	    savedChar = name[nameChars];
+	    name[nameChars] = '\0';
+	    objIndex = TclObjIndexForString(name, nameChars,
+		    /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr);
+	    name[nameChars] = savedChar;
+	    TclEmitPush(objIndex, envPtr);
+	    maxDepth = 1;
+	} else {
+	    localIndex = LookupCompiledLocal(name, nameChars,
+	            /*createIfNew*/ 0, /*flagsIfCreated*/ 0,
+		    envPtr->procPtr);
+	    if ((localIndex < 0) || (localIndex > 255)) {
+		if (localIndex > 255) {	      /* we'll push the name */
+		    localIndex = -1;
+		}
+		savedChar = name[nameChars];
+		name[nameChars] = '\0';
+		objIndex = TclObjIndexForString(name, nameChars,
+			/*allocStrRep*/ 1, /*inHeap*/ 0, envPtr);
+		name[nameChars] = savedChar;
+		TclEmitPush(objIndex, envPtr);
+		maxDepth = 1;
+	    } else {
+		maxDepth = 0;
+	    }
+	}
+	
+	if (elName != NULL) {
+	    /*
+	     * Parse and push the array element's name. Perform
+	     * substitutions on it, just as is done for quoted strings.
+	     */
+
+	    savedChar = elName[elNameChars];
+	    elName[elNameChars] = '\0';
+	    envPtr->pushSimpleWords = 1;
+	    result = TclCompileQuotes(interp, elName, elName+elNameChars,
+		    0, flags, envPtr);
+	    elName[elNameChars] = savedChar;
+	    if (result != TCL_OK) {
+		char msg[200];
+		sprintf(msg, "\n    (parsing index for array \"%.*s\")",
+			TclMin(nameChars, 100), name);
+		Tcl_AddObjErrorInfo(interp, msg, -1);
+		goto done;
+	    }
+	    maxDepth += envPtr->maxStackDepth;
+	}
+    }
+
+    /*
+     * If an increment was given, push the new value.
+     */
+    
+    if (incrementGiven) {
+	type = CHAR_TYPE(src, lastChar);
+	envPtr->pushSimpleWords = 0;
+	result = CompileWord(interp, src, lastChar, flags, envPtr);
+	if (result != TCL_OK) {
+	    if (result == TCL_ERROR) {
+		Tcl_AddObjErrorInfo(interp,
+		        "\n    (increment expression)", -1);
+	    }
+	    goto done;
+	}
+	if (type & (TCL_QUOTE | TCL_OPEN_BRACE)) {
+	    src++;
+	}
+	if (envPtr->wordIsSimple) {
+	    /*
+	     * See if the word represents an integer whose formatted
+	     * representation is the same as the word (e.g., this is
+	     * true for 123 and -1 but not for 00005). If so, just
+	     * push an integer object.
+	     */
+	    
+	    int isCompilableInt = 0;
+	    int numChars = envPtr->numSimpleWordChars;
+	    char savedChar = src[numChars];
+	    char buf[40];
+	    Tcl_Obj *objPtr;
+	    long n;
+
+	    src[numChars] = '\0';
+	    if (TclLooksLikeInt(src)) {
+		int code = TclGetLong(interp, src, &n);
+		if (code == TCL_OK) {
+		    if ((-127 <= n) && (n <= 127)) {
+			isCompilableInt = 1;
+			isImmIncrValue = 1;
+			immIncrValue = n;
+		    } else {
+			TclFormatInt(buf, n);
+			if (strcmp(src, buf) == 0) {
+			    isCompilableInt = 1;
+			    isImmIncrValue = 0;
+			    objIndex = TclObjIndexForString(src, numChars,
+                                /*allocStrRep*/ 0, /*inHeap*/ 0, envPtr);
+			    objPtr = envPtr->objArrayPtr[objIndex];
+
+			    Tcl_InvalidateStringRep(objPtr);
+			    objPtr->internalRep.longValue = n;
+			    objPtr->typePtr = &tclIntType;
+			    
+			    TclEmitPush(objIndex, envPtr);
+			    maxDepth += 1;
+			}
+		    }
+		} else {
+		    Tcl_ResetResult(interp);
+		}
+	    }
+	    if (!isCompilableInt) {
+		objIndex = TclObjIndexForString(src, numChars,
+			/*allocStrRep*/ 1, /*inHeap*/ 0, envPtr);
+		TclEmitPush(objIndex, envPtr);
+		maxDepth += 1;
+	    }
+	    src[numChars] = savedChar;
+	} else {
+	    maxDepth += envPtr->maxStackDepth;
+	}
+	if (type & (TCL_QUOTE | TCL_OPEN_BRACE)) {
+	    src += (envPtr->termOffset - 1); /* already advanced 1 above */
+	} else {
+	    src += envPtr->termOffset;
+	}
+    } else {			/* no incr amount given so use 1 */
+	isImmIncrValue = 1;
+	immIncrValue = 1;
+    }
+    
+    /*
+     * Now emit instructions to increment the variable.
+     */
+
+    if (simpleVarName) {
+	if (elName == NULL) {  /* scalar */
+	    if (localIndex >= 0) {
+		if (isImmIncrValue) {
+		    TclEmitInstUInt1(INST_INCR_SCALAR1_IMM, localIndex,
+				    envPtr);
+		    TclEmitInt1(immIncrValue, envPtr);
+		} else {
+		    TclEmitInstUInt1(INST_INCR_SCALAR1, localIndex, envPtr);
+		}
+	    } else {
+		if (isImmIncrValue) {
+		    TclEmitInstInt1(INST_INCR_SCALAR_STK_IMM, immIncrValue,
+				   envPtr);
+		} else {
+		    TclEmitOpcode(INST_INCR_SCALAR_STK, envPtr);
+		}
+	    }
+	} else {		/* array */
+	    if (localIndex >= 0) {
+		if (isImmIncrValue) {
+		    TclEmitInstUInt1(INST_INCR_ARRAY1_IMM, localIndex,
+				    envPtr);
+		    TclEmitInt1(immIncrValue, envPtr);
+		} else {
+		    TclEmitInstUInt1(INST_INCR_ARRAY1, localIndex, envPtr);
+		}
+	    } else {
+		if (isImmIncrValue) {
+		    TclEmitInstInt1(INST_INCR_ARRAY_STK_IMM, immIncrValue,
+				   envPtr);
+		} else {
+		    TclEmitOpcode(INST_INCR_ARRAY_STK, envPtr);
+		}
+	    }
+	}
+    } else {			/* non-simple variable name */
+	if (isImmIncrValue) {
+	    TclEmitInstInt1(INST_INCR_STK_IMM, immIncrValue, envPtr);
+	} else {
+	    TclEmitOpcode(INST_INCR_STK, envPtr);
+	}
+    }
+	
+    /*
+     * Skip over white space until the end of the command.
+     */
+
+    type = CHAR_TYPE(src, lastChar);
+    if (type != TCL_COMMAND_END) {
+	AdvanceToNextWord(src, envPtr);
+	src += envPtr->termOffset;
+	type = CHAR_TYPE(src, lastChar);
+	if (type != TCL_COMMAND_END) {
+	    goto badArgs;
+	}
+    }
+
+    done:
+    envPtr->termOffset = (src - string);
+    envPtr->maxStackDepth = maxDepth;
+    envPtr->pushSimpleWords = savePushSimpleWords;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileSetCmd --
+ *
+ *	Procedure called to compile the "set" command.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is normally TCL_OK
+ *	unless there was an error while parsing string. If an error occurs
+ *	then the interpreter's result contains a standard error message. If
+ *	complation fails because the set command requires a second level of
+ *	substitutions, TCL_OUT_LINE_COMPILE is returned indicating that the
+ *	set command should be compiled "out of line" by emitting code to
+ *	invoke its command procedure (Tcl_SetCmd) at runtime.
+ *
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one successfully processed.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the incr command.
+ *
+ * Side effects:
+ *	Instructions are added to envPtr to evaluate the "set" command
+ *	at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileSetCmd(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    char *string;		/* The source string to compile. */
+    char *lastChar;		/* Pointer to terminating character of
+				 * string. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    Proc *procPtr = envPtr->procPtr;
+				/* Points to structure describing procedure
+				 * containing the set command, else NULL. */
+    ArgInfo argInfo;		/* Structure holding information about the
+				 * start and end of each argument word. */
+    int simpleVarName;		/* 1 if name is just sequence of chars with
+                                 * an optional element name in parens. */
+    char *elName = NULL;	/* If simpleVarName, points to first char of
+				 * element name and elNameChars is length.
+				 * Otherwise NULL. */
+    int isAssignment;		/* 1 if assigning value to var, else 0. */
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute cmd. */
+    int localIndex = -1;	/* Index of the variable in the current
+				 * procedure's array of local variables.
+				 * Otherwise -1 if not in a procedure, the
+				 * name contains "::"s, or the variable
+				 * wasn't found. */
+    char savedChar;		/* Holds the character from string
+				 * termporarily replaced by a null char
+				 * during name processing. */
+    int objIndex = -1;		/* The object array index for a pushed
+				 * object holding a name part. Initialized
+				 * to avoid a compiler warning. */
+    char *wordStart, *p;
+    int numWords, isCompilableInt, i, result;
+    Tcl_Obj *objPtr;
+    int savePushSimpleWords = envPtr->pushSimpleWords;
+
+    /*
+     * Scan the words of the command and record the start and finish of
+     * each argument word.
+     */
+
+    InitArgInfo(&argInfo);
+    result = CollectArgInfo(interp, string, lastChar, flags, &argInfo);
+    numWords = argInfo.numArgs;	  /* i.e., the # after the command name */
+    if (result != TCL_OK) {
+	goto done;
+    }
+    if ((numWords < 1) || (numWords > 2)) {
+	Tcl_ResetResult(interp);
+	Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	        "wrong # args: should be \"set varName ?newValue?\"", -1);
+        result = TCL_ERROR;
+	goto done;
+    }
+    isAssignment = (numWords == 2);
+
+    /*
+     * Parse the next word: the variable name. If the name is enclosed in
+     * quotes or braces, we return TCL_OUT_LINE_COMPILE and call the set
+     * command procedure at runtime since this makes sure that a second
+     * round of substitutions is done properly. 
+     */
+
+    wordStart = argInfo.startArray[0]; /* start of 1st arg word: varname */
+    if ((*wordStart == '{') || (*wordStart == '"')) {
+	result = TCL_OUT_LINE_COMPILE;
+	goto done;
+    }
+
+    /*
+     * Check whether the name is "simple": requires no substitutions at
+     * runtime.
+     */
+    
+    envPtr->pushSimpleWords = 0;
+    result = CompileWord(interp, wordStart, argInfo.endArray[0] + 1,
+	    flags, envPtr);
+    if (result != TCL_OK) {
+	goto done;
+    }
+    simpleVarName = envPtr->wordIsSimple;
+    
+    if (!simpleVarName) {
+	/*
+	 * The name isn't simple. CompileWord already pushed it.
+	 */
+	
+	maxDepth = envPtr->maxStackDepth;
+    } else {
+	char *name;		/* If simpleVarName, points to first char of
+				 * variable name and nameChars is length.
+				 * Otherwise NULL. */
+	int nameChars;		/* Length of the var name. */
+	int nameHasNsSeparators = 0;
+				/* Set 1 if name contains "::"s. */
+	int elNameChars;	/* Length of array's element name if any. */
+
+	/*
+	 * A simple name. First divide it up into "name" plus "elName"
+	 * for an array element name, if any.
+	 */
+	
+	name = wordStart;
+	nameChars = envPtr->numSimpleWordChars;
+	elName = NULL;
+	elNameChars = 0;
+	
+	p = name;
+	for (i = 0;  i < nameChars;  i++) {
+	    if (*p == '(') {
+		char *openParen = p;
+		p = (name + nameChars-1);	
+		if (*p == ')') { /* last char is ')' => array reference */
+		    nameChars = (openParen - name);
+		    elName = openParen+1;
+		    elNameChars = (p - elName);
+		}
+		break;
+	    }
+	    p++;
+	}
+
+	/*
+	 * Determine if name has any namespace separators (::'s).
+	 */
+
+	p = name;
+	for (i = 0;  i < nameChars;  i++) {
+	    if ((*p == ':') && ((i+1) < nameChars) && (*(p+1) == ':')) {
+		nameHasNsSeparators = 1;
+		break;
+	    }
+	    p++;
+	}
+
+	/*
+	 * Now either push the name or determine its index in the array of
+	 * local variables in a procedure frame. Note that if we are
+	 * compiling a procedure the variable must be local unless its
+	 * name has namespace separators ("::"s). Note also that global
+	 * variables are implemented by a local variable that "points" to
+	 * the real global. There are two cases:
+	 *   1) We are not compiling a procedure body. Push the global
+	 *      variable's name and do the lookup at runtime.
+	 *   2) We are compiling a procedure and the name has "::"s.
+	 *	Push the namespace variable's name and do the lookup at
+	 *	runtime.
+	 *   3) We are compiling a procedure and the name has no "::"s.
+	 *	If the variable has already been allocated an local index,
+	 *	just look it up. If the variable is unknown and we are
+	 *	doing an assignment, allocate a new index. Otherwise,
+	 *	push the name and try to do the lookup at runtime.
+	 */
+
+	if ((procPtr == NULL) || nameHasNsSeparators) {
+	    savedChar = name[nameChars];
+	    name[nameChars] = '\0';
+	    objIndex = TclObjIndexForString(name, nameChars,
+		    /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr);
+	    name[nameChars] = savedChar;
+	    TclEmitPush(objIndex, envPtr);
+	    maxDepth = 1;
+	} else {
+	    localIndex = LookupCompiledLocal(name, nameChars,
+	            /*createIfNew*/ isAssignment,
+                    /*flagsIfCreated*/
+			((elName == NULL)? VAR_SCALAR : VAR_ARRAY),
+		    envPtr->procPtr);
+	    if (localIndex >= 0) {
+		maxDepth = 0;
+	    } else {
+		savedChar = name[nameChars];
+		name[nameChars] = '\0';
+		objIndex = TclObjIndexForString(name, nameChars,
+			/*allocStrRep*/ 1, /*inHeap*/ 0, envPtr);
+		name[nameChars] = savedChar;
+		TclEmitPush(objIndex, envPtr);
+		maxDepth = 1;
+	    }
+	}
+
+	/*
+	 * If we are dealing with a reference to an array element, push the
+	 * array element. Perform substitutions on it, just as is done
+	 * for quoted strings.
+	 */
+	
+	if (elName != NULL) {
+	    savedChar = elName[elNameChars];
+	    elName[elNameChars] = '\0';
+	    envPtr->pushSimpleWords = 1;
+	    result = TclCompileQuotes(interp, elName, elName+elNameChars,
+		    0, flags, envPtr);
+	    elName[elNameChars] = savedChar;
+	    if (result != TCL_OK) {
+		char msg[200];
+		sprintf(msg, "\n    (parsing index for array \"%.*s\")",
+			TclMin(nameChars, 100), name);
+		Tcl_AddObjErrorInfo(interp, msg, -1);
+		goto done;
+	    }
+	    maxDepth += envPtr->maxStackDepth;
+	}
+    }
+
+    /*
+     * If we are doing an assignment, push the new value.
+     */
+    
+    if (isAssignment) {
+	wordStart = argInfo.startArray[1]; /* start of 2nd arg word */
+	envPtr->pushSimpleWords = 0;       /* we will handle simple words */
+	result = CompileWord(interp, wordStart,	argInfo.endArray[1] + 1,
+		flags, envPtr);
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	if (!envPtr->wordIsSimple) {
+	    /*
+	     * The value isn't simple. CompileWord already pushed it.
+	     */
+
+	    maxDepth += envPtr->maxStackDepth;
+	} else {
+	    /*
+	     * The value is simple. See if the word represents an integer
+	     * whose formatted representation is the same as the word (e.g.,
+	     * this is true for 123 and -1 but not for 00005). If so, just
+	     * push an integer object.
+	     */
+	    
+	    char buf[40];
+	    long n;
+
+	    p = wordStart;
+	    if ((*wordStart == '"') || (*wordStart == '{')) {
+		p++;
+	    }
+	    savedChar = p[envPtr->numSimpleWordChars];
+	    p[envPtr->numSimpleWordChars] = '\0';
+	    isCompilableInt = 0;
+	    if (TclLooksLikeInt(p)) {
+		int code = TclGetLong(interp, p, &n);
+		if (code == TCL_OK) {
+		    TclFormatInt(buf, n);
+		    if (strcmp(p, buf) == 0) {
+			isCompilableInt = 1;
+			objIndex = TclObjIndexForString(p,
+				envPtr->numSimpleWordChars,
+                                /*allocStrRep*/ 0, /*inHeap*/ 0, envPtr);
+			objPtr = envPtr->objArrayPtr[objIndex];
+
+			Tcl_InvalidateStringRep(objPtr);
+			objPtr->internalRep.longValue = n;
+			objPtr->typePtr = &tclIntType;
+		    }
+		} else {
+		    Tcl_ResetResult(interp);
+		}
+	    }
+	    if (!isCompilableInt) {
+		objIndex = TclObjIndexForString(p,
+			envPtr->numSimpleWordChars, /*allocStrRep*/ 1,
+			/*inHeap*/ 0, envPtr);
+	    }
+	    p[envPtr->numSimpleWordChars] = savedChar;
+	    TclEmitPush(objIndex, envPtr);
+	    maxDepth += 1;
+	}
+    }
+    
+    /*
+     * Now emit instructions to set/retrieve the variable.
+     */
+
+    if (simpleVarName) {
+	if (elName == NULL) {  /* scalar */
+	    if (localIndex >= 0) {
+		if (localIndex <= 255) {
+		    TclEmitInstUInt1((isAssignment?
+			     INST_STORE_SCALAR1 : INST_LOAD_SCALAR1),
+			localIndex, envPtr);
+		} else {
+		    TclEmitInstUInt4((isAssignment?
+			     INST_STORE_SCALAR4 : INST_LOAD_SCALAR4),
+			localIndex, envPtr);
+		}
+	    } else {
+		TclEmitOpcode((isAssignment?
+			     INST_STORE_SCALAR_STK : INST_LOAD_SCALAR_STK),
+			    envPtr);
+	    }
+	} else {		/* array */
+	    if (localIndex >= 0) {
+		if (localIndex <= 255) {
+		    TclEmitInstUInt1((isAssignment?
+			     INST_STORE_ARRAY1 : INST_LOAD_ARRAY1),
+			localIndex, envPtr);
+		} else {
+		    TclEmitInstUInt4((isAssignment?
+			     INST_STORE_ARRAY4 : INST_LOAD_ARRAY4),
+			localIndex, envPtr);
+		}
+	    } else {
+		TclEmitOpcode((isAssignment?
+			     INST_STORE_ARRAY_STK : INST_LOAD_ARRAY_STK),
+			    envPtr);
+	    }
+	}
+    } else {			/* non-simple variable name */
+	TclEmitOpcode((isAssignment? INST_STORE_STK : INST_LOAD_STK), envPtr);
+    }
+	
+    done:
+    if (numWords == 0) {
+	envPtr->termOffset = 0;
+    } else {
+	envPtr->termOffset = (argInfo.endArray[numWords-1] + 1 - string);
+    }
+    envPtr->pushSimpleWords = savePushSimpleWords;
+    envPtr->maxStackDepth = maxDepth;
+    FreeArgInfo(&argInfo);
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileWhileCmd --
+ *
+ *	Procedure called to compile the "while" command.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is TCL_OK if
+ *	compilation was successful. If an error occurs then the
+ *	interpreter's result contains a standard error message and TCL_ERROR
+ *	is returned. If compilation failed because the command is too
+ *	complex for TclCompileWhileCmd, TCL_OUT_LINE_COMPILE is returned
+ *	indicating that the while command should be compiled "out of line"
+ *	by emitting code to invoke its command procedure at runtime.
+ *
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one successfully processed.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the "while" command.
+ *
+ * Side effects:
+ *	Instructions are added to envPtr to evaluate the "while" command
+ *	at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileWhileCmd(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    char *string;		/* The source string to compile. */
+    char *lastChar;		 /* Pointer to terminating character of
+				  * string. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    register char *src = string;/* Points to current source char. */
+    register int type;		/* Current char's CHAR_TYPE type. */
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute cmd. */
+    int range = -1;		/* Index in the ExceptionRange array of the
+				 * ExceptionRange record for this loop. */
+    JumpFixup jumpFalseFixup;	/* Used to update or replace the ifFalse
+				 * jump after test when its target PC is
+				 * determined. */
+    unsigned char *jumpPc;
+    int jumpDist, jumpBackDist, jumpBackOffset, objIndex, result;
+    int savePushSimpleWords = envPtr->pushSimpleWords;
+
+    AdvanceToNextWord(src, envPtr);
+    src += envPtr->termOffset;
+    type = CHAR_TYPE(src, lastChar);
+    if (type == TCL_COMMAND_END) {
+	badArgs:
+	Tcl_ResetResult(interp);
+	Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	        "wrong # args: should be \"while test command\"", -1);
+	result = TCL_ERROR;
+	goto done;
+    }
+
+    /*
+     * If the test expression is not enclosed in braces, don't compile
+     * the while inline. As a result of Tcl's two level substitution
+     * semantics for expressions, the expression might have a constant
+     * value that results in the loop never executing, or executing forever.
+     * Consider "set x 0; whie "$x > 5" {incr x}": the loop body 
+     * should never be executed.
+     * NOTE: This is an overly aggressive test, since there are legitimate
+     * literals that could be compiled but aren't in braces.  However, until
+     * the parser is integrated in 8.1, this is the simplest implementation.
+     */
+
+    if (*src != '{') {
+	result = TCL_OUT_LINE_COMPILE;
+	goto done;
+    }
+
+    /*
+     * Create and initialize a ExceptionRange record to hold information
+     * about this loop. This is used to implement break and continue.
+     */
+
+    envPtr->excRangeDepth++;
+    envPtr->maxExcRangeDepth =
+	TclMax(envPtr->excRangeDepth, envPtr->maxExcRangeDepth);
+
+    range = CreateExceptionRange(LOOP_EXCEPTION_RANGE, envPtr);
+    envPtr->excRangeArrayPtr[range].continueOffset = TclCurrCodeOffset();
+
+    /*
+     * Compile the next word: the test expression.
+     */
+
+    envPtr->pushSimpleWords = 1;
+    result = CompileExprWord(interp, src, lastChar, flags, envPtr);
+    if (result != TCL_OK) {
+	if (result == TCL_ERROR) {
+            Tcl_AddObjErrorInfo(interp,
+		    "\n    (\"while\" test expression)", -1);
+        }
+	goto done;
+    }
+    maxDepth = envPtr->maxStackDepth;
+    src += envPtr->termOffset;
+
+    /*
+     * Emit the ifFalse jump that terminates the while if the test was
+     * false. We emit a one byte (relative) jump here, and replace it
+     * later with a four byte jump if the jump target is more than
+     * 127 bytes away.
+     */
+
+    TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup);
+    
+    /*
+     * Compile the loop body word inline. Also register the loop body's
+     * starting PC offset and byte length in the its ExceptionRange record.
+     */
+
+    AdvanceToNextWord(src, envPtr);
+    src += envPtr->termOffset;
+    type = CHAR_TYPE(src, lastChar);
+    if (type == TCL_COMMAND_END) {
+	goto badArgs;
+    }
+
+    envPtr->excRangeArrayPtr[range].codeOffset = TclCurrCodeOffset();
+    result = CompileCmdWordInline(interp, src, lastChar,
+	    flags, envPtr);
+    if (result != TCL_OK) {
+	if (result == TCL_ERROR) {
+	    char msg[60];
+	    sprintf(msg, "\n    (\"while\" body line %d)", interp->errorLine);
+            Tcl_AddObjErrorInfo(interp, msg, -1);
+        }
+	goto done;
+    }
+    maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);
+    src += envPtr->termOffset;
+    envPtr->excRangeArrayPtr[range].numCodeBytes =
+	(TclCurrCodeOffset() - envPtr->excRangeArrayPtr[range].codeOffset);
+
+    /*
+     * Discard the loop body's result.
+     */
+
+    TclEmitOpcode(INST_POP, envPtr);
+	
+    /*
+     * Emit the unconditional jump back to the test at the top of the
+     * loop. We generate a four byte jump if the distance to the while's
+     * test is greater than 120 bytes. This is conservative, and ensures
+     * that we won't have to replace this unconditional jump if we later
+     * need to replace the ifFalse jump with a four-byte jump.
+     */
+
+    jumpBackOffset = TclCurrCodeOffset();
+    jumpBackDist =
+	(jumpBackOffset - envPtr->excRangeArrayPtr[range].continueOffset);
+    if (jumpBackDist > 120) {
+	TclEmitInstInt4(INST_JUMP4, /*offset*/ -jumpBackDist, envPtr);
+    } else {
+	TclEmitInstInt1(INST_JUMP1, /*offset*/ -jumpBackDist, envPtr);
+    }
+
+    /*
+     * Now that we know the target of the jumpFalse after the test, update
+     * it with the correct distance. If the distance is too great (more
+     * than 127 bytes), replace that jump with a four byte instruction and
+     * move the instructions after the jump down. 
+     */
+
+    jumpDist = (TclCurrCodeOffset() - jumpFalseFixup.codeOffset);
+    if (TclFixupForwardJump(envPtr, &jumpFalseFixup, jumpDist, 127)) {
+	/*
+	 * Update the loop body's starting PC offset since it moved down.
+	 */
+
+	envPtr->excRangeArrayPtr[range].codeOffset += 3;
+
+	/*
+	 * Update the distance for the unconditional jump back to the test
+	 * at the top of the loop since it moved down 3 bytes too.
+	 */
+
+	jumpBackOffset += 3;
+	jumpPc = (envPtr->codeStart + jumpBackOffset);
+	if (jumpBackDist > 120) {
+	    jumpBackDist += 3;
+	    TclUpdateInstInt4AtPc(INST_JUMP4, /*offset*/ -jumpBackDist,
+				   jumpPc);
+	} else {
+	    jumpBackDist += 3;
+	    TclUpdateInstInt1AtPc(INST_JUMP1, /*offset*/ -jumpBackDist,
+				   jumpPc);
+	}
+    }
+
+    /*
+     * The current PC offset (after the loop's body) is the loop's
+     * break target.
+     */
+
+    envPtr->excRangeArrayPtr[range].breakOffset = TclCurrCodeOffset();
+    
+    /*
+     * Push an empty string object as the while command's result.
+     */
+
+    objIndex = TclObjIndexForString("", 0, /*allocStrRep*/ 0, /*inHeap*/ 0,
+				    envPtr);
+    TclEmitPush(objIndex, envPtr);
+    if (maxDepth == 0) {
+	maxDepth = 1;
+    }
+
+    /*
+     * Skip over white space until the end of the command.
+     */
+
+    type = CHAR_TYPE(src, lastChar);
+    if (type != TCL_COMMAND_END) {
+	AdvanceToNextWord(src, envPtr);
+	src += envPtr->termOffset;
+	type = CHAR_TYPE(src, lastChar);
+	if (type != TCL_COMMAND_END) {
+	    goto badArgs;
+	}
+    }
+
+    done:
+    envPtr->termOffset = (src - string);
+    envPtr->pushSimpleWords = savePushSimpleWords;
+    envPtr->maxStackDepth = maxDepth;
+    if (range != -1) {
+	envPtr->excRangeDepth--;
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileExprWord --
+ *
+ *	Procedure that compiles a Tcl expression in a command word.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is TCL_OK unless
+ *	there was an error while compiling string. If an error occurs then
+ *	the interpreter's result contains a standard error message.
+ *
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one successfully processed.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the "expr" word.
+ *
+ * Side effects:
+ *	Instructions are added to envPtr to evaluate the expression word
+ *	at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileExprWord(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    char *string;		/* The source string to compile. */
+    char *lastChar;		 /* Pointer to terminating character of
+				  * string. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    register char *src = string;/* Points to current source char. */
+    register int type;          /* Current char's CHAR_TYPE type. */
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute the expression. */
+    int nestedCmd = (flags & TCL_BRACKET_TERM);
+				/* 1 if script being compiled is a nested
+				 * command and is terminated by a ']';
+				 * otherwise 0. */
+    char *first, *last;		/* Points to the first and last significant
+				 * characters of the word. */
+    char savedChar;		/* Holds the character termporarily replaced
+				 * by a null character during compilation
+				 * of the expression. */
+    int inlineCode;		/* 1 if inline "optimistic" code is
+				 * emitted for the expression; else 0. */
+    int range = -1;		/* If we inline compile an un-{}'d
+				 * expression, the index for its catch range
+				 * record in the ExceptionRange array.
+				 * Initialized to enable proper cleanup. */
+    JumpFixup jumpFixup;	/* Used to emit the "success" jump after
+				 * the inline expression code. */
+    char *p;
+    char c;
+    int savePushSimpleWords = envPtr->pushSimpleWords;
+    int saveExprIsJustVarRef = envPtr->exprIsJustVarRef;
+    int saveExprIsComparison = envPtr->exprIsComparison;
+    int numChars, result;
+
+    /*
+     * Skip over leading white space.
+     */
+
+    AdvanceToNextWord(src, envPtr);
+    src += envPtr->termOffset;
+    type = CHAR_TYPE(src, lastChar);
+    if (type == TCL_COMMAND_END) {
+	badArgs:
+	Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		    "malformed expression word", -1);
+	result = TCL_ERROR;
+	goto done;
+    }
+
+    /*
+     * If the word is enclosed in {}s, we may strip them off and safely
+     * compile the expression into an inline sequence of instructions using
+     * TclCompileExpr. We know these instructions will have the right Tcl7.x
+     * expression semantics.
+     *
+     * Otherwise, if the word is not enclosed in {}s, we may need to call
+     * the expr command (Tcl_ExprObjCmd) at runtime. This recompiles the
+     * expression each time (typically) and so is slow. However, there are
+     * some circumstances where we can still compile inline instructions
+     * "optimistically" and check, during their execution, for double
+     * substitutions (these appear as nonnumeric operands). We check for any
+     * backslash or command substitutions. If none appear, and only variable
+     * substitutions are found, we generate inline instructions.
+     *
+     * For now, if the expression is not enclosed in {}s, we call the expr
+     * command at runtime if either command or backslash substitutions
+     * appear (but not if only variable substitutions appear).
+     */
+
+    if (*src == '{') {
+	/*
+	 * Inline compile the expression inside {}s.
+	 */
+	
+	first = src+1;
+	src = TclWordEnd(src, lastChar, nestedCmd, NULL);
+	if (*src == 0) {
+	    goto badArgs;
+	}
+	if (*src != '}') {
+	    goto badArgs;
+	}
+	last = (src-1);
+
+	numChars = (last - first + 1);
+	savedChar = first[numChars];
+	first[numChars] = '\0';
+	result = TclCompileExpr(interp, first, first+numChars,
+		flags, envPtr);
+	first[numChars] = savedChar;
+
+	src++;
+	maxDepth = envPtr->maxStackDepth;
+    } else {
+	/*
+	 * No braces. If the expression is enclosed in '"'s, call the expr
+	 * cmd at runtime. Otherwise, scan the word's characters looking for
+	 * any '['s or (for now) '\'s. If any are found, just call expr cmd
+	 * at runtime.
+	 */
+
+	first = src;
+	last = TclWordEnd(first, lastChar, nestedCmd, NULL);
+	if (*last == 0) {	/* word doesn't end properly. */
+	    src = last;
+	    goto badArgs;
+	}
+
+	inlineCode = 1;
+	if ((*first == '"') && (*last == '"')) {
+	    inlineCode = 0;
+	} else {
+	    for (p = first;  p <= last;  p++) {
+		c = *p;
+		if ((c == '[') || (c == '\\')) {
+		    inlineCode = 0;
+		    break;
+		}
+	    }
+	}
+	
+	if (inlineCode) {
+	    /*
+	     * Inline compile the expression inside a "catch" so that a
+	     * runtime error will back off to make a (slow) call on expr.
+	     */
+
+	    int startCodeOffset = (envPtr->codeNext - envPtr->codeStart);
+	    int startRangeNext = envPtr->excRangeArrayNext;
+
+	    /*
+	     * Create a ExceptionRange record to hold information about
+	     * the "catch" range for the expression's inline code. Also
+	     * emit the instruction to mark the start of the range.
+	     */
+
+	    envPtr->excRangeDepth++;
+	    envPtr->maxExcRangeDepth =
+		TclMax(envPtr->excRangeDepth, envPtr->maxExcRangeDepth);
+	    range = CreateExceptionRange(CATCH_EXCEPTION_RANGE, envPtr);
+	    TclEmitInstUInt4(INST_BEGIN_CATCH4, range, envPtr);
+
+	    /*
+	     * Inline compile the expression.
+	     */
+
+	    envPtr->excRangeArrayPtr[range].codeOffset = TclCurrCodeOffset();
+	    numChars = (last - first + 1);
+	    savedChar = first[numChars];
+	    first[numChars] = '\0';
+	    result = TclCompileExpr(interp, first, first + numChars,
+		    flags, envPtr);
+	    first[numChars] = savedChar;
+	    
+	    envPtr->excRangeArrayPtr[range].numCodeBytes =
+		TclCurrCodeOffset() - envPtr->excRangeArrayPtr[range].codeOffset;
+
+	    if ((result != TCL_OK) || (envPtr->exprIsJustVarRef)
+	            || (envPtr->exprIsComparison)) {
+		/*
+		 * We must call the expr command at runtime. Either there
+		 * was a compilation error or the inline code might fail to
+		 * give the correct 2 level substitution semantics.
+		 *
+		 * The latter can happen if the expression consisted of just
+		 * a single variable reference or if the top-level operator
+		 * in the expr is a comparison (which might operate on
+		 * strings). In the latter case, the expression's code might
+		 * execute (apparently) successfully but produce the wrong
+		 * result. We depend on its execution failing if a second
+		 * level of substitutions is required. This causes the
+		 * "catch" code we generate around the inline code to back
+		 * off to a call on the expr command at runtime, and this
+		 * always gives the right 2 level substitution semantics.
+		 *
+		 * We delete the inline code by backing up the code pc and
+		 * catch index. Note that if there was a compilation error,
+		 * we can't report the error yet since the expression might
+		 * be valid after the second round of substitutions.
+		 */
+		
+		envPtr->codeNext = (envPtr->codeStart + startCodeOffset);
+		envPtr->excRangeArrayNext = startRangeNext;
+		inlineCode = 0;
+	    } else {
+		TclEmitOpcode(INST_END_CATCH, envPtr); /* for ok case */
+		TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup);
+		envPtr->excRangeArrayPtr[range].catchOffset = TclCurrCodeOffset();
+		TclEmitOpcode(INST_END_CATCH, envPtr); /* for error case */
+	    }
+	}
+	    
+	/*
+	 * Arrange to call expr at runtime with the (already substituted
+	 * once) expression word on the stack.
+	 */
+
+	envPtr->pushSimpleWords = 1;
+	result = CompileWord(interp, first, lastChar, flags, envPtr);
+	src += envPtr->termOffset;
+	maxDepth = envPtr->maxStackDepth;
+	if (result == TCL_OK) {
+	    TclEmitOpcode(INST_EXPR_STK, envPtr);
+	}
+
+	/*
+	 * If emitting inline code for this non-{}'d expression, update
+	 * the target of the jump after that inline code.
+	 */
+
+	if (inlineCode) {
+	    int jumpDist = (TclCurrCodeOffset() - jumpFixup.codeOffset);
+	    if (TclFixupForwardJump(envPtr, &jumpFixup, jumpDist, 127)) {
+		/*
+		 * Update the inline expression code's catch ExceptionRange
+		 * target since it, being after the jump, also moved down.
+		 */
+
+		envPtr->excRangeArrayPtr[range].catchOffset += 3;
+	    }
+	}
+    } /* if expression isn't in {}s */
+    
+    done:
+    if (range != -1) {
+	envPtr->excRangeDepth--;
+    }
+    envPtr->termOffset = (src - string);
+    envPtr->maxStackDepth = maxDepth;
+    envPtr->pushSimpleWords = savePushSimpleWords;
+    envPtr->exprIsJustVarRef = saveExprIsJustVarRef;
+    envPtr->exprIsComparison = saveExprIsComparison;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileCmdWordInline --
+ *
+ *	Procedure that compiles a Tcl command word inline. If the word is
+ *	enclosed in quotes or braces, we call TclCompileString to compile it
+ *	after stripping them off. Otherwise, we normally push the word's
+ *	value and call eval at runtime, but if the word is just a sequence
+ *	of alphanumeric characters, we emit an invoke instruction
+ *	directly. This procedure assumes that string points to the start of
+ *	the word to compile.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is TCL_OK unless
+ *	there was an error while compiling string. If an error occurs then
+ *	the interpreter's result contains a standard error message.
+ *
+ *	envPtr->termOffset is filled in with the offset of the character in
+ *	"string" just after the last one successfully processed.
+ *
+ *	envPtr->maxStackDepth is updated with the maximum number of stack
+ *	elements needed to execute the command.
+ *
+ * Side effects:
+ *	Instructions are added to envPtr to execute the command word
+ *	at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileCmdWordInline(interp, string, lastChar, flags, envPtr)
+    Tcl_Interp *interp;		/* Used for error reporting. */
+    char *string;		/* The source string to compile. */
+    char *lastChar;		/* Pointer to terminating character of
+				 * string. */
+    int flags;			/* Flags to control compilation (same as
+				 * passed to Tcl_Eval). */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    Interp *iPtr = (Interp *) interp;
+    register char *src = string;/* Points to current source char. */
+    register int type;          /* Current char's CHAR_TYPE type. */
+    int maxDepth = 0;		/* Maximum number of stack elements needed
+				 * to execute cmd. */
+    char *termPtr;		/* Points to char that terminated braced
+				 * string. */
+    char savedChar;		/* Holds the character termporarily replaced
+				 * by a null character during compilation
+				 * of the command. */
+    int savePushSimpleWords = envPtr->pushSimpleWords;
+    int objIndex;
+    int result = TCL_OK;
+    register char c;
+
+    type = CHAR_TYPE(src, lastChar);
+    if (type & (TCL_QUOTE | TCL_OPEN_BRACE)) {
+	src++;
+	envPtr->pushSimpleWords = 0;
+	if (type == TCL_QUOTE) {
+	    result = TclCompileQuotes(interp, src, lastChar,
+		    '"', flags, envPtr);
+	} else {
+	    result = CompileBraces(interp, src, lastChar, flags, envPtr);
+	}
+	if (result != TCL_OK) {
+	    goto done;
+	}
+	
+	/*
+	 * Make sure the terminating character is the end of word.
+	 */
+	
+	termPtr = (src + envPtr->termOffset);
+	c = *termPtr;
+	if ((c == '\\') && (*(termPtr+1) == '\n')) {
+	    /*
+	     * Line is continued on next line; the backslash-newline turns
+	     * into space, which terminates the word.
+	     */
+	} else {
+	    type = CHAR_TYPE(termPtr, lastChar);
+	    if ((type != TCL_SPACE) && (type != TCL_COMMAND_END)) {
+		Tcl_ResetResult(interp);
+		if (*(src-1) == '"') {
+		    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+			    "extra characters after close-quote", -1);
+		} else {
+		    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		            "extra characters after close-brace", -1);
+		}
+		result = TCL_ERROR;
+		goto done;
+	    }
+	}
+	
+	if (envPtr->wordIsSimple) {
+	    /*
+	     * A simple word enclosed in "" or {}s. Call TclCompileString to
+	     * compile it inline. Add a null character after the end of the
+	     * quoted or braced string: i.e., at the " or }. Turn the
+	     * flag bit TCL_BRACKET_TERM off since the recursively
+	     * compiled subcommand is now terminated by a null character.
+	     */
+	    char *closeCharPos = (termPtr - 1);
+	    
+	    savedChar = *closeCharPos;
+	    *closeCharPos = '\0';
+	    result = TclCompileString(interp, src, closeCharPos,
+		    (flags & ~TCL_BRACKET_TERM), envPtr);
+	    *closeCharPos = savedChar;
+	    if (result != TCL_OK) {
+		goto done;
+	    }
+	} else {
+            /*
+	     * The braced string contained a backslash-newline. Call eval
+	     * at runtime.
+	     */
+	    TclEmitOpcode(INST_EVAL_STK, envPtr);
+	}
+	src = termPtr;
+	maxDepth = envPtr->maxStackDepth;
+    } else {
+	/*
+	 * Not a braced or quoted string. We normally push the word's
+	 * value and call eval at runtime. However, if the word is just
+	 * a sequence of alphanumeric characters, we call its compile
+	 * procedure, if any, or otherwise just emit an invoke instruction.
+	 */
+
+	char *p = src;
+	c = *p;
+	while (isalnum(UCHAR(c)) || (c == '_')) {
+            p++;
+            c = *p;
+        }
+	type = CHAR_TYPE(p, lastChar);
+        if ((p > src) && (type == TCL_COMMAND_END)) {
+            /*
+	     * Look for a compile procedure and call it. Otherwise emit an
+	     * invoke instruction to call the command at runtime.
+	     */
+
+	    Tcl_Command cmd;
+	    Command *cmdPtr = NULL;
+	    int wasCompiled = 0;
+
+	    savedChar = *p;
+	    *p = '\0';
+
+	    cmd = Tcl_FindCommand(interp, src, (Tcl_Namespace *) NULL,
+		    /*flags*/ 0);
+	    if (cmd != (Tcl_Command) NULL) {
+                cmdPtr = (Command *) cmd;
+            }
+	    if (cmdPtr != NULL && cmdPtr->compileProc != NULL) {
+		*p = savedChar;
+		src = p;
+		iPtr->flags &= ~(ERR_ALREADY_LOGGED | ERR_IN_PROGRESS
+				 | ERROR_CODE_SET);
+		result = (*(cmdPtr->compileProc))(interp, src, lastChar, flags, envPtr);
+		if (result != TCL_OK) {
+		    goto done;
+		}
+		wasCompiled = 1;
+		src += envPtr->termOffset;
+		maxDepth = envPtr->maxStackDepth;
+	    }
+	    if (!wasCompiled) {
+		objIndex = TclObjIndexForString(src, p-src,
+			/*allocStrRep*/ 1, /*inHeap*/ 0, envPtr);
+		*p = savedChar;
+		TclEmitPush(objIndex, envPtr);
+		TclEmitInstUInt1(INST_INVOKE_STK1, 1, envPtr);
+		src = p;
+		maxDepth = 1;
+	    }
+        } else {
+	    /*
+	     * Push the word and call eval at runtime.
+	     */
+
+	    envPtr->pushSimpleWords = 1;
+	    result = CompileWord(interp, src, lastChar, flags, envPtr);
+	    if (result != TCL_OK) {
+		goto done;
+	    }
+	    TclEmitOpcode(INST_EVAL_STK, envPtr);
+	    src += envPtr->termOffset;
+	    maxDepth = envPtr->maxStackDepth;
+	}
+    }
+
+    done:
+    envPtr->termOffset = (src - string);
+    envPtr->maxStackDepth = maxDepth;
+    envPtr->pushSimpleWords = savePushSimpleWords;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * LookupCompiledLocal --
+ *
+ *	This procedure is called at compile time to look up and optionally
+ *	allocate an entry ("slot") for a variable in a procedure's array of
+ *	local variables. If the variable's name is NULL, a new temporary
+ *	variable is always created. (Such temporary variables can only be
+ *	referenced using their slot index.)
+ *
+ * Results:
+ *	If createIfNew is 0 (false) and the name is non-NULL, then if the
+ *	variable is found, the index of its entry in the procedure's array
+ *	of local variables is returned; otherwise -1 is returned.
+ *	If name is NULL, the index of a new temporary variable is returned.
+ *	Finally, if createIfNew is 1 and name is non-NULL, the index of a
+ *	new entry is returned.
+ *
+ * Side effects:
+ *	Creates and registers a new local variable if createIfNew is 1 and
+ *	the variable is unknown, or if the name is NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+LookupCompiledLocal(name, nameChars, createIfNew, flagsIfCreated, procPtr)
+    register char *name;	/* Points to first character of the name of
+				 * a scalar or array variable. If NULL, a
+				 * temporary var should be created. */
+    int nameChars;		/* The length of the name excluding the
+				 * terminating null character. */
+    int createIfNew;		/* 1 to allocate a local frame entry for the
+				 * variable if it is new. */
+    int flagsIfCreated;		/* Flag bits for the compiled local if
+				 * created. Only VAR_SCALAR, VAR_ARRAY, and
+				 * VAR_LINK make sense. */
+    register Proc *procPtr;	/* Points to structure describing procedure
+				 * containing the variable reference. */
+{
+    register CompiledLocal *localPtr;
+    int localIndex = -1;
+    register int i;
+    int localCt;
+
+    /*
+     * If not creating a temporary, does a local variable of the specified
+     * name already exist?
+     */
+
+    if (name != NULL) {	
+	localCt = procPtr->numCompiledLocals;
+	localPtr = procPtr->firstLocalPtr;
+	for (i = 0;  i < localCt;  i++) {
+	    if (!TclIsVarTemporary(localPtr)) {
+		char *localName = localPtr->name;
+		if ((name[0] == localName[0])
+	                && (nameChars == localPtr->nameLength)
+	                && (strncmp(name, localName, (unsigned) nameChars) == 0)) {
+		    return i;
+		}
+	    }
+	    localPtr = localPtr->nextPtr;
+	}
+    }
+
+    /*
+     * Create a new variable if appropriate.
+     */
+    
+    if (createIfNew || (name == NULL)) {
+	localIndex = procPtr->numCompiledLocals;
+	localPtr = (CompiledLocal *) ckalloc((unsigned) 
+	        (sizeof(CompiledLocal) - sizeof(localPtr->name)
+		+ nameChars+1));
+	if (procPtr->firstLocalPtr == NULL) {
+	    procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr;
+	} else {
+	    procPtr->lastLocalPtr->nextPtr = localPtr;
+	    procPtr->lastLocalPtr = localPtr;
+	}
+	localPtr->nextPtr = NULL;
+	localPtr->nameLength = nameChars;
+	localPtr->frameIndex = localIndex;
+	localPtr->flags = flagsIfCreated;
+	if (name == NULL) {
+	    localPtr->flags |= VAR_TEMPORARY;
+	}
+	localPtr->defValuePtr = NULL;
+ 	localPtr->resolveInfo = NULL;
+ 	
+	if (name != NULL) {
+	    memcpy((VOID *) localPtr->name, (VOID *) name, (size_t) nameChars);
+	}
+	localPtr->name[nameChars] = '\0';
+	procPtr->numCompiledLocals++;
+    }
+    return localIndex;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInitCompiledLocals --
+ *
+ *	This routine is invoked in order to initialize the compiled
+ *	locals table for a new call frame.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	May invoke various name resolvers in order to determine which
+ *	variables are being referenced at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclInitCompiledLocals(interp, framePtr, nsPtr)
+    Tcl_Interp *interp;		/* Current interpreter. */
+    CallFrame *framePtr;	/* Call frame to initialize. */
+    Namespace *nsPtr;		/* Pointer to current namespace. */
+{
+    register CompiledLocal *localPtr;
+    Interp *iPtr = (Interp*) interp;
+    Tcl_ResolvedVarInfo *vinfo, *resVarInfo;
+    Var *varPtr = framePtr->compiledLocals;
+    Var *resolvedVarPtr;
+    ResolverScheme *resPtr;
+    int result;
+
+    /*
+     * Initialize the array of local variables stored in the call frame.
+     * Some variables may have special resolution rules.  In that case,
+     * we call their "resolver" procs to get our hands on the variable,
+     * and we make the compiled local a link to the real variable.
+     */
+
+    for (localPtr = framePtr->procPtr->firstLocalPtr;
+	 localPtr != NULL;
+	 localPtr = localPtr->nextPtr) {
+
+	/*
+	 * Check to see if this local is affected by namespace or
+	 * interp resolvers.  The resolver to use is cached for the
+	 * next invocation of the procedure.
+	 */
+
+	if (!(localPtr->flags & (VAR_ARGUMENT|VAR_TEMPORARY|VAR_RESOLVED))
+		&& (nsPtr->compiledVarResProc || iPtr->resolverPtr)) {
+	    resPtr = iPtr->resolverPtr;
+
+	    if (nsPtr->compiledVarResProc) {
+		result = (*nsPtr->compiledVarResProc)(nsPtr->interp,
+			localPtr->name, localPtr->nameLength,
+			(Tcl_Namespace *) nsPtr, &vinfo);
+	    } else {
+		result = TCL_CONTINUE;
+	    }
+
+	    while ((result == TCL_CONTINUE) && resPtr) {
+		if (resPtr->compiledVarResProc) {
+		    result = (*resPtr->compiledVarResProc)(nsPtr->interp,
+			    localPtr->name, localPtr->nameLength,
+			    (Tcl_Namespace *) nsPtr, &vinfo);
+		}
+		resPtr = resPtr->nextPtr;
+	    }
+	    if (result == TCL_OK) {
+		localPtr->resolveInfo = vinfo;
+		localPtr->flags |= VAR_RESOLVED;
+	    }
+	}
+
+	/*
+	 * Now invoke the resolvers to determine the exact variables that
+	 * should be used.
+	 */
+
+        resVarInfo = localPtr->resolveInfo;
+        resolvedVarPtr = NULL;
+
+        if (resVarInfo && resVarInfo->fetchProc) {
+            resolvedVarPtr = (Var*) (*resVarInfo->fetchProc)(interp,
+                resVarInfo);
+        }
+
+        if (resolvedVarPtr) {
+	    varPtr->name = localPtr->name; /* will be just '\0' if temp var */
+	    varPtr->nsPtr = NULL;
+	    varPtr->hPtr = NULL;
+	    varPtr->refCount = 0;
+	    varPtr->tracePtr = NULL;
+	    varPtr->searchPtr = NULL;
+	    varPtr->flags = 0;
+            TclSetVarLink(varPtr);
+            varPtr->value.linkPtr = resolvedVarPtr;
+            resolvedVarPtr->refCount++;
+        } else {
+	    varPtr->value.objPtr = NULL;
+	    varPtr->name = localPtr->name; /* will be just '\0' if temp var */
+	    varPtr->nsPtr = NULL;
+	    varPtr->hPtr = NULL;
+	    varPtr->refCount = 0;
+	    varPtr->tracePtr = NULL;
+	    varPtr->searchPtr = NULL;
+	    varPtr->flags = (localPtr->flags | VAR_UNDEFINED);
+        }
+	varPtr++;
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AdvanceToNextWord --
+ *
+ *	This procedure is called to skip over any leading white space at the
+ *	start of a word. Note that a backslash-newline is treated as a
+ *	space.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Updates envPtr->termOffset with the offset of the first
+ *	character in "string" that was not white space or a
+ *	backslash-newline. This might be the offset of the character that
+ *	ends the command: a newline, null, semicolon, or close-bracket.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AdvanceToNextWord(string, envPtr)
+    char *string;		/* The source string to compile. */
+    CompileEnv *envPtr;		/* Holds resulting instructions. */
+{
+    register char *src;		/* Points to current source char. */
+    register int type;		/* Current char's CHAR_TYPE type. */
+    
+    src = string;
+    type = CHAR_TYPE(src, src+1);
+    while (type & (TCL_SPACE | TCL_BACKSLASH)) {
+	if (type == TCL_BACKSLASH) {
+	    if (src[1] == '\n') {
+		src += 2;
+	    } else {
+		break;		/* exit loop; no longer white space */
+	    }
+	} else {
+	    src++;
+	}
+	type = CHAR_TYPE(src, src+1);
+    }
+    envPtr->termOffset = (src - string);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_Backslash --
+ *
+ *	Figure out how to handle a backslash sequence.
+ *
+ * Results:
+ *	The return value is the character that should be substituted
+ *	in place of the backslash sequence that starts at src.  If
+ *	readPtr isn't NULL then it is filled in with a count of the
+ *	number of characters in the backslash sequence.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char
+Tcl_Backslash(src, readPtr)
+    CONST char *src;		/* Points to the backslash character of
+				 * a backslash sequence. */
+    int *readPtr;		/* Fill in with number of characters read
+				 * from src, unless NULL. */
+{
+    CONST char *p = src + 1;
+    char result;
+    int count;
+
+    count = 2;
+
+    switch (*p) {
+	/*
+         * Note: in the conversions below, use absolute values (e.g.,
+         * 0xa) rather than symbolic values (e.g. \n) that get converted
+         * by the compiler.  It's possible that compilers on some
+         * platforms will do the symbolic conversions differently, which
+         * could result in non-portable Tcl scripts.
+         */
+
+        case 'a':
+            result = 0x7;
+            break;
+        case 'b':
+            result = 0x8;
+            break;
+        case 'f':
+            result = 0xc;
+            break;
+        case 'n':
+            result = 0xa;
+            break;
+        case 'r':
+            result = 0xd;
+            break;
+        case 't':
+            result = 0x9;
+            break;
+        case 'v':
+            result = 0xb;
+            break;
+        case 'x':
+            if (isxdigit(UCHAR(p[1]))) {
+                char *end;
+
+                result = (char) strtoul(p+1, &end, 16);
+                count = end - src;
+            } else {
+                count = 2;
+                result = 'x';
+            }
+            break;
+        case '\n':
+            do {
+                p++;
+            } while ((*p == ' ') || (*p == '\t'));
+            result = ' ';
+            count = p - src;
+            break;
+        case 0:
+            result = '\\';
+            count = 1;
+            break;
+	default:
+	    if (isdigit(UCHAR(*p))) {
+		result = (char)(*p - '0');
+		p++;
+		if (!isdigit(UCHAR(*p))) {
+		    break;
+		}
+		count = 3;
+		result = (char)((result << 3) + (*p - '0'));
+		p++;
+		if (!isdigit(UCHAR(*p))) {
+		    break;
+		}
+		count = 4;
+		result = (char)((result << 3) + (*p - '0'));
+		break;
+	    }
+	    result = *p;
+	    count = 2;
+	    break;
+    }
+
+    if (readPtr != NULL) {
+	*readPtr = count;
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclObjIndexForString --
+ *
+ *	Procedure to find, or if necessary create, an object in a
+ *	CompileEnv's object array that has a string representation
+ *	matching the argument string.
+ *
+ * Results:
+ *	The index in the CompileEnv's object array of an object with a
+ *	string representation matching the argument "string". The object is
+ *	created if necessary. If inHeap is 1, then string is heap allocated
+ *	and ownership of the string is passed to TclObjIndexForString;
+ *	otherwise, the string is owned by the caller and must not be
+ *	modified or freed by TclObjIndexForString. Typically, a caller sets
+ *	inHeap 1 if string is an already heap-allocated buffer holding the
+ *	result of backslash substitutions.
+ *
+ * Side effects:
+ *	A new Tcl object will be created if no existing object matches the
+ *	input string. If allocStrRep is 1 then if a new object is created,
+ *	its string representation is allocated in the heap, else it is left
+ *	NULL. If inHeap is 1, this procedure is given ownership of the
+ * 	string: if an object is created and allocStrRep is 1 then its
+ *	string representation is set directly from string, otherwise
+ *	the string is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclObjIndexForString(string, length, allocStrRep, inHeap, envPtr)
+    register char *string;	/* Points to string for which an object is
+				 * found or created in CompileEnv's object
+				 * array. */
+    int length;			/* Length of string. */
+    int allocStrRep;		/* If 1 then the object's string rep should
+				 * be allocated in the heap. */
+    int inHeap;			/* If 1 then string is heap allocated and
+				 * its ownership is passed to
+				 * TclObjIndexForString. */
+    CompileEnv *envPtr;		/* Points to the CompileEnv in whose object
+				 * array an object is found or created. */
+{
+    register Tcl_Obj *objPtr;	/* Points to the object created for
+				 * the string, if one was created. */
+    int objIndex;		/* Index of matching object. */
+    Tcl_HashEntry *hPtr;
+    int strLength, new;
+    
+    /*
+     * Look up the string in the code's object hashtable. If found, just
+     * return the associated object array index.  Note that if the string
+     * has embedded nulls, we don't create a hash table entry.  This
+     * should be fixed, but we need to update hash tables, first.
+     */
+
+    strLength = strlen(string);
+    if (length == -1) {
+	length = strLength;
+    }
+    if (strLength != length) {
+	hPtr = NULL;
+    } else {
+	hPtr = Tcl_CreateHashEntry(&envPtr->objTable, string, &new);
+	if (!new) {		/* already in object table and array */
+	    objIndex = (int) Tcl_GetHashValue(hPtr);
+	    if (inHeap) {
+		ckfree(string);
+	    }
+	    return objIndex;
+	}
+    }    
+
+    /*
+     * Create a new object holding the string, add it to the object array,
+     * and register its index in the object hashtable.
+     */
+
+    objPtr = Tcl_NewObj();
+    if (allocStrRep) {
+	if (inHeap) {		/* use input string for obj's string rep */
+	    objPtr->bytes = string;
+	} else {
+	    if (length > 0) {
+		objPtr->bytes = ckalloc((unsigned) length + 1);
+		memcpy((VOID *) objPtr->bytes, (VOID *) string,
+			(size_t) length);
+		objPtr->bytes[length] = '\0';
+	    }
+	}
+	objPtr->length = length;
+    } else {			/* leave the string rep NULL */
+	if (inHeap) {
+	    ckfree(string);
+	}
+    }
+
+    if (envPtr->objArrayNext >= envPtr->objArrayEnd) {
+        ExpandObjectArray(envPtr);
+    }
+    objIndex = envPtr->objArrayNext;
+    envPtr->objArrayPtr[objIndex] = objPtr;
+    Tcl_IncrRefCount(objPtr);
+    envPtr->objArrayNext++;
+
+    if (hPtr) {
+	Tcl_SetHashValue(hPtr, objIndex);
+    }
+    return objIndex;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclExpandCodeArray --
+ *
+ *	Procedure that uses malloc to allocate more storage for a
+ *	CompileEnv's code array.
+ *
+ * Results:
+ *	None. 
+ *
+ * Side effects:
+ *	The byte code array in *envPtr is reallocated to a new array of
+ *	double the size, and if envPtr->mallocedCodeArray is non-zero the
+ *	old array is freed. Byte codes are copied from the old array to the
+ *	new one.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclExpandCodeArray(envPtr)
+    CompileEnv *envPtr;		/* Points to the CompileEnv whose code array
+				 * must be enlarged. */
+{
+    /*
+     * envPtr->codeNext is equal to envPtr->codeEnd. The currently defined
+     * code bytes are stored between envPtr->codeStart and
+     * (envPtr->codeNext - 1) [inclusive].
+     */
+    
+    size_t currBytes = TclCurrCodeOffset();
+    size_t newBytes  = 2*(envPtr->codeEnd  - envPtr->codeStart);
+    unsigned char *newPtr = (unsigned char *) ckalloc((unsigned) newBytes);
+
+    /*
+     * Copy from old code array to new, free old code array if needed, and
+     * mark new code array as malloced.
+     */
+ 
+    memcpy((VOID *) newPtr, (VOID *) envPtr->codeStart, currBytes);
+    if (envPtr->mallocedCodeArray) {
+        ckfree((char *) envPtr->codeStart);
+    }
+    envPtr->codeStart = newPtr;
+    envPtr->codeNext = (newPtr + currBytes);
+    envPtr->codeEnd  = (newPtr + newBytes);
+    envPtr->mallocedCodeArray = 1;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ExpandObjectArray --
+ *
+ *	Procedure that uses malloc to allocate more storage for a
+ *	CompileEnv's object array.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The object array in *envPtr is reallocated to a new array of
+ *	double the size, and if envPtr->mallocedObjArray is non-zero the
+ *	old array is freed. Tcl_Obj pointers are copied from the old array
+ *	to the new one.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ExpandObjectArray(envPtr)
+    CompileEnv *envPtr;		/* Points to the CompileEnv whose object
+				 * array must be enlarged. */
+{
+    /*
+     * envPtr->objArrayNext is equal to envPtr->objArrayEnd. The currently
+     * allocated Tcl_Obj pointers are stored between elements
+     * 0 and (envPtr->objArrayNext - 1) [inclusive] in the object array
+     * pointed to by objArrayPtr.
+     */
+
+    size_t currBytes = envPtr->objArrayNext * sizeof(Tcl_Obj *);
+    int newElems = 2*envPtr->objArrayEnd;
+    size_t newBytes = newElems * sizeof(Tcl_Obj *);
+    Tcl_Obj **newPtr = (Tcl_Obj **) ckalloc((unsigned) newBytes);
+
+    /*
+     * Copy from old object array to new, free old object array if needed,
+     * and mark new object array as malloced.
+     */
+ 
+    memcpy((VOID *) newPtr, (VOID *) envPtr->objArrayPtr, currBytes);
+    if (envPtr->mallocedObjArray) {
+	ckfree((char *) envPtr->objArrayPtr);
+    }
+    envPtr->objArrayPtr = (Tcl_Obj **) newPtr;
+    envPtr->objArrayEnd = newElems;
+    envPtr->mallocedObjArray = 1;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EnterCmdStartData --
+ *
+ *	Registers the starting source and bytecode location of a
+ *	command. This information is used at runtime to map between
+ *	instruction pc and source locations.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Inserts source and code location information into the compilation
+ *	environment envPtr for the command at index cmdIndex. The
+ *	compilation environment's CmdLocation array is grown if necessary.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EnterCmdStartData(envPtr, cmdIndex, srcOffset, codeOffset)
+    CompileEnv *envPtr;		/* Points to the compilation environment
+				 * structure in which to enter command
+				 * location information. */
+    int cmdIndex;		/* Index of the command whose start data
+				 * is being set. */
+    int srcOffset;		/* Offset of first char of the command. */
+    int codeOffset;		/* Offset of first byte of command code. */
+{
+    CmdLocation *cmdLocPtr;
+    
+    if ((cmdIndex < 0) || (cmdIndex >= envPtr->numCommands)) {
+	panic("EnterCmdStartData: bad command index %d\n", cmdIndex);
+    }
+    
+    if (cmdIndex >= envPtr->cmdMapEnd) {
+	/*
+	 * Expand the command location array by allocating more storage from
+	 * the heap. The currently allocated CmdLocation entries are stored
+	 * from cmdMapPtr[0] up to cmdMapPtr[envPtr->cmdMapEnd] (inclusive).
+	 */
+
+	size_t currElems = envPtr->cmdMapEnd;
+	size_t newElems  = 2*currElems;
+	size_t currBytes = currElems * sizeof(CmdLocation);
+	size_t newBytes  = newElems  * sizeof(CmdLocation);
+	CmdLocation *newPtr = (CmdLocation *) ckalloc((unsigned) newBytes);
+	
+	/*
+	 * Copy from old command location array to new, free old command
+	 * location array if needed, and mark new array as malloced.
+	 */
+	
+	memcpy((VOID *) newPtr, (VOID *) envPtr->cmdMapPtr, currBytes);
+	if (envPtr->mallocedCmdMap) {
+	    ckfree((char *) envPtr->cmdMapPtr);
+	}
+	envPtr->cmdMapPtr = (CmdLocation *) newPtr;
+	envPtr->cmdMapEnd = newElems;
+	envPtr->mallocedCmdMap = 1;
+    }
+
+    if (cmdIndex > 0) {
+	if (codeOffset < envPtr->cmdMapPtr[cmdIndex-1].codeOffset) {
+	    panic("EnterCmdStartData: cmd map table not sorted by code offset");
+	}
+    }
+
+    cmdLocPtr = &(envPtr->cmdMapPtr[cmdIndex]);
+    cmdLocPtr->codeOffset = codeOffset;
+    cmdLocPtr->srcOffset = srcOffset;
+    cmdLocPtr->numSrcChars = -1;
+    cmdLocPtr->numCodeBytes = -1;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EnterCmdExtentData --
+ *
+ *	Registers the source and bytecode length for a command. This
+ *	information is used at runtime to map between instruction pc and
+ *	source locations.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Inserts source and code length information into the compilation
+ *	environment envPtr for the command at index cmdIndex. Starting
+ *	source and bytecode information for the command must already
+ *	have been registered.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EnterCmdExtentData(envPtr, cmdIndex, numSrcChars, numCodeBytes)
+    CompileEnv *envPtr;		/* Points to the compilation environment
+				 * structure in which to enter command
+				 * location information. */
+    int cmdIndex;		/* Index of the command whose source and
+				 * code length data is being set. */
+    int numSrcChars;		/* Number of command source chars. */
+    int numCodeBytes;		/* Offset of last byte of command code. */
+{
+    CmdLocation *cmdLocPtr;
+
+    if ((cmdIndex < 0) || (cmdIndex >= envPtr->numCommands)) {
+	panic("EnterCmdStartData: bad command index %d\n", cmdIndex);
+    }
+    
+    if (cmdIndex > envPtr->cmdMapEnd) {
+	panic("EnterCmdStartData: no start data registered for command with index %d\n", cmdIndex);
+    }
+
+    cmdLocPtr = &(envPtr->cmdMapPtr[cmdIndex]);
+    cmdLocPtr->numSrcChars = numSrcChars;
+    cmdLocPtr->numCodeBytes = numCodeBytes;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitArgInfo --
+ *
+ *	Initializes a ArgInfo structure to hold information about
+ *	some number of argument words in a command.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The ArgInfo structure is initialized.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitArgInfo(argInfoPtr)
+    register ArgInfo *argInfoPtr; /* Points to the ArgInfo structure
+				   * to initialize. */
+{
+    argInfoPtr->numArgs = 0;
+    argInfoPtr->startArray = argInfoPtr->staticStartSpace;
+    argInfoPtr->endArray   = argInfoPtr->staticEndSpace;
+    argInfoPtr->allocArgs = ARGINFO_INIT_ENTRIES;
+    argInfoPtr->mallocedArrays = 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CollectArgInfo --
+ *
+ *	Procedure to scan the argument words of a command and record the
+ *	start and finish of each argument word in a ArgInfo structure.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is TCL_OK unless
+ *	there was an error while scanning string. If an error occurs then
+ *	the interpreter's result contains a standard error message.
+ *
+ * Side effects:
+ *	If necessary, the argument start and end arrays in *argInfoPtr
+ *	are grown and reallocated to a new arrays of double the size, and
+ *	if argInfoPtr->mallocedArray is non-zero the old arrays are freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CollectArgInfo(interp, string, lastChar, flags, argInfoPtr)
+    Tcl_Interp *interp;         /* Used for error reporting. */
+    char *string;               /* The source command string to scan. */
+    char *lastChar;		 /* Pointer to terminating character of
+				  * string. */
+    int flags;                  /* Flags to control compilation (same as
+                                 * passed to Tcl_Eval). */
+    register ArgInfo *argInfoPtr;
+				/* Points to the ArgInfo structure in which
+				 * to record the arg word information. */
+{
+    register char *src = string;/* Points to current source char. */
+    register int type;		/* Current char's CHAR_TYPE type. */
+    int nestedCmd = (flags & TCL_BRACKET_TERM);
+                                /* 1 if string being scanned is a nested
+				 * command and is terminated by a ']';
+				 * otherwise 0. */
+    int scanningArgs;           /* 1 if still scanning argument words to
+				 * determine their start and end. */
+    char *wordStart, *wordEnd;  /* Points to the first and last significant
+				 * characters of each word. */
+    CompileEnv tempCompEnv;	/* Only used to hold the termOffset field
+				 * updated by AdvanceToNextWord. */
+    char *prev;
+
+    argInfoPtr->numArgs = 0;
+    scanningArgs = 1;
+    while (scanningArgs) {
+	AdvanceToNextWord(src, &tempCompEnv);
+	src += tempCompEnv.termOffset;
+	type = CHAR_TYPE(src, lastChar);
+
+	if ((type == TCL_COMMAND_END) && ((*src != ']') || nestedCmd)) {
+	    break;		    /* done collecting argument words */
+	} else if (*src == '"') {
+	    wordStart = src;
+	    src = TclWordEnd(src, lastChar, nestedCmd, NULL);
+	    if (src == lastChar) {
+	        badStringTermination:
+		Tcl_ResetResult(interp);
+		Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	                "quoted string doesn't terminate properly", -1);
+		return TCL_ERROR;
+	    }
+	    prev = (src-1);
+	    if (*src == '"') {
+		wordEnd = src;
+		src++;
+	    } else if ((*src == ';') && (*prev == '"')) {
+		scanningArgs = 0;
+		wordEnd = prev;
+	    } else {
+		goto badStringTermination;
+	    }
+	} else if (*src == '{') {
+	    wordStart = src;
+	    src = TclWordEnd(src, lastChar, nestedCmd, NULL);
+	    if (src == lastChar) {
+		Tcl_ResetResult(interp);
+		Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		        "missing close-brace", -1);
+		return TCL_ERROR;
+	    }
+	    prev = (src-1);
+	    if (*src == '}') {
+		wordEnd = src;
+		src++;
+	    } else if ((*src == ';') && (*prev == '}')) {
+		scanningArgs = 0;
+		wordEnd = prev;
+	    } else {
+		Tcl_ResetResult(interp);
+		Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	                "argument word in braces doesn't terminate properly", -1);
+		return TCL_ERROR;
+	    }
+	} else {
+	    wordStart = src;
+	    src = TclWordEnd(src, lastChar, nestedCmd, NULL);
+	    prev = (src-1);
+	    if (src == lastChar) {
+		Tcl_ResetResult(interp);
+		Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		        "missing close-bracket or close-brace", -1);
+		return TCL_ERROR;
+	    } else if (*src == ';') {
+		scanningArgs = 0;
+		wordEnd = prev;
+	    } else {
+		wordEnd = src;
+		src++;
+		if ((src == lastChar) || (*src == '\n')
+	                || ((*src == ']') && nestedCmd)) {
+		    scanningArgs = 0;
+		}
+	    }
+	} /* end of test on each kind of word */
+
+	if (argInfoPtr->numArgs == argInfoPtr->allocArgs) {
+	    int newArgs = 2*argInfoPtr->numArgs;
+	    size_t currBytes = argInfoPtr->numArgs * sizeof(char *);
+	    size_t newBytes  = newArgs * sizeof(char *);
+	    char **newStartArrayPtr =
+		    (char **) ckalloc((unsigned) newBytes);
+	    char **newEndArrayPtr =
+		    (char **) ckalloc((unsigned) newBytes);
+	    
+	    /*
+	     * Copy from the old arrays to the new, free the old arrays if
+	     * needed, and mark the new arrays as malloc'ed.
+	     */
+	    
+	    memcpy((VOID *) newStartArrayPtr,
+	            (VOID *) argInfoPtr->startArray, currBytes);
+	    memcpy((VOID *) newEndArrayPtr,
+		    (VOID *) argInfoPtr->endArray, currBytes);
+	    if (argInfoPtr->mallocedArrays) {
+		ckfree((char *) argInfoPtr->startArray);
+		ckfree((char *) argInfoPtr->endArray);
+	    }
+	    argInfoPtr->startArray = newStartArrayPtr;
+	    argInfoPtr->endArray   = newEndArrayPtr;
+	    argInfoPtr->allocArgs = newArgs;
+	    argInfoPtr->mallocedArrays = 1;
+	}
+	argInfoPtr->startArray[argInfoPtr->numArgs] = wordStart;
+	argInfoPtr->endArray[argInfoPtr->numArgs]   = wordEnd;
+	argInfoPtr->numArgs++;
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeArgInfo --
+ *
+ *	Free any storage allocated in a ArgInfo structure.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Allocated storage in the ArgInfo structure is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeArgInfo(argInfoPtr)
+    register ArgInfo *argInfoPtr; /* Points to the ArgInfo structure
+				   * to free. */
+{
+    if (argInfoPtr->mallocedArrays) {
+	ckfree((char *) argInfoPtr->startArray);
+	ckfree((char *) argInfoPtr->endArray);
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CreateExceptionRange --
+ *
+ *	Procedure that allocates and initializes a new ExceptionRange
+ *	structure of the specified kind in a CompileEnv's ExceptionRange
+ *	array.
+ *
+ * Results:
+ *	Returns the index for the newly created ExceptionRange.
+ *
+ * Side effects:
+ *	If there is not enough room in the CompileEnv's ExceptionRange
+ *	array, the array in expanded: a new array of double the size is
+ *	allocated, if envPtr->mallocedExcRangeArray is non-zero the old
+ *	array is freed, and ExceptionRange entries are copied from the old
+ *	array to the new one.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CreateExceptionRange(type, envPtr)
+    ExceptionRangeType type;	/* The kind of ExceptionRange desired. */
+    register CompileEnv *envPtr;/* Points to the CompileEnv for which a new
+				 * loop ExceptionRange structure is to be
+				 * allocated. */
+{
+    int index;			/* Index for the newly-allocated
+				 * ExceptionRange structure. */
+    register ExceptionRange *rangePtr;
+    				/* Points to the new ExceptionRange
+				 * structure */
+    
+    index = envPtr->excRangeArrayNext;
+    if (index >= envPtr->excRangeArrayEnd) {
+        /*
+	 * Expand the ExceptionRange array. The currently allocated entries
+	 * are stored between elements 0 and (envPtr->excRangeArrayNext - 1)
+	 * [inclusive].
+	 */
+	
+	size_t currBytes =
+	        envPtr->excRangeArrayNext * sizeof(ExceptionRange);
+	int newElems = 2*envPtr->excRangeArrayEnd;
+	size_t newBytes = newElems * sizeof(ExceptionRange);
+	ExceptionRange *newPtr = (ExceptionRange *)
+	        ckalloc((unsigned) newBytes);
+	
+	/*
+	 * Copy from old ExceptionRange array to new, free old
+	 * ExceptionRange array if needed, and mark the new ExceptionRange
+	 * array as malloced.
+	 */
+	
+	memcpy((VOID *) newPtr, (VOID *) envPtr->excRangeArrayPtr,
+	        currBytes);
+	if (envPtr->mallocedExcRangeArray) {
+	    ckfree((char *) envPtr->excRangeArrayPtr);
+	}
+	envPtr->excRangeArrayPtr = (ExceptionRange *) newPtr;
+	envPtr->excRangeArrayEnd = newElems;
+	envPtr->mallocedExcRangeArray = 1;
+    }
+    envPtr->excRangeArrayNext++;
+    
+    rangePtr = &(envPtr->excRangeArrayPtr[index]);
+    rangePtr->type = type;
+    rangePtr->nestingLevel = envPtr->excRangeDepth;
+    rangePtr->codeOffset = -1;
+    rangePtr->numCodeBytes = -1;
+    rangePtr->breakOffset = -1;
+    rangePtr->continueOffset = -1;
+    rangePtr->catchOffset = -1;
+    return index;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCreateAuxData --
+ *
+ *	Procedure that allocates and initializes a new AuxData structure in
+ *	a CompileEnv's array of compilation auxiliary data records. These
+ *	AuxData records hold information created during compilation by
+ *	CompileProcs and used by instructions during execution.
+ *
+ * Results:
+ *	Returns the index for the newly created AuxData structure.
+ *
+ * Side effects:
+ *	If there is not enough room in the CompileEnv's AuxData array,
+ *	the AuxData array in expanded: a new array of double the size
+ *	is allocated, if envPtr->mallocedAuxDataArray is non-zero
+ *	the old array is freed, and AuxData entries are copied from
+ *	the old array to the new one.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCreateAuxData(clientData, typePtr, envPtr)
+    ClientData clientData;	/* The compilation auxiliary data to store
+                             * in the new aux data record. */
+    AuxDataType *typePtr;	/* Pointer to the type to attach to this AuxData */
+    register CompileEnv *envPtr;/* Points to the CompileEnv for which a new
+                                 * aux data structure is to be allocated. */
+{
+    int index;			/* Index for the new AuxData structure. */
+    register AuxData *auxDataPtr;
+    				/* Points to the new AuxData structure */
+    
+    index = envPtr->auxDataArrayNext;
+    if (index >= envPtr->auxDataArrayEnd) {
+        /*
+	 * Expand the AuxData array. The currently allocated entries are
+	 * stored between elements 0 and (envPtr->auxDataArrayNext - 1)
+	 * [inclusive].
+	 */
+	
+	size_t currBytes = envPtr->auxDataArrayNext * sizeof(AuxData);
+	int newElems = 2*envPtr->auxDataArrayEnd;
+	size_t newBytes = newElems * sizeof(AuxData);
+	AuxData *newPtr = (AuxData *) ckalloc((unsigned) newBytes);
+	
+	/*
+	 * Copy from old AuxData array to new, free old AuxData array if
+	 * needed, and mark the new AuxData array as malloced.
+	 */
+	
+	memcpy((VOID *) newPtr, (VOID *) envPtr->auxDataArrayPtr,
+	        currBytes);
+	if (envPtr->mallocedAuxDataArray) {
+	    ckfree((char *) envPtr->auxDataArrayPtr);
+	}
+	envPtr->auxDataArrayPtr = newPtr;
+	envPtr->auxDataArrayEnd = newElems;
+	envPtr->mallocedAuxDataArray = 1;
+    }
+    envPtr->auxDataArrayNext++;
+    
+    auxDataPtr = &(envPtr->auxDataArrayPtr[index]);
+    auxDataPtr->type = typePtr;
+    auxDataPtr->clientData = clientData;
+    return index;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInitJumpFixupArray --
+ *
+ *	Initializes a JumpFixupArray structure to hold some number of
+ *	jump fixup entries.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The JumpFixupArray structure is initialized.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclInitJumpFixupArray(fixupArrayPtr)
+    register JumpFixupArray *fixupArrayPtr;
+				 /* Points to the JumpFixupArray structure
+				  * to initialize. */
+{
+    fixupArrayPtr->fixup = fixupArrayPtr->staticFixupSpace;
+    fixupArrayPtr->next = 0;
+    fixupArrayPtr->end = (JUMPFIXUP_INIT_ENTRIES - 1);
+    fixupArrayPtr->mallocedArray = 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclExpandJumpFixupArray --
+ *
+ *	Procedure that uses malloc to allocate more storage for a
+ *      jump fixup array.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The jump fixup array in *fixupArrayPtr is reallocated to a new array
+ *	of double the size, and if fixupArrayPtr->mallocedArray is non-zero
+ *	the old array is freed. Jump fixup structures are copied from the
+ *	old array to the new one.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclExpandJumpFixupArray(fixupArrayPtr)
+    register JumpFixupArray *fixupArrayPtr;
+				 /* Points to the JumpFixupArray structure
+				  * to enlarge. */
+{
+    /*
+     * The currently allocated jump fixup entries are stored from fixup[0]
+     * up to fixup[fixupArrayPtr->fixupNext] (*not* inclusive). We assume
+     * fixupArrayPtr->fixupNext is equal to fixupArrayPtr->fixupEnd.
+     */
+
+    size_t currBytes = fixupArrayPtr->next * sizeof(JumpFixup);
+    int newElems = 2*(fixupArrayPtr->end + 1);
+    size_t newBytes = newElems * sizeof(JumpFixup);
+    JumpFixup *newPtr = (JumpFixup *) ckalloc((unsigned) newBytes);
+
+    /*
+     * Copy from the old array to new, free the old array if needed,
+     * and mark the new array as malloced.
+     */
+ 
+    memcpy((VOID *) newPtr, (VOID *) fixupArrayPtr->fixup, currBytes);
+    if (fixupArrayPtr->mallocedArray) {
+	ckfree((char *) fixupArrayPtr->fixup);
+    }
+    fixupArrayPtr->fixup = (JumpFixup *) newPtr;
+    fixupArrayPtr->end = newElems;
+    fixupArrayPtr->mallocedArray = 1;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFreeJumpFixupArray --
+ *
+ *	Free any storage allocated in a jump fixup array structure.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Allocated storage in the JumpFixupArray structure is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclFreeJumpFixupArray(fixupArrayPtr)
+    register JumpFixupArray *fixupArrayPtr;
+				 /* Points to the JumpFixupArray structure
+				  * to free. */
+{
+    if (fixupArrayPtr->mallocedArray) {
+	ckfree((char *) fixupArrayPtr->fixup);
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclEmitForwardJump --
+ *
+ *	Procedure to emit a two-byte forward jump of kind "jumpType". Since
+ *	the jump may later have to be grown to five bytes if the jump target
+ *	is more than, say, 127 bytes away, this procedure also initializes a
+ *	JumpFixup record with information about the jump. 
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The JumpFixup record pointed to by "jumpFixupPtr" is initialized
+ *	with information needed later if the jump is to be grown. Also,
+ *	a two byte jump of the designated type is emitted at the current
+ *	point in the bytecode stream.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclEmitForwardJump(envPtr, jumpType, jumpFixupPtr)
+    CompileEnv *envPtr;		/* Points to the CompileEnv structure that
+				 * holds the resulting instruction. */
+    TclJumpType jumpType;	/* Indicates the kind of jump: if true or
+				 * false or unconditional. */
+    JumpFixup *jumpFixupPtr;	/* Points to the JumpFixup structure to
+				 * initialize with information about this
+				 * forward jump. */
+{
+    /*
+     * Initialize the JumpFixup structure:
+     *    - codeOffset is offset of first byte of jump below
+     *    - cmdIndex is index of the command after the current one
+     *    - excRangeIndex is the index of the first ExceptionRange after
+     *      the current one.
+     */
+    
+    jumpFixupPtr->jumpType = jumpType;
+    jumpFixupPtr->codeOffset = TclCurrCodeOffset();
+    jumpFixupPtr->cmdIndex = envPtr->numCommands;
+    jumpFixupPtr->excRangeIndex = envPtr->excRangeArrayNext;
+    
+    switch (jumpType) {
+    case TCL_UNCONDITIONAL_JUMP:
+	TclEmitInstInt1(INST_JUMP1, /*offset*/ 0, envPtr);
+	break;
+    case TCL_TRUE_JUMP:
+	TclEmitInstInt1(INST_JUMP_TRUE1, /*offset*/ 0, envPtr);
+	break;
+    default:
+	TclEmitInstInt1(INST_JUMP_FALSE1, /*offset*/ 0, envPtr);
+	break;
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFixupForwardJump --
+ *
+ *	Procedure that updates a previously-emitted forward jump to jump
+ *	a specified number of bytes, "jumpDist". If necessary, the jump is
+ *      grown from two to five bytes; this is done if the jump distance is
+ *	greater than "distThreshold" (normally 127 bytes). The jump is
+ *	described by a JumpFixup record previously initialized by
+ *	TclEmitForwardJump.
+ *
+ * Results:
+ *	1 if the jump was grown and subsequent instructions had to be moved;
+ *	otherwise 0. This result is returned to allow callers to update
+ *	any additional code offsets they may hold.
+ *
+ * Side effects:
+ *	The jump may be grown and subsequent instructions moved. If this
+ *	happens, the code offsets for any commands and any ExceptionRange
+ *	records	between the jump and the current code address will be
+ *	updated to reflect the moved code. Also, the bytecode instruction
+ *	array in the CompileEnv structure may be grown and reallocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclFixupForwardJump(envPtr, jumpFixupPtr, jumpDist, distThreshold)
+    CompileEnv *envPtr;		/* Points to the CompileEnv structure that
+				 * holds the resulting instruction. */
+    JumpFixup *jumpFixupPtr;    /* Points to the JumpFixup structure that
+				 * describes the forward jump. */
+    int jumpDist;		/* Jump distance to set in jump
+				 * instruction. */
+    int distThreshold;		/* Maximum distance before the two byte
+				 * jump is grown to five bytes. */
+{
+    unsigned char *jumpPc, *p;
+    int firstCmd, lastCmd, firstRange, lastRange, k;
+    unsigned int numBytes;
+    
+    if (jumpDist <= distThreshold) {
+	jumpPc = (envPtr->codeStart + jumpFixupPtr->codeOffset);
+	switch (jumpFixupPtr->jumpType) {
+	case TCL_UNCONDITIONAL_JUMP:
+	    TclUpdateInstInt1AtPc(INST_JUMP1, jumpDist, jumpPc);
+	    break;
+	case TCL_TRUE_JUMP:
+	    TclUpdateInstInt1AtPc(INST_JUMP_TRUE1, jumpDist, jumpPc);
+	    break;
+	default:
+	    TclUpdateInstInt1AtPc(INST_JUMP_FALSE1, jumpDist, jumpPc);
+	    break;
+	}
+	return 0;
+    }
+
+    /*
+     * We must grow the jump then move subsequent instructions down.
+     */
+    
+    TclEnsureCodeSpace(3, envPtr);  /* NB: might change code addresses! */
+    jumpPc = (envPtr->codeStart + jumpFixupPtr->codeOffset);
+    for (numBytes = envPtr->codeNext-jumpPc-2, p = jumpPc+2+numBytes-1;
+	    numBytes > 0;  numBytes--, p--) {
+	p[3] = p[0];
+    }
+    envPtr->codeNext += 3;
+    jumpDist += 3;
+    switch (jumpFixupPtr->jumpType) {
+    case TCL_UNCONDITIONAL_JUMP:
+	TclUpdateInstInt4AtPc(INST_JUMP4, jumpDist, jumpPc);
+	break;
+    case TCL_TRUE_JUMP:
+	TclUpdateInstInt4AtPc(INST_JUMP_TRUE4, jumpDist, jumpPc);
+	break;
+    default:
+	TclUpdateInstInt4AtPc(INST_JUMP_FALSE4, jumpDist, jumpPc);
+	break;
+    }
+    
+    /*
+     * Adjust the code offsets for any commands and any ExceptionRange
+     * records between the jump and the current code address.
+     */
+    
+    firstCmd = jumpFixupPtr->cmdIndex;
+    lastCmd  = (envPtr->numCommands - 1);
+    if (firstCmd < lastCmd) {
+	for (k = firstCmd;  k <= lastCmd;  k++) {
+	    (envPtr->cmdMapPtr[k]).codeOffset += 3;
+	}
+    }
+    
+    firstRange = jumpFixupPtr->excRangeIndex;
+    lastRange  = (envPtr->excRangeArrayNext - 1);
+    for (k = firstRange;  k <= lastRange;  k++) {
+	ExceptionRange *rangePtr = &(envPtr->excRangeArrayPtr[k]);
+	rangePtr->codeOffset += 3;
+	
+	switch (rangePtr->type) {
+	case LOOP_EXCEPTION_RANGE:
+	    rangePtr->breakOffset += 3;
+	    if (rangePtr->continueOffset != -1) {
+		rangePtr->continueOffset += 3;
+	    }
+	    break;
+	case CATCH_EXCEPTION_RANGE:
+	    rangePtr->catchOffset += 3;
+	    break;
+	default:
+	    panic("TclFixupForwardJump: unrecognized ExceptionRange type %d\n", rangePtr->type);
+	}
+    }
+    return 1;			/* the jump was grown */
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetInstructionTable --
+ *
+ *  Returns a pointer to the table describing Tcl bytecode instructions.
+ *  This procedure is defined so that clients can access the pointer from
+ *  outside the TCL DLLs.
+ *
+ * Results:
+ *	Returns a pointer to the global instruction table, same as the expression
+ *  (&instructionTable[0]).
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+InstructionDesc *
+TclGetInstructionTable()
+{
+    return &instructionTable[0];
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TclRegisterAuxDataType --
+ *
+ *	This procedure is called to register a new AuxData type
+ *	in the table of all AuxData types supported by Tcl.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The type is registered in the AuxData type table. If there was already
+ *	a type with the same name as in typePtr, it is replaced with the
+ *	new type.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TclRegisterAuxDataType(typePtr)
+    AuxDataType *typePtr;	/* Information about object type;
+                             * storage must be statically
+                             * allocated (must live forever). */
+{
+    register Tcl_HashEntry *hPtr;
+    int new;
+
+    if (!auxDataTypeTableInitialized) {
+        TclInitAuxDataTypeTable();
+    }
+
+    /*
+     * If there's already a type with the given name, remove it.
+     */
+
+    hPtr = Tcl_FindHashEntry(&auxDataTypeTable, typePtr->name);
+    if (hPtr != (Tcl_HashEntry *) NULL) {
+        Tcl_DeleteHashEntry(hPtr);
+    }
+
+    /*
+     * Now insert the new object type.
+     */
+
+    hPtr = Tcl_CreateHashEntry(&auxDataTypeTable, typePtr->name, &new);
+    if (new) {
+        Tcl_SetHashValue(hPtr, typePtr);
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetAuxDataType --
+ *
+ *	This procedure looks up an Auxdata type by name.
+ *
+ * Results:
+ *	If an AuxData type with name matching "typeName" is found, a pointer
+ *	to its AuxDataType structure is returned; otherwise, NULL is returned.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+AuxDataType *
+TclGetAuxDataType(typeName)
+    char *typeName;		/* Name of AuxData type to look up. */
+{
+    register Tcl_HashEntry *hPtr;
+    AuxDataType *typePtr = NULL;
+
+    if (!auxDataTypeTableInitialized) {
+        TclInitAuxDataTypeTable();
+    }
+
+    hPtr = Tcl_FindHashEntry(&auxDataTypeTable, typeName);
+    if (hPtr != (Tcl_HashEntry *) NULL) {
+        typePtr = (AuxDataType *) Tcl_GetHashValue(hPtr);
+    }
+
+    return typePtr;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TclInitAuxDataTypeTable --
+ *
+ *	This procedure is invoked to perform once-only initialization of
+ *	the AuxData type table. It also registers the AuxData types defined in 
+ *	this file.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Initializes the table of defined AuxData types "auxDataTypeTable" with
+ *	builtin AuxData types defined in this file.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TclInitAuxDataTypeTable()
+{
+    auxDataTypeTableInitialized = 1;
+
+    Tcl_InitHashTable(&auxDataTypeTable, TCL_STRING_KEYS);
+    TclRegisterAuxDataType(&tclForeachInfoType);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFinalizeAuxDataTypeTable --
+ *
+ *	This procedure is called by Tcl_Finalize after all exit handlers
+ *	have been run to free up storage associated with the table of AuxData
+ *	types.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Deletes all entries in the hash table of AuxData types, "auxDataTypeTable".
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclFinalizeAuxDataTypeTable()
+{
+    if (auxDataTypeTableInitialized) {
+        Tcl_DeleteHashTable(&auxDataTypeTable);
+        auxDataTypeTableInitialized = 0;
+    }
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclCompile.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclCompile.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclCompile.h	(revision 5)
@@ -0,0 +1,1054 @@
+/*
+ * tclCompile.h --
+ *
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclCompile.h,v 1.1 2008-06-04 13:58:05 demin Exp $
+ */
+
+#ifndef _TCLCOMPILATION
+#define _TCLCOMPILATION 1
+
+#ifndef _TCLINT
+#include "tclInt.h"
+#endif /* _TCLINT */
+
+#ifdef BUILD_tcl
+# undef TCL_STORAGE_CLASS
+# define TCL_STORAGE_CLASS DLLEXPORT
+#endif
+
+/*
+ *------------------------------------------------------------------------
+ * Variables related to compilation. These are used in tclCompile.c,
+ * tclExecute.c, tclBasic.c, and their clients.
+ *------------------------------------------------------------------------
+ */
+
+/*
+ * Variable that denotes the command name Tcl object type. Objects of this
+ * type cache the Command pointer that results from looking up command names
+ * in the command hashtable.
+ */
+
+extern Tcl_ObjType	tclCmdNameType;
+
+/*
+ * Variable that controls whether compilation tracing is enabled and, if so,
+ * what level of tracing is desired:
+ *    0: no compilation tracing
+ *    1: summarize compilation of top level cmds and proc bodies
+ *    2: display all instructions of each ByteCode compiled
+ * This variable is linked to the Tcl variable "tcl_traceCompile".
+ */
+
+extern int 		tclTraceCompile;
+
+/*
+ * Variable that controls whether execution tracing is enabled and, if so,
+ * what level of tracing is desired:
+ *    0: no execution tracing
+ *    1: trace invocations of Tcl procs only
+ *    2: trace invocations of all (not compiled away) commands
+ *    3: display each instruction executed
+ * This variable is linked to the Tcl variable "tcl_traceExec".
+ */
+
+extern int 		tclTraceExec;
+
+/*
+ * The number of bytecode compilations and various other compilation-related
+ * statistics. The tclByteCodeCount and tclSourceCount arrays are used to
+ * hold the count of ByteCodes and sources whose sizes fall into various
+ * binary decades; e.g., tclByteCodeCount[5] is a count of the ByteCodes
+ * with size larger than 2**4 and less than or equal to 2**5.
+ */
+
+#ifdef TCL_COMPILE_STATS
+extern long		tclNumCompilations;
+extern double		tclTotalSourceBytes;
+extern double		tclTotalCodeBytes;
+
+extern double		tclTotalInstBytes;
+extern double		tclTotalObjBytes;
+extern double		tclTotalExceptBytes;
+extern double		tclTotalAuxBytes;
+extern double		tclTotalCmdMapBytes;
+
+extern double		tclCurrentSourceBytes;
+extern double		tclCurrentCodeBytes;
+
+extern int		tclSourceCount[32];
+extern int		tclByteCodeCount[32];
+#endif /* TCL_COMPILE_STATS */
+
+/*
+ *------------------------------------------------------------------------
+ * Data structures related to compilation.
+ *------------------------------------------------------------------------
+ */
+
+/*
+ * The structure used to implement Tcl "exceptions" (exceptional returns):
+ * for example, those generated in loops by the break and continue commands,
+ * and those generated by scripts and caught by the catch command. This
+ * ExceptionRange structure describes a range of code (e.g., a loop body),
+ * the kind of exceptions (e.g., a break or continue) that might occur, and
+ * the PC offsets to jump to if a matching exception does occur. Exception
+ * ranges can nest so this structure includes a nesting level that is used
+ * at runtime to find the closest exception range surrounding a PC. For
+ * example, when a break command is executed, the ExceptionRange structure
+ * for the most deeply nested loop, if any, is found and used. These
+ * structures are also generated for the "next" subcommands of for loops
+ * since a break there terminates the for command. This means a for command
+ * actually generates two LoopInfo structures.
+ */
+
+typedef enum {
+    LOOP_EXCEPTION_RANGE,	/* Code range is part of a loop command.
+				 * break and continue "exceptions" cause
+				 * jumps to appropriate PC offsets. */
+    CATCH_EXCEPTION_RANGE	/* Code range is controlled by a catch
+				 * command. Errors in the range cause a
+				 * jump to a particular PC offset. */
+} ExceptionRangeType;
+
+typedef struct ExceptionRange {
+    ExceptionRangeType type;	/* The kind of ExceptionRange. */
+    int nestingLevel;		/* Static depth of the exception range.
+				 * Used to find the most deeply-nested
+				 * range surrounding a PC at runtime. */
+    int codeOffset;		/* Offset of the first instruction byte of
+				 * the code range. */
+    int numCodeBytes;		/* Number of bytes in the code range. */
+    int breakOffset;		/* If a LOOP_EXCEPTION_RANGE, the target
+				 * PC offset for a break command in the
+				 * range. */
+    int continueOffset;		/* If a LOOP_EXCEPTION_RANGE and not -1,
+				 * the target PC offset for a continue
+				 * command in the code range. Otherwise,
+				 * ignore this range when processing a
+				 * continue command. */
+    int catchOffset;		/* If a CATCH_EXCEPTION_RANGE, the target PC
+				 * offset for an "exception" in range. */
+} ExceptionRange;
+
+/*
+ * Structure used to map between instruction pc and source locations. It
+ * defines for each compiled Tcl command its code's starting offset and 
+ * its source's starting offset and length. Note that the code offset
+ * increases monotonically: that is, the table is sorted in code offset
+ * order. The source offset is not monotonic.
+ */
+
+typedef struct CmdLocation {
+    int codeOffset;		/* Offset of first byte of command code. */
+    int numCodeBytes;		/* Number of bytes for command's code. */
+    int srcOffset;		/* Offset of first char of the command. */
+    int numSrcChars;		/* Number of command source chars. */
+} CmdLocation;
+
+/*
+ * CompileProcs need the ability to record information during compilation
+ * that can be used by bytecode instructions during execution. The AuxData
+ * structure provides this "auxiliary data" mechanism. An arbitrary number
+ * of these structures can be stored in the ByteCode record (during
+ * compilation they are stored in a CompileEnv structure). Each AuxData
+ * record holds one word of client-specified data (often a pointer) and is
+ * given an index that instructions can later use to look up the structure
+ * and its data.
+ *
+ * The following definitions declare the types of procedures that are called
+ * to duplicate or free this auxiliary data when the containing ByteCode
+ * objects are duplicated and freed. Pointers to these procedures are kept
+ * in the AuxData structure.
+ */
+
+typedef ClientData (AuxDataDupProc)  _ANSI_ARGS_((ClientData clientData));
+typedef void       (AuxDataFreeProc) _ANSI_ARGS_((ClientData clientData));
+
+/*
+ * We define a separate AuxDataType struct to hold type-related information
+ * for the AuxData structure. This separation makes it possible for clients
+ * outside of the TCL core to manipulate (in a limited fashion!) AuxData;
+ * for example, it makes it possible to pickle and unpickle AuxData structs.
+ */
+
+typedef struct AuxDataType {
+    char *name;					/* the name of the type. Types can be
+                                 * registered and found by name */
+    AuxDataDupProc *dupProc;	/* Callback procedure to invoke when the
+                                 * aux data is duplicated (e.g., when the
+                                 * ByteCode structure containing the aux
+                                 * data is duplicated). NULL means just
+                                 * copy the source clientData bits; no
+                                 * proc need be called. */
+    AuxDataFreeProc *freeProc;	/* Callback procedure to invoke when the
+                                 * aux data is freed. NULL means no
+                                 * proc need be called. */
+} AuxDataType;
+
+/*
+ * The definition of the AuxData structure that holds information created
+ * during compilation by CompileProcs and used by instructions during
+ * execution.
+ */
+
+typedef struct AuxData {
+    AuxDataType *type;		/* pointer to the AuxData type associated with
+                             * this ClientData. */
+    ClientData clientData;	/* The compilation data itself. */
+} AuxData;
+
+/*
+ * Structure defining the compilation environment. After compilation, fields
+ * describing bytecode instructions are copied out into the more compact
+ * ByteCode structure defined below.
+ */
+
+#define COMPILEENV_INIT_CODE_BYTES    250
+#define COMPILEENV_INIT_NUM_OBJECTS    40
+#define COMPILEENV_INIT_EXCEPT_RANGES   5
+#define COMPILEENV_INIT_CMD_MAP_SIZE   40
+#define COMPILEENV_INIT_AUX_DATA_SIZE   5
+
+typedef struct CompileEnv {
+    Interp *iPtr;		/* Interpreter containing the code being
+				 * compiled. Commands and their compile
+				 * procs are specific to an interpreter so
+				 * the code emitted will depend on the
+				 * interpreter. */
+    char *source;		/* The source string being compiled by
+				 * SetByteCodeFromAny. This pointer is not
+				 * owned by the CompileEnv and must not be
+				 * freed or changed by it. */
+    Proc *procPtr;		/* If a procedure is being compiled, a
+				 * pointer to its Proc structure; otherwise
+				 * NULL. Used to compile local variables.
+				 * Set from information provided by
+				 * ObjInterpProc in tclProc.c. */
+    int numCommands;		/* Number of commands compiled. */
+    int excRangeDepth;		/* Current exception range nesting level;
+				 * -1 if not in any range currently. */
+    int maxExcRangeDepth;	/* Max nesting level of exception ranges;
+				 * -1 if no ranges have been compiled. */
+    int maxStackDepth;		/* Maximum number of stack elements needed
+				 * to execute the code. Set by compilation
+				 * procedures before returning. */
+    Tcl_HashTable objTable;	/* Contains all Tcl objects referenced by
+				 * the compiled code. Indexed by the string
+				 * representations of the objects. Used to
+				 * avoid creating duplicate objects. */
+    int pushSimpleWords;	/* Set 1 by callers of compilation routines
+				 * if they should emit instructions to push
+				 * "simple" command words (those that are
+				 * just a sequence of characters). If 0, the
+				 * callers are responsible for compiling
+				 * simple words. */
+    int wordIsSimple;		/* Set 1 by compilation procedures before
+				 * returning if the previous command word
+				 * was just a sequence of characters,
+				 * otherwise 0. Used to help determine the
+				 * command being compiled. */
+    int numSimpleWordChars;	/* If wordIsSimple is 1 then the number of
+				 * characters in the simple word, else 0. */
+    int exprIsJustVarRef;	/* Set 1 if the expression last compiled by
+				 * TclCompileExpr consisted of just a
+				 * variable reference as in the expression
+				 * of "if $b then...". Otherwise 0. Used
+				 * to implement expr's 2 level substitution
+				 * semantics properly. */
+    int exprIsComparison;	/* Set 1 if the top-level operator in the
+				 * expression last compiled is a comparison.
+				 * Otherwise 0. If 1, since the operands
+				 * might be strings, the expr is compiled
+				 * out-of-line to implement expr's 2 level
+				 * substitution semantics properly. */
+    int termOffset;		/* Offset of character just after the last
+				 * one compiled. Set by compilation
+				 * procedures before returning. */
+    unsigned char *codeStart;	/* Points to the first byte of the code. */
+    unsigned char *codeNext;	/* Points to next code array byte to use. */
+    unsigned char *codeEnd;	/* Points just after the last allocated
+				 * code array byte. */
+    int mallocedCodeArray;      /* Set 1 if code array was expanded 
+				 * and codeStart points into the heap.*/
+    Tcl_Obj **objArrayPtr;	/* Points to start of object array. */
+    int objArrayNext;		/* Index of next free object array entry. */
+    int objArrayEnd;		/* Index just after last obj array entry. */
+    int mallocedObjArray;       /* 1 if object array was expanded and
+                                 * objArray points into the heap, else 0. */
+    ExceptionRange *excRangeArrayPtr;
+    				/* Points to start of the ExceptionRange
+				 * array. */
+    int excRangeArrayNext;	/* Next free ExceptionRange array index.
+				 * excRangeArrayNext is the number of ranges
+				 * and (excRangeArrayNext-1) is the index of
+				 * the current range's array entry. */
+    int excRangeArrayEnd;	/* Index after the last ExceptionRange
+				 * array entry. */
+    int mallocedExcRangeArray;	/* 1 if ExceptionRange array was expanded
+				 * and excRangeArrayPtr points in heap,
+				 * else 0. */
+    CmdLocation *cmdMapPtr;	/* Points to start of CmdLocation array.
+				 * numCommands is the index of the next
+				 * entry to use; (numCommands-1) is the
+				 * entry index for the last command. */
+    int cmdMapEnd;		/* Index after last CmdLocation entry. */
+    int mallocedCmdMap;		/* 1 if command map array was expanded and
+				 * cmdMapPtr points in the heap, else 0. */
+    AuxData *auxDataArrayPtr;   /* Points to auxiliary data array start. */
+    int auxDataArrayNext;	/* Next free compile aux data array index.
+				 * auxDataArrayNext is the number of aux
+				 * data items and (auxDataArrayNext-1) is
+				 * index of current aux data array entry. */
+    int auxDataArrayEnd;	/* Index after last aux data array entry. */
+    int mallocedAuxDataArray;	/* 1 if aux data array was expanded and
+				 * auxDataArrayPtr points in heap else 0. */
+    unsigned char staticCodeSpace[COMPILEENV_INIT_CODE_BYTES];
+                                /* Initial storage for code. */
+    Tcl_Obj *staticObjArraySpace[COMPILEENV_INIT_NUM_OBJECTS];
+                                /* Initial storage for object array. */
+    ExceptionRange staticExcRangeArraySpace[COMPILEENV_INIT_EXCEPT_RANGES];
+                                /* Initial ExceptionRange array storage. */
+    CmdLocation staticCmdMapSpace[COMPILEENV_INIT_CMD_MAP_SIZE];
+                                /* Initial storage for cmd location map. */
+    AuxData staticAuxDataArraySpace[COMPILEENV_INIT_AUX_DATA_SIZE];
+                                /* Initial storage for aux data array. */
+} CompileEnv;
+
+/*
+ * The structure defining the bytecode instructions resulting from compiling
+ * a Tcl script. Note that this structure is variable length: a single heap
+ * object is allocated to hold the ByteCode structure immediately followed
+ * by the code bytes, the object array, the ExceptionRange array, the
+ * CmdLocation map, and the compilation AuxData array.
+ */
+
+/*
+ * A PRECOMPILED bytecode struct is one that was generated from a compiled
+ * image rather than implicitly compiled from source
+ */
+#define TCL_BYTECODE_PRECOMPILED		0x0001
+
+typedef struct ByteCode {
+    Interp *iPtr;		/* Interpreter containing the code being
+				 * compiled. Commands and their compile
+				 * procs are specific to an interpreter so
+				 * the code emitted will depend on the
+				 * interpreter. */
+    int compileEpoch;		/* Value of iPtr->compileEpoch when this
+				 * ByteCode was compiled. Used to invalidate
+				 * code when, e.g., commands with compile
+				 * procs are redefined. */
+    Namespace *nsPtr;		/* Namespace context in which this code
+				 * was compiled. If the code is executed
+				 * if a different namespace, it must be
+				 * recompiled. */
+    int nsEpoch;		/* Value of nsPtr->resolverEpoch when this
+				 * ByteCode was compiled. Used to invalidate
+				 * code when new namespace resolution rules
+				 * are put into effect. */
+    int refCount;		/* Reference count: set 1 when created
+				 * plus 1 for each execution of the code
+				 * currently active. This structure can be
+				 * freed when refCount becomes zero. */
+    unsigned int flags;		/* flags describing state for the codebyte.
+                                 * this variable holds ORed values from the
+                                 * TCL_BYTECODE_ masks defined above */
+    char *source;		/* The source string from which this
+				 * ByteCode was compiled. Note that this
+				 * pointer is not owned by the ByteCode and
+				 * must not be freed or modified by it. */
+    Proc *procPtr;		/* If the ByteCode was compiled from a
+				 * procedure body, this is a pointer to its
+				 * Proc structure; otherwise NULL. This
+				 * pointer is also not owned by the ByteCode
+				 * and must not be freed by it. Used for
+				 * debugging. */
+    size_t totalSize;		/* Total number of bytes required for this
+				 * ByteCode structure including the storage
+				 * for Tcl objects in its object array. */
+    int numCommands;		/* Number of commands compiled. */
+    int numSrcChars;		/* Number of source chars compiled. */
+    int numCodeBytes;		/* Number of code bytes. */
+    int numObjects;		/* Number of Tcl objects in object array. */
+    int numExcRanges;		/* Number of ExceptionRange array elems. */
+    int numAuxDataItems;	/* Number of AuxData items. */
+    int numCmdLocBytes;		/* Number of bytes needed for encoded
+				 * command location information. */
+    int maxExcRangeDepth;	/* Maximum nesting level of ExceptionRanges;
+				 * -1 if no ranges were compiled. */
+    int maxStackDepth;		/* Maximum number of stack elements needed
+				 * to execute the code. */
+    unsigned char *codeStart;	/* Points to the first byte of the code.
+				 * This is just after the final ByteCode
+				 * member cmdMapPtr. */
+    Tcl_Obj **objArrayPtr;	/* Points to the start of the object array.
+				 * This is just after the last code byte. */
+    ExceptionRange *excRangeArrayPtr;
+    				/* Points to the start of the ExceptionRange
+				 * array. This is just after the last
+				 * object in the object array. */
+    AuxData *auxDataArrayPtr;   /* Points to the start of the auxiliary data
+				 * array. This is just after the last entry
+				 * in the ExceptionRange array. */
+    unsigned char *codeDeltaStart;
+				/* Points to the first of a sequence of
+				 * bytes that encode the change in the
+				 * starting offset of each command's code.
+				 * If -127<=delta<=127, it is encoded as 1
+				 * byte, otherwise 0xFF (128) appears and
+				 * the delta is encoded by the next 4 bytes.
+				 * Code deltas are always positive. This
+				 * sequence is just after the last entry in
+				 * the AuxData array. */
+    unsigned char *codeLengthStart;
+				/* Points to the first of a sequence of
+				 * bytes that encode the length of each
+				 * command's code. The encoding is the same
+				 * as for code deltas. Code lengths are
+				 * always positive. This sequence is just
+				 * after the last entry in the code delta
+				 * sequence. */
+    unsigned char *srcDeltaStart;
+				/* Points to the first of a sequence of
+				 * bytes that encode the change in the
+				 * starting offset of each command's source.
+				 * The encoding is the same as for code
+				 * deltas. Source deltas can be negative.
+				 * This sequence is just after the last byte
+				 * in the code length sequence. */
+    unsigned char *srcLengthStart;
+				/* Points to the first of a sequence of
+				 * bytes that encode the length of each
+				 * command's source. The encoding is the
+				 * same as for code deltas. Source lengths
+				 * are always positive. This sequence is
+				 * just after the last byte in the source
+				 * delta sequence. */
+} ByteCode;
+
+/*
+ * Opcodes for the Tcl bytecode instructions. These opcodes must correspond
+ * to the entries in the table of instruction descriptions in tclCompile.c.
+ * Also, the order and number of the expression opcodes (e.g., INST_LOR)
+ * must match the entries in the array operatorStrings in tclExecute.c.
+ */
+
+/* Opcodes 0 to 9 */
+#define INST_DONE			0
+#define INST_PUSH1			(INST_DONE + 1)
+#define INST_PUSH4			(INST_DONE + 2)
+#define INST_POP			(INST_DONE + 3)
+#define INST_DUP			(INST_DONE + 4)
+#define INST_CONCAT1			(INST_DONE + 5)
+#define INST_INVOKE_STK1		(INST_DONE + 6)
+#define INST_INVOKE_STK4		(INST_DONE + 7)
+#define INST_EVAL_STK			(INST_DONE + 8)
+#define INST_EXPR_STK			(INST_DONE + 9)
+
+/* Opcodes 10 to 23 */
+#define INST_LOAD_SCALAR1		(INST_EXPR_STK + 1)
+#define INST_LOAD_SCALAR4		(INST_LOAD_SCALAR1 + 1)
+#define INST_LOAD_SCALAR_STK		(INST_LOAD_SCALAR1 + 2)
+#define INST_LOAD_ARRAY1		(INST_LOAD_SCALAR1 + 3)
+#define INST_LOAD_ARRAY4		(INST_LOAD_SCALAR1 + 4)
+#define INST_LOAD_ARRAY_STK		(INST_LOAD_SCALAR1 + 5)
+#define INST_LOAD_STK			(INST_LOAD_SCALAR1 + 6)
+#define INST_STORE_SCALAR1		(INST_LOAD_SCALAR1 + 7)
+#define INST_STORE_SCALAR4		(INST_LOAD_SCALAR1 + 8)
+#define INST_STORE_SCALAR_STK		(INST_LOAD_SCALAR1 + 9)
+#define INST_STORE_ARRAY1		(INST_LOAD_SCALAR1 + 10)
+#define INST_STORE_ARRAY4		(INST_LOAD_SCALAR1 + 11)
+#define INST_STORE_ARRAY_STK		(INST_LOAD_SCALAR1 + 12)
+#define INST_STORE_STK			(INST_LOAD_SCALAR1 + 13)
+
+/* Opcodes 24 to 33 */
+#define INST_INCR_SCALAR1		(INST_STORE_STK + 1)
+#define INST_INCR_SCALAR_STK		(INST_INCR_SCALAR1 + 1)
+#define INST_INCR_ARRAY1		(INST_INCR_SCALAR1 + 2)
+#define INST_INCR_ARRAY_STK		(INST_INCR_SCALAR1 + 3)
+#define INST_INCR_STK			(INST_INCR_SCALAR1 + 4)
+#define INST_INCR_SCALAR1_IMM		(INST_INCR_SCALAR1 + 5)
+#define INST_INCR_SCALAR_STK_IMM	(INST_INCR_SCALAR1 + 6)
+#define INST_INCR_ARRAY1_IMM		(INST_INCR_SCALAR1 + 7)
+#define INST_INCR_ARRAY_STK_IMM		(INST_INCR_SCALAR1 + 8)
+#define INST_INCR_STK_IMM		(INST_INCR_SCALAR1 + 9)
+
+/* Opcodes 34 to 39 */
+#define INST_JUMP1			(INST_INCR_STK_IMM + 1)
+#define INST_JUMP4			(INST_JUMP1 + 1)
+#define INST_JUMP_TRUE1			(INST_JUMP1 + 2)
+#define INST_JUMP_TRUE4			(INST_JUMP1 + 3)
+#define INST_JUMP_FALSE1		(INST_JUMP1 + 4)
+#define INST_JUMP_FALSE4	        (INST_JUMP1 + 5)
+
+/* Opcodes 40 to 64 */
+#define INST_LOR			(INST_JUMP_FALSE4 + 1)
+#define INST_LAND			(INST_LOR + 1)
+#define INST_BITOR			(INST_LOR + 2)
+#define INST_BITXOR			(INST_LOR + 3)
+#define INST_BITAND			(INST_LOR + 4)
+#define INST_EQ				(INST_LOR + 5)
+#define INST_NEQ			(INST_LOR + 6)
+#define INST_LT				(INST_LOR + 7)
+#define INST_GT				(INST_LOR + 8)
+#define INST_LE				(INST_LOR + 9)
+#define INST_GE				(INST_LOR + 10)
+#define INST_LSHIFT			(INST_LOR + 11)
+#define INST_RSHIFT			(INST_LOR + 12)
+#define INST_ADD			(INST_LOR + 13)
+#define INST_SUB			(INST_LOR + 14)
+#define INST_MULT			(INST_LOR + 15)
+#define INST_DIV			(INST_LOR + 16)
+#define INST_MOD			(INST_LOR + 17)
+#define INST_UPLUS			(INST_LOR + 18)
+#define INST_UMINUS			(INST_LOR + 19)
+#define INST_BITNOT			(INST_LOR + 20)
+#define INST_LNOT			(INST_LOR + 21)
+#define INST_CALL_BUILTIN_FUNC1		(INST_LOR + 22)
+#define INST_CALL_FUNC1			(INST_LOR + 23)
+#define INST_TRY_CVT_TO_NUMERIC		(INST_LOR + 24)
+
+/* Opcodes 65 to 66 */
+#define INST_BREAK			(INST_TRY_CVT_TO_NUMERIC + 1)
+#define INST_CONTINUE			(INST_BREAK + 1)
+
+/* Opcodes 67 to 68 */
+#define INST_FOREACH_START4		(INST_CONTINUE + 1)
+#define INST_FOREACH_STEP4		(INST_FOREACH_START4 + 1)
+
+/* Opcodes 69 to 72 */
+#define INST_BEGIN_CATCH4		(INST_FOREACH_STEP4 + 1)
+#define INST_END_CATCH			(INST_BEGIN_CATCH4 + 1)
+#define INST_PUSH_RESULT		(INST_BEGIN_CATCH4 + 2)
+#define INST_PUSH_RETURN_CODE		(INST_BEGIN_CATCH4 + 3)
+
+/* The last opcode */
+#define LAST_INST_OPCODE        	INST_PUSH_RETURN_CODE
+
+/*
+ * Table describing the Tcl bytecode instructions: their name (for
+ * displaying code), total number of code bytes required (including
+ * operand bytes), and a description of the type of each operand.
+ * These operand types include signed and unsigned integers of length
+ * one and four bytes. The unsigned integers are used for indexes or
+ * for, e.g., the count of objects to push in a "push" instruction.
+ */
+
+#define MAX_INSTRUCTION_OPERANDS 2
+
+typedef enum InstOperandType {
+    OPERAND_NONE,
+    OPERAND_INT1,		/* One byte signed integer. */
+    OPERAND_INT4,		/* Four byte signed integer. */
+    OPERAND_UINT1,		/* One byte unsigned integer. */
+    OPERAND_UINT4		/* Four byte unsigned integer. */
+} InstOperandType;
+
+typedef struct InstructionDesc {
+    char *name;			/* Name of instruction. */
+    int numBytes;		/* Total number of bytes for instruction. */
+    int numOperands;		/* Number of operands. */
+    InstOperandType opTypes[MAX_INSTRUCTION_OPERANDS];
+				/* The type of each operand. */
+} InstructionDesc;
+
+extern InstructionDesc instructionTable[];
+
+/*
+ * Definitions of the values of the INST_CALL_BUILTIN_FUNC instruction's
+ * operand byte. Each value denotes a builtin Tcl math function. These
+ * values must correspond to the entries in the builtinFuncTable array
+ * below and to the values stored in the tclInt.h MathFunc structure's
+ * builtinFuncIndex field.
+ */
+
+#define BUILTIN_FUNC_ACOS		0
+#define BUILTIN_FUNC_ASIN		1
+#define BUILTIN_FUNC_ATAN		2
+#define BUILTIN_FUNC_ATAN2		3
+#define BUILTIN_FUNC_CEIL		4
+#define BUILTIN_FUNC_COS		5
+#define BUILTIN_FUNC_COSH		6
+#define BUILTIN_FUNC_EXP		7
+#define BUILTIN_FUNC_FLOOR		8
+#define BUILTIN_FUNC_FMOD		9
+#define BUILTIN_FUNC_HYPOT		10
+#define BUILTIN_FUNC_LOG		11
+#define BUILTIN_FUNC_LOG10		12
+#define BUILTIN_FUNC_POW		13
+#define BUILTIN_FUNC_SIN		14
+#define BUILTIN_FUNC_SINH		15
+#define BUILTIN_FUNC_SQRT		16
+#define BUILTIN_FUNC_TAN		17
+#define BUILTIN_FUNC_TANH		18
+#define BUILTIN_FUNC_ABS		19
+#define BUILTIN_FUNC_DOUBLE		20
+#define BUILTIN_FUNC_INT		21
+#define BUILTIN_FUNC_RAND		22
+#define BUILTIN_FUNC_ROUND		23
+#define BUILTIN_FUNC_SRAND		24
+
+#define LAST_BUILTIN_FUNC        	BUILTIN_FUNC_SRAND
+
+/*
+ * Table describing the built-in math functions. Entries in this table are
+ * indexed by the values of the INST_CALL_BUILTIN_FUNC instruction's
+ * operand byte.
+ */
+
+typedef int (CallBuiltinFuncProc) _ANSI_ARGS_((Tcl_Interp *interp,
+        ExecEnv *eePtr, ClientData clientData));
+
+typedef struct {
+    char *name;			/* Name of function. */
+    int numArgs;		/* Number of arguments for function. */
+    Tcl_ValueType argTypes[MAX_MATH_ARGS];
+				/* Acceptable types for each argument. */
+    CallBuiltinFuncProc *proc;	/* Procedure implementing this function. */
+    ClientData clientData;	/* Additional argument to pass to the
+				 * function when invoking it. */
+} BuiltinFunc;
+
+extern BuiltinFunc builtinFuncTable[];
+
+/*
+ * The structure used to hold information about the start and end of each
+ * argument word in a command. 
+ */
+
+#define ARGINFO_INIT_ENTRIES 5
+
+typedef struct ArgInfo {
+    int numArgs;		/* Number of argument words in command. */
+    char **startArray;		/* Array of pointers to the first character
+				 * of each argument word. */
+    char **endArray;		/* Array of pointers to the last character
+				 * of each argument word. */
+    int allocArgs;		/* Number of array entries currently
+				 * allocated. */
+    int mallocedArrays;		/* 1 if the arrays were expanded and
+				 * wordStartArray/wordEndArray point into
+				 * the heap, else 0. */
+    char *staticStartSpace[ARGINFO_INIT_ENTRIES];
+                                /* Initial storage for word start array. */
+    char *staticEndSpace[ARGINFO_INIT_ENTRIES];
+                                /* Initial storage for word end array. */
+} ArgInfo;
+
+/*
+ * Compilation of some Tcl constructs such as if commands and the logical or
+ * (||) and logical and (&&) operators in expressions requires the
+ * generation of forward jumps. Since the PC target of these jumps isn't
+ * known when the jumps are emitted, we record the offset of each jump in an
+ * array of JumpFixup structures. There is one array for each sequence of
+ * jumps to one target PC. When we learn the target PC, we update the jumps
+ * with the correct distance. Also, if the distance is too great (> 127
+ * bytes), we replace the single-byte jump with a four byte jump
+ * instruction, move the instructions after the jump down, and update the
+ * code offsets for any commands between the jump and the target.
+ */
+
+typedef enum {
+    TCL_UNCONDITIONAL_JUMP,
+    TCL_TRUE_JUMP,
+    TCL_FALSE_JUMP
+} TclJumpType;
+
+typedef struct JumpFixup {
+    TclJumpType jumpType;	/* Indicates the kind of jump. */
+    int codeOffset;		/* Offset of the first byte of the one-byte
+				 * forward jump's code. */
+    int cmdIndex;		/* Index of the first command after the one
+				 * for which the jump was emitted. Used to
+				 * update the code offsets for subsequent
+				 * commands if the two-byte jump at jumpPc
+				 * must be replaced with a five-byte one. */
+    int excRangeIndex;		/* Index of the first range entry in the
+				 * ExceptionRange array after the current
+				 * one. This field is used to adjust the
+				 * code offsets in subsequent ExceptionRange
+				 * records when a jump is grown from 2 bytes
+				 * to 5 bytes. */
+} JumpFixup;
+
+#define JUMPFIXUP_INIT_ENTRIES    10
+
+typedef struct JumpFixupArray {
+    JumpFixup *fixup;		/* Points to start of jump fixup array. */
+    int next;			/* Index of next free array entry. */
+    int end;			/* Index of last usable entry in array. */
+    int mallocedArray;		/* 1 if array was expanded and fixups points
+				 * into the heap, else 0. */
+    JumpFixup staticFixupSpace[JUMPFIXUP_INIT_ENTRIES];
+				/* Initial storage for jump fixup array. */
+} JumpFixupArray;
+
+/*
+ * The structure describing one variable list of a foreach command. Note
+ * that only foreach commands inside procedure bodies are compiled inline so
+ * a ForeachVarList structure always describes local variables. Furthermore,
+ * only scalar variables are supported for inline-compiled foreach loops.
+ */
+
+typedef struct ForeachVarList {
+    int numVars;		/* The number of variables in the list. */
+    int varIndexes[1];		/* An array of the indexes ("slot numbers")
+				 * for each variable in the procedure's
+				 * array of local variables. Only scalar
+				 * variables are supported. The actual
+				 * size of this field will be large enough
+				 * to numVars indexes. THIS MUST BE THE
+				 * LAST FIELD IN THE STRUCTURE! */
+} ForeachVarList;
+
+/*
+ * Structure used to hold information about a foreach command that is needed
+ * during program execution. These structures are stored in CompileEnv and
+ * ByteCode structures as auxiliary data.
+ */
+
+typedef struct ForeachInfo {
+    int numLists;		/* The number of both the variable and value
+				 * lists of the foreach command. */
+    int firstListTmp;		/* The slot number of the first temporary
+				 * variable holding the lists themselves. */
+    int loopIterNumTmp;		/* The slot number of the temp var holding
+				 * the count of times the loop body has been
+				 * executed. This is used to determine which
+				 * list element to assign each loop var. */
+    ForeachVarList *varLists[1];/* An array of pointers to ForeachVarList
+				 * structures describing each var list. The
+				 * actual size of this field will be large
+				 * enough to numVars indexes. THIS MUST BE
+				 * THE LAST FIELD IN THE STRUCTURE! */
+} ForeachInfo;
+
+/*
+ * Structure containing a cached pointer to a command that is the result
+ * of resolving the command's name in some namespace. It is the internal
+ * representation for a cmdName object. It contains the pointer along
+ * with some information that is used to check the pointer's validity.
+ */
+
+typedef struct ResolvedCmdName {
+    Command *cmdPtr;		/* A cached Command pointer. */
+    Namespace *refNsPtr;	/* Points to the namespace containing the
+				 * reference (not the namespace that
+				 * contains the referenced command). */
+    long refNsId;		/* refNsPtr's unique namespace id. Used to
+				 * verify that refNsPtr is still valid
+				 * (e.g., it's possible that the cmd's
+				 * containing namespace was deleted and a
+				 * new one created at the same address). */
+    int refNsCmdEpoch;		/* Value of the referencing namespace's
+				 * cmdRefEpoch when the pointer was cached.
+				 * Before using the cached pointer, we check
+				 * if the namespace's epoch was incremented;
+				 * if so, this cached pointer is invalid. */
+    int cmdEpoch;		/* Value of the command's cmdEpoch when this
+				 * pointer was cached. Before using the
+				 * cached pointer, we check if the cmd's
+				 * epoch was incremented; if so, the cmd was
+				 * renamed, deleted, hidden, or exposed, and
+				 * so the pointer is invalid. */
+    int refCount;		/* Reference count: 1 for each cmdName
+				 * object that has a pointer to this
+				 * ResolvedCmdName structure as its internal
+				 * rep. This structure can be freed when
+				 * refCount becomes zero. */
+} ResolvedCmdName;
+
+/*
+ *----------------------------------------------------------------
+ * Procedures shared among Tcl bytecode compilation and execution
+ * modules but not used outside:
+ *----------------------------------------------------------------
+ */
+
+EXTERN void		TclCleanupByteCode _ANSI_ARGS_((ByteCode *codePtr));
+EXTERN int		TclCompileExpr _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, char *lastChar, int flags,
+			    CompileEnv *envPtr));
+EXTERN int		TclCompileQuotes _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, char *lastChar, int termChar,
+			    int flags, CompileEnv *envPtr));
+EXTERN int		TclCompileString _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, char *lastChar, int flags,
+			    CompileEnv *envPtr));
+EXTERN int		TclCompileDollarVar _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, char *lastChar, int flags,
+			    CompileEnv *envPtr));
+EXTERN int		TclCreateAuxData _ANSI_ARGS_((ClientData clientData,
+                AuxDataType *typePtr, CompileEnv *envPtr));
+EXTERN ExecEnv *	TclCreateExecEnv _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN void		TclDeleteExecEnv _ANSI_ARGS_((ExecEnv *eePtr));
+EXTERN void		TclEmitForwardJump _ANSI_ARGS_((CompileEnv *envPtr,
+			    TclJumpType jumpType, JumpFixup *jumpFixupPtr));
+EXTERN AuxDataType *TclGetAuxDataType _ANSI_ARGS_((char *typeName));
+EXTERN ExceptionRange *	TclGetExceptionRangeForPc _ANSI_ARGS_((
+			    unsigned char *pc, int catchOnly,
+			    ByteCode* codePtr));
+EXTERN InstructionDesc * TclGetInstructionTable _ANSI_ARGS_(());
+EXTERN int		TclExecuteByteCode _ANSI_ARGS_((Tcl_Interp *interp,
+			    ByteCode *codePtr));
+EXTERN void		TclExpandCodeArray _ANSI_ARGS_((
+                            CompileEnv *envPtr));
+EXTERN void		TclExpandJumpFixupArray _ANSI_ARGS_((
+                            JumpFixupArray *fixupArrayPtr));
+EXTERN void		TclFinalizeAuxDataTypeTable _ANSI_ARGS_((void));
+EXTERN int		TclFixupForwardJump _ANSI_ARGS_((
+			    CompileEnv *envPtr, JumpFixup *jumpFixupPtr,
+			    int jumpDist, int distThreshold));
+EXTERN void		TclFreeCompileEnv _ANSI_ARGS_((CompileEnv *envPtr));
+EXTERN void		TclFreeJumpFixupArray _ANSI_ARGS_((
+  			    JumpFixupArray *fixupArrayPtr));
+EXTERN void		TclInitAuxDataTypeTable _ANSI_ARGS_((void));
+EXTERN void		TclInitByteCodeObj _ANSI_ARGS_((Tcl_Obj *objPtr,
+			    CompileEnv *envPtr));
+EXTERN void		TclInitCompileEnv _ANSI_ARGS_((Tcl_Interp *interp,
+			    CompileEnv *envPtr, char *string));
+EXTERN void		TclInitJumpFixupArray _ANSI_ARGS_((
+			    JumpFixupArray *fixupArrayPtr));
+#ifdef TCL_COMPILE_STATS
+EXTERN int		TclLog2 _ANSI_ARGS_((int value));
+#endif /*TCL_COMPILE_STATS*/
+EXTERN int		TclObjIndexForString _ANSI_ARGS_((char *start,
+			    int length, int allocStrRep, int inHeap,
+			    CompileEnv *envPtr));
+EXTERN int		TclPrintInstruction _ANSI_ARGS_((ByteCode* codePtr,
+			    unsigned char *pc));
+EXTERN void		TclPrintSource _ANSI_ARGS_((FILE *outFile,
+			    char *string, int maxChars));
+EXTERN void		TclRegisterAuxDataType _ANSI_ARGS_((AuxDataType *typePtr));
+
+/*
+ *----------------------------------------------------------------
+ * Macros used by Tcl bytecode compilation and execution modules
+ * inside the Tcl core but not used outside.
+ *----------------------------------------------------------------
+ */
+
+/*
+ * Macros to ensure there is enough room in a CompileEnv's code array.
+ * The ANSI C "prototypes" for these macros are:
+ *
+ * EXTERN void	TclEnsureCodeSpace1 _ANSI_ARGS_((CompileEnv *envPtr));
+ * EXTERN void	TclEnsureCodeSpace _ANSI_ARGS_((int nBytes,
+ *		    CompileEnv *envPtr));
+ */
+
+#define TclEnsureCodeSpace1(envPtr) \
+    if ((envPtr)->codeNext == (envPtr)->codeEnd) \
+        TclExpandCodeArray(envPtr)
+
+#define TclEnsureCodeSpace(nBytes, envPtr) \
+    if (((envPtr)->codeNext + nBytes) > (envPtr)->codeEnd) \
+        TclExpandCodeArray(envPtr)
+
+/*
+ * Macro to emit an opcode byte into a CompileEnv's code array.
+ * The ANSI C "prototype" for this macro is:
+ *
+ * EXTERN void	TclEmitOpcode _ANSI_ARGS_((unsigned char op,
+ *		    CompileEnv *envPtr));
+ */
+
+#define TclEmitOpcode(op, envPtr) \
+    TclEnsureCodeSpace1(envPtr); \
+    *(envPtr)->codeNext++ = (unsigned char) (op)
+
+/*
+ * Macros to emit a (signed or unsigned) int operand. The two variants
+ * depend on the number of bytes needed for the int. Four byte integers
+ * are stored in "big-endian" order with the high order byte stored at
+ * the lowest address. The ANSI C "prototypes" for these macros are:
+ *
+ * EXTERN void	TclEmitInt1 _ANSI_ARGS_((int i, CompileEnv *envPtr));
+ * EXTERN void	TclEmitInt4 _ANSI_ARGS_((int i, CompileEnv *envPtr));
+ */
+
+#define TclEmitInt1(i, envPtr) \
+    TclEnsureCodeSpace(1, (envPtr)); \
+    *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i))
+
+#define TclEmitInt4(i, envPtr) \
+    TclEnsureCodeSpace(4, (envPtr)); \
+    *(envPtr)->codeNext++ = \
+        (unsigned char) ((unsigned int) (i) >> 24); \
+    *(envPtr)->codeNext++ = \
+        (unsigned char) ((unsigned int) (i) >> 16); \
+    *(envPtr)->codeNext++ = \
+        (unsigned char) ((unsigned int) (i) >>  8); \
+    *(envPtr)->codeNext++ = \
+        (unsigned char) ((unsigned int) (i)      )
+
+/*
+ * Macros to emit an instruction with signed or unsigned int operands.
+ * The ANSI C "prototypes" for these macros are:
+ *
+ * EXTERN void	TclEmitInstInt1 _ANSI_ARGS_((unsigned char op, int i, 
+ *		    CompileEnv *envPtr));
+ * EXTERN void	TclEmitInstInt4 _ANSI_ARGS_((unsigned char op, int i, 
+ *		    CompileEnv *envPtr));
+ * EXTERN void	TclEmitInstUInt1 _ANSI_ARGS_((unsigned char op,
+ *		    unsigned int i, CompileEnv *envPtr));
+ * EXTERN void	TclEmitInstUInt4 _ANSI_ARGS_((unsigned char op,
+ *		    unsigned int i, CompileEnv *envPtr));
+ */
+
+#define TclEmitInstInt1(op, i, envPtr) \
+    TclEnsureCodeSpace(2, (envPtr)); \
+    *(envPtr)->codeNext++ = (unsigned char) (op); \
+    *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i))
+
+#define TclEmitInstInt4(op, i, envPtr) \
+    TclEnsureCodeSpace(5, (envPtr)); \
+    *(envPtr)->codeNext++ = (unsigned char) (op); \
+    *(envPtr)->codeNext++ = \
+        (unsigned char) ((unsigned int) (i) >> 24); \
+    *(envPtr)->codeNext++ = \
+        (unsigned char) ((unsigned int) (i) >> 16); \
+    *(envPtr)->codeNext++ = \
+        (unsigned char) ((unsigned int) (i) >>  8); \
+    *(envPtr)->codeNext++ = \
+        (unsigned char) ((unsigned int) (i)      )
+    
+#define TclEmitInstUInt1(op, i, envPtr) \
+    TclEmitInstInt1((op), (i), (envPtr))
+
+#define TclEmitInstUInt4(op, i, envPtr) \
+    TclEmitInstInt4((op), (i), (envPtr))
+    
+/*
+ * Macro to push a Tcl object onto the Tcl evaluation stack. It emits the
+ * object's one or four byte array index into the CompileEnv's code
+ * array. These support, respectively, a maximum of 256 (2**8) and 2**32
+ * objects in a CompileEnv. The ANSI C "prototype" for this macro is:
+ *
+ * EXTERN void	TclEmitPush _ANSI_ARGS_((int objIndex, CompileEnv *envPtr));
+ */
+
+#define TclEmitPush(objIndex, envPtr) \
+    if ((objIndex) <= 255) { \
+	TclEmitInstUInt1(INST_PUSH1, (objIndex), (envPtr)); \
+    } else { \
+	TclEmitInstUInt4(INST_PUSH4, (objIndex), (envPtr)); \
+    }
+
+/*
+ * Macros to update a (signed or unsigned) integer starting at a pointer.
+ * The two variants depend on the number of bytes. The ANSI C "prototypes"
+ * for these macros are:
+ *
+ * EXTERN void	TclStoreInt1AtPtr _ANSI_ARGS_((int i, unsigned char *p));
+ * EXTERN void	TclStoreInt4AtPtr _ANSI_ARGS_((int i, unsigned char *p));
+ */
+    
+#define TclStoreInt1AtPtr(i, p) \
+    *(p)   = (unsigned char) ((unsigned int) (i))
+    
+#define TclStoreInt4AtPtr(i, p) \
+    *(p)   = (unsigned char) ((unsigned int) (i) >> 24); \
+    *(p+1) = (unsigned char) ((unsigned int) (i) >> 16); \
+    *(p+2) = (unsigned char) ((unsigned int) (i) >>  8); \
+    *(p+3) = (unsigned char) ((unsigned int) (i)      )
+
+/*
+ * Macros to update instructions at a particular pc with a new op code
+ * and a (signed or unsigned) int operand. The ANSI C "prototypes" for
+ * these macros are:
+ *
+ * EXTERN void	TclUpdateInstInt1AtPc _ANSI_ARGS_((unsigned char op, int i,
+ *		    unsigned char *pc));
+ * EXTERN void	TclUpdateInstInt4AtPc _ANSI_ARGS_((unsigned char op, int i,
+ *		    unsigned char *pc));
+ */
+
+#define TclUpdateInstInt1AtPc(op, i, pc) \
+    *(pc) = (unsigned char) (op); \
+    TclStoreInt1AtPtr((i), ((pc)+1))
+
+#define TclUpdateInstInt4AtPc(op, i, pc) \
+    *(pc) = (unsigned char) (op); \
+    TclStoreInt4AtPtr((i), ((pc)+1))
+    
+/*
+ * Macros to get a signed integer (GET_INT{1,2}) or an unsigned int
+ * (GET_UINT{1,2}) from a pointer. There are two variants for each
+ * return type that depend on the number of bytes fetched.
+ * The ANSI C "prototypes" for these macros are:
+ *
+ * EXTERN int	        TclGetInt1AtPtr  _ANSI_ARGS_((unsigned char *p));
+ * EXTERN int	        TclGetInt4AtPtr  _ANSI_ARGS_((unsigned char *p));
+ * EXTERN unsigned int	TclGetUInt1AtPtr _ANSI_ARGS_((unsigned char *p));
+ * EXTERN unsigned int	TclGetUInt4AtPtr _ANSI_ARGS_((unsigned char *p));
+ */
+
+/*
+ * The TclGetInt1AtPtr macro is tricky because we want to do sign
+ * extension on the 1-byte value. Unfortunately the "char" type isn't
+ * signed on all platforms so sign-extension doesn't always happen
+ * automatically. Sometimes we can explicitly declare the pointer to be
+ * signed, but other times we have to explicitly sign-extend the value
+ * in software.
+ */
+
+#ifndef __CHAR_UNSIGNED__
+#   define TclGetInt1AtPtr(p) ((int) *((char *) p))
+#else
+#   ifdef HAVE_SIGNED_CHAR
+#	define TclGetInt1AtPtr(p) ((int) *((signed char *) p))
+#    else
+#	define TclGetInt1AtPtr(p) (((int) *((char *) p)) \
+		| ((*(p) & 0200) ? (-256) : 0))
+#    endif
+#endif
+
+#define TclGetInt4AtPtr(p) (((int) TclGetInt1AtPtr(p) << 24) | \
+		                  	    (*((p)+1) << 16) | \
+				  	    (*((p)+2) <<  8) | \
+				  	    (*((p)+3)))
+
+#define TclGetUInt1AtPtr(p) ((unsigned int) *(p))
+#define TclGetUInt4AtPtr(p) ((unsigned int) (*(p)     << 24) | \
+		                            (*((p)+1) << 16) | \
+				            (*((p)+2) <<  8) | \
+				            (*((p)+3)))
+
+/*
+ * Macros used to compute the minimum and maximum of two integers.
+ * The ANSI C "prototypes" for these macros are:
+ *
+ * EXTERN int  TclMin _ANSI_ARGS_((int i, int j));
+ * EXTERN int  TclMax _ANSI_ARGS_((int i, int j));
+ */
+
+#define TclMin(i, j)   ((((int) i) < ((int) j))? (i) : (j))
+#define TclMax(i, j)   ((((int) i) > ((int) j))? (i) : (j))
+
+/*
+ * Macro used to compute the offset of the current instruction in the
+ * bytecode instruction stream. The ANSI C "prototypes" for this macro is:
+ *
+ * EXTERN int  TclCurrCodeOffset _ANSI_ARGS_((void));
+ */
+
+#define TclCurrCodeOffset()  ((envPtr)->codeNext - (envPtr)->codeStart)
+
+/*
+ * Upper bound for legal jump distances. Checked during compilation if
+ * debugging.
+ */
+
+#define MAX_JUMP_DIST   5000
+
+# undef TCL_STORAGE_CLASS
+# define TCL_STORAGE_CLASS DLLIMPORT
+
+#endif /* _TCLCOMPILATION */
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclExecute.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclExecute.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclExecute.c	(revision 5)
@@ -0,0 +1,4797 @@
+/* 
+ * tclExecute.c --
+ *
+ *	This file contains procedures that execute byte-compiled Tcl
+ *	commands.
+ *
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclExecute.c,v 1.1 2008-06-04 13:58:06 demin Exp $
+ */
+
+#include "tclInt.h"
+#include "tclCompile.h"
+
+#ifdef NO_FLOAT_H
+#   include "../compat/float.h"
+#else
+#   include <float.h>
+#endif
+#ifndef TCL_NO_MATH
+#include "tclMath.h"
+#endif
+
+/*
+ * The stuff below is a bit of a hack so that this file can be used
+ * in environments that include no UNIX, i.e. no errno.  Just define
+ * errno here.
+ */
+
+#ifndef TCL_GENERIC_ONLY
+#include "tclPort.h"
+#else
+#define NO_ERRNO_H
+#endif
+
+#ifdef NO_ERRNO_H
+int errno;
+#define EDOM 33
+#define ERANGE 34
+#endif
+
+/*
+ * Boolean flag indicating whether the Tcl bytecode interpreter has been
+ * initialized.
+ */
+
+static int execInitialized = 0;
+
+/*
+ * Variable that controls whether execution tracing is enabled and, if so,
+ * what level of tracing is desired:
+ *    0: no execution tracing
+ *    1: trace invocations of Tcl procs only
+ *    2: trace invocations of all (not compiled away) commands
+ *    3: display each instruction executed
+ * This variable is linked to the Tcl variable "tcl_traceExec".
+ */
+
+int tclTraceExec = 0;
+
+/*
+ * The following global variable is use to signal matherr that Tcl
+ * is responsible for the arithmetic, so errors can be handled in a
+ * fashion appropriate for Tcl.  Zero means no Tcl math is in
+ * progress;  non-zero means Tcl is doing math.
+ */
+
+int tcl_MathInProgress = 0;
+
+/*
+ * The variable below serves no useful purpose except to generate
+ * a reference to matherr, so that the Tcl version of matherr is
+ * linked in rather than the system version. Without this reference
+ * the need for matherr won't be discovered during linking until after
+ * libtcl.a has been processed, so Tcl's version won't be used.
+ */
+
+#ifdef NEED_MATHERR
+extern int matherr();
+int (*tclMatherrPtr)() = matherr;
+#endif
+
+/*
+ * Array of instruction names.
+ */
+
+static char *opName[256];
+
+/*
+ * Mapping from expression instruction opcodes to strings; used for error
+ * messages. Note that these entries must match the order and number of the
+ * expression opcodes (e.g., INST_LOR) in tclCompile.h.
+ */
+
+static char *operatorStrings[] = {
+    "||", "&&", "|", "^", "&", "==", "!=", "<", ">", "<=", ">=", "<<", ">>",
+    "+", "-", "*", "/", "%", "+", "-", "~", "!",
+    "BUILTIN FUNCTION", "FUNCTION"
+};
+    
+/*
+ * Mapping from Tcl result codes to strings; used for error and debugging
+ * messages. 
+ */
+
+#ifdef TCL_COMPILE_DEBUG
+static char *resultStrings[] = {
+    "TCL_OK", "TCL_ERROR", "TCL_RETURN", "TCL_BREAK", "TCL_CONTINUE"
+};
+#endif /* TCL_COMPILE_DEBUG */
+
+/*
+ * The following are statistics-related variables that record information
+ * about the bytecode compiler and interpreter's operation. This includes
+ * an array that records for each instruction how often it is executed.
+ */
+
+#ifdef TCL_COMPILE_STATS
+static long numExecutions = 0;
+static int instructionCount[256];
+#endif /* TCL_COMPILE_STATS */
+
+/*
+ * Macros for testing floating-point values for certain special cases. Test
+ * for not-a-number by comparing a value against itself; test for infinity
+ * by comparing against the largest floating-point value.
+ */
+
+#define IS_NAN(v) ((v) != (v))
+#ifdef DBL_MAX
+#   define IS_INF(v) (((v) > DBL_MAX) || ((v) < -DBL_MAX))
+#else
+#   define IS_INF(v) 0
+#endif
+
+/*
+ * Macro to adjust the program counter and restart the instruction execution
+ * loop after each instruction is executed.
+ */
+
+#define ADJUST_PC(instBytes) \
+    pc += instBytes;  continue
+
+/*
+ * Macros used to cache often-referenced Tcl evaluation stack information
+ * in local variables. Note that a DECACHE_STACK_INFO()-CACHE_STACK_INFO()
+ * pair must surround any call inside TclExecuteByteCode (and a few other
+ * procedures that use this scheme) that could result in a recursive call
+ * to TclExecuteByteCode.
+ */
+
+#define CACHE_STACK_INFO() \
+    stackPtr = eePtr->stackPtr; \
+    stackTop = eePtr->stackTop
+
+#define DECACHE_STACK_INFO() \
+    eePtr->stackTop = stackTop
+
+/*
+ * Macros used to access items on the Tcl evaluation stack. PUSH_OBJECT
+ * increments the object's ref count since it makes the stack have another
+ * reference pointing to the object. However, POP_OBJECT does not decrement
+ * the ref count. This is because the stack may hold the only reference to
+ * the object, so the object would be destroyed if its ref count were
+ * decremented before the caller had a chance to, e.g., store it in a
+ * variable. It is the caller's responsibility to decrement the ref count
+ * when it is finished with an object.
+ */
+
+#define STK_ITEM(offset)    (stackPtr[stackTop + (offset)])
+#define STK_OBJECT(offset)  (STK_ITEM(offset).o)
+#define STK_INT(offset)     (STK_ITEM(offset).i)
+#define STK_POINTER(offset) (STK_ITEM(offset).p)
+
+/*
+ * WARNING! It is essential that objPtr only appear once in the PUSH_OBJECT
+ * macro. The actual parameter might be an expression with side effects,
+ * and this ensures that it will be executed only once. 
+ */
+    
+#define PUSH_OBJECT(objPtr) \
+    Tcl_IncrRefCount(stackPtr[++stackTop].o = (objPtr))
+    
+#define POP_OBJECT() \
+    (stackPtr[stackTop--].o)
+
+/*
+ * Macros used to trace instruction execution. The macros TRACE,
+ * TRACE_WITH_OBJ, and O2S are only used inside TclExecuteByteCode.
+ * O2S is only used in TRACE* calls to get a string from an object.
+ * 
+ * NOTE THAT CLIENTS OF O2S ARE LIKELY TO FAIL IF THE OBJECT'S
+ * STRING REP CONTAINS NULLS. 
+ */
+
+#ifdef TCL_COMPILE_DEBUG
+	
+#define O2S(objPtr) \
+    Tcl_GetStringFromObj((objPtr), &length)
+	
+#ifdef TCL_COMPILE_STATS
+#define TRACE(a) \
+    if (traceInstructions) { \
+        fprintf(stdout, "%d: %d,%ld (%u) ", iPtr->numLevels, \
+	       stackTop, (tclObjsAlloced - tclObjsFreed), \
+	       (unsigned int)(pc - codePtr->codeStart)); \
+	printf a; \
+        fflush(stdout); \
+    }
+#define TRACE_WITH_OBJ(a, objPtr) \
+    if (traceInstructions) { \
+        fprintf(stdout, "%d: %d,%ld (%u) ", iPtr->numLevels, \
+	       stackTop, (tclObjsAlloced - tclObjsFreed), \
+	       (unsigned int)(pc - codePtr->codeStart)); \
+	printf a; \
+	bytes = Tcl_GetStringFromObj((objPtr), &length); \
+        TclPrintSource(stdout, bytes, TclMin(length, 30)); \
+        fprintf(stdout, "\n"); \
+        fflush(stdout); \
+    }
+#else  /* not TCL_COMPILE_STATS */
+#define TRACE(a) \
+    if (traceInstructions) { \
+        fprintf(stdout, "%d: %d (%u) ", iPtr->numLevels, stackTop, \
+	       (unsigned int)(pc - codePtr->codeStart)); \
+	printf a; \
+        fflush(stdout); \
+    }
+#define TRACE_WITH_OBJ(a, objPtr) \
+    if (traceInstructions) { \
+        fprintf(stdout, "%d: %d (%u) ", iPtr->numLevels, stackTop, \
+	       (unsigned int)(pc - codePtr->codeStart)); \
+	printf a; \
+	bytes = Tcl_GetStringFromObj((objPtr), &length); \
+        TclPrintSource(stdout, bytes, TclMin(length, 30)); \
+        fprintf(stdout, "\n"); \
+        fflush(stdout); \
+    }
+#endif /* TCL_COMPILE_STATS */
+
+#else  /* not TCL_COMPILE_DEBUG */
+	
+#define TRACE(a)
+#define TRACE_WITH_OBJ(a, objPtr)
+#define O2S(objPtr)
+	
+#endif /* TCL_COMPILE_DEBUG */
+
+/*
+ * Declarations for local procedures to this file:
+ */
+
+static void		CallTraceProcedure _ANSI_ARGS_((Tcl_Interp *interp,
+			    Trace *tracePtr, Command *cmdPtr,
+			    char *command, int numChars,
+			    int objc, Tcl_Obj *objv[]));
+static void		DupCmdNameInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr,
+			    Tcl_Obj *copyPtr));
+static int		ExprAbsFunc _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExecEnv *eePtr, ClientData clientData));
+static int		ExprBinaryFunc _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExecEnv *eePtr, ClientData clientData));
+static int		ExprCallMathFunc _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExecEnv *eePtr, int objc, Tcl_Obj **objv));
+static int		ExprDoubleFunc _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExecEnv *eePtr, ClientData clientData));
+static int		ExprIntFunc _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExecEnv *eePtr, ClientData clientData));
+static int		ExprRoundFunc _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExecEnv *eePtr, ClientData clientData));
+static int		ExprUnaryFunc _ANSI_ARGS_((Tcl_Interp *interp,
+			    ExecEnv *eePtr, ClientData clientData));
+#ifdef TCL_COMPILE_STATS
+static int              EvalStatsCmd _ANSI_ARGS_((ClientData clientData,
+                            Tcl_Interp *interp, int argc, char **argv));
+#endif /* TCL_COMPILE_STATS */
+static void		FreeCmdNameInternalRep _ANSI_ARGS_((
+    			    Tcl_Obj *objPtr));
+static char *		GetSrcInfoForPc _ANSI_ARGS_((unsigned char *pc,
+        		    ByteCode* codePtr, int *lengthPtr));
+static void		GrowEvaluationStack _ANSI_ARGS_((ExecEnv *eePtr));
+static void		IllegalExprOperandType _ANSI_ARGS_((
+			    Tcl_Interp *interp, unsigned int opCode,
+			    Tcl_Obj *opndPtr));
+static void		InitByteCodeExecution _ANSI_ARGS_((
+			    Tcl_Interp *interp));
+static void		PrintByteCodeInfo _ANSI_ARGS_((ByteCode *codePtr));
+static void		RecordTracebackInfo _ANSI_ARGS_((Tcl_Interp *interp,
+			    unsigned char *pc, ByteCode *codePtr));
+static int		SetCmdNameFromAny _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr));
+#ifdef TCL_COMPILE_DEBUG
+static char *		StringForResultCode _ANSI_ARGS_((int result));
+#endif /* TCL_COMPILE_DEBUG */
+static void		UpdateStringOfCmdName _ANSI_ARGS_((Tcl_Obj *objPtr));
+#ifdef TCL_COMPILE_DEBUG
+static void		ValidatePcAndStackTop _ANSI_ARGS_((
+			    ByteCode *codePtr, unsigned char *pc,
+			    int stackTop, int stackLowerBound,
+			    int stackUpperBound));
+#endif /* TCL_COMPILE_DEBUG */
+
+/*
+ * Table describing the built-in math functions. Entries in this table are
+ * indexed by the values of the INST_CALL_BUILTIN_FUNC instruction's
+ * operand byte.
+ */
+
+BuiltinFunc builtinFuncTable[] = {
+#ifndef TCL_NO_MATH
+    {"acos", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) acos},
+    {"asin", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) asin},
+    {"atan", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) atan},
+    {"atan2", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) atan2},
+    {"ceil", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) ceil},
+    {"cos", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) cos},
+    {"cosh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) cosh},
+    {"exp", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) exp},
+    {"floor", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) floor},
+    {"fmod", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) fmod},
+    {"hypot", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) hypot},
+    {"log", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) log},
+    {"log10", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) log10},
+    {"pow", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) pow},
+    {"sin", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sin},
+    {"sinh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sinh},
+    {"sqrt", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sqrt},
+    {"tan", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) tan},
+    {"tanh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) tanh},
+#endif
+    {"abs", 1, {TCL_EITHER}, ExprAbsFunc, 0},
+    {"double", 1, {TCL_EITHER}, ExprDoubleFunc, 0},
+    {"int", 1, {TCL_EITHER}, ExprIntFunc, 0},
+    {"round", 1, {TCL_EITHER}, ExprRoundFunc, 0},
+    {0},
+};
+
+/*
+ * The structure below defines the command name Tcl object type by means of
+ * procedures that can be invoked by generic object code. Objects of this
+ * type cache the Command pointer that results from looking up command names
+ * in the command hashtable. Such objects appear as the zeroth ("command
+ * name") argument in a Tcl command.
+ */
+
+Tcl_ObjType tclCmdNameType = {
+    "cmdName",				/* name */
+    FreeCmdNameInternalRep,		/* freeIntRepProc */
+    DupCmdNameInternalRep,		/* dupIntRepProc */
+    UpdateStringOfCmdName,		/* updateStringProc */
+    SetCmdNameFromAny			/* setFromAnyProc */
+};
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitByteCodeExecution --
+ *
+ *	This procedure is called once to initialize the Tcl bytecode
+ *	interpreter.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	This procedure initializes the array of instruction names. If
+ *	compiling with the TCL_COMPILE_STATS flag, it initializes the
+ *	array that counts the executions of each instruction and it
+ *	creates the "evalstats" command. It also registers the command name
+ *	Tcl_ObjType. It also establishes the link between the Tcl
+ *	"tcl_traceExec" and C "tclTraceExec" variables.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitByteCodeExecution(interp)
+    Tcl_Interp *interp;		/* Interpreter for which the Tcl variable
+				 * "tcl_traceExec" is linked to control
+				 * instruction tracing. */
+{
+    int i;
+    
+    Tcl_RegisterObjType(&tclCmdNameType);
+
+    (VOID *) memset(opName, 0, sizeof(opName));
+    for (i = 0;  instructionTable[i].name != NULL;  i++) {
+	opName[i] = instructionTable[i].name;
+    }
+
+#ifdef TCL_COMPILE_STATS    
+    (VOID *) memset(instructionCount, 0, sizeof(instructionCount));
+    (VOID *) memset(tclByteCodeCount, 0, sizeof(tclByteCodeCount));
+    (VOID *) memset(tclSourceCount, 0, sizeof(tclSourceCount));
+
+    Tcl_CreateCommand(interp, "evalstats", EvalStatsCmd,
+		      (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
+#endif /* TCL_COMPILE_STATS */
+    
+    if (Tcl_LinkVar(interp, "tcl_traceExec", (char *) &tclTraceExec,
+		    TCL_LINK_INT) != TCL_OK) {
+	panic("InitByteCodeExecution: can't create link for tcl_traceExec variable");
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCreateExecEnv --
+ *
+ *	This procedure creates a new execution environment for Tcl bytecode
+ *	execution. An ExecEnv points to a Tcl evaluation stack. An ExecEnv
+ *	is typically created once for each Tcl interpreter (Interp
+ *	structure) and recursively passed to TclExecuteByteCode to execute
+ *	ByteCode sequences for nested commands.
+ *
+ * Results:
+ *	A newly allocated ExecEnv is returned. This points to an empty
+ *	evaluation stack of the standard initial size.
+ *
+ * Side effects:
+ *	The bytecode interpreter is also initialized here, as this
+ *	procedure will be called before any call to TclExecuteByteCode.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#define TCL_STACK_INITIAL_SIZE 2000
+
+ExecEnv *
+TclCreateExecEnv(interp)
+    Tcl_Interp *interp;		/* Interpreter for which the execution
+				 * environment is being created. */
+{
+    ExecEnv *eePtr = (ExecEnv *) ckalloc(sizeof(ExecEnv));
+
+    eePtr->stackPtr = (StackItem *)
+	ckalloc((unsigned) (TCL_STACK_INITIAL_SIZE * sizeof(StackItem)));
+    eePtr->stackTop = -1;
+    eePtr->stackEnd = (TCL_STACK_INITIAL_SIZE - 1);
+
+    if (!execInitialized) {
+        TclInitAuxDataTypeTable();
+        InitByteCodeExecution(interp);
+        execInitialized = 1;
+    }
+
+    return eePtr;
+}
+#undef TCL_STACK_INITIAL_SIZE
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclDeleteExecEnv --
+ *
+ *	Frees the storage for an ExecEnv.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Storage for an ExecEnv and its contained storage (e.g. the
+ *	evaluation stack) is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclDeleteExecEnv(eePtr)
+    ExecEnv *eePtr;		/* Execution environment to free. */
+{
+    ckfree((char *) eePtr->stackPtr);
+    ckfree((char *) eePtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFinalizeExecEnv --
+ *
+ *	Finalizes the execution environment setup so that it can be
+ *	later reinitialized.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	After this call, the next time TclCreateExecEnv will be called
+ *	it will call InitByteCodeExecution.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclFinalizeExecEnv()
+{
+    execInitialized = 0;
+    TclFinalizeAuxDataTypeTable();
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GrowEvaluationStack --
+ *
+ *	This procedure grows a Tcl evaluation stack stored in an ExecEnv.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The size of the evaluation stack is doubled.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GrowEvaluationStack(eePtr)
+    register ExecEnv *eePtr; /* Points to the ExecEnv with an evaluation
+			      * stack to enlarge. */
+{
+    /*
+     * The current Tcl stack elements are stored from eePtr->stackPtr[0]
+     * to eePtr->stackPtr[eePtr->stackEnd] (inclusive).
+     */
+
+    int currElems = (eePtr->stackEnd + 1);
+    int newElems  = 2*currElems;
+    int currBytes = currElems * sizeof(StackItem);
+    int newBytes  = 2*currBytes;
+    StackItem *newStackPtr = (StackItem *) ckalloc((unsigned) newBytes);
+
+    /*
+     * Copy the existing stack items to the new stack space, free the old
+     * storage if appropriate, and mark new space as malloc'ed.
+     */
+ 
+    memcpy((VOID *) newStackPtr, (VOID *) eePtr->stackPtr,
+	   (size_t) currBytes);
+    ckfree((char *) eePtr->stackPtr);
+    eePtr->stackPtr = newStackPtr;
+    eePtr->stackEnd = (newElems - 1); /* i.e. index of last usable item */
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclExecuteByteCode --
+ *
+ *	This procedure executes the instructions of a ByteCode structure.
+ *	It returns when a "done" instruction is executed or an error occurs.
+ *
+ * Results:
+ *	The return value is one of the return codes defined in tcl.h
+ *	(such as TCL_OK), and interp->objResultPtr refers to a Tcl object
+ *	that either contains the result of executing the code or an
+ *	error message.
+ *
+ * Side effects:
+ *	Almost certainly, depending on the ByteCode's instructions.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclExecuteByteCode(interp, codePtr)
+    Tcl_Interp *interp;		/* Token for command interpreter. */
+    ByteCode *codePtr;		/* The bytecode sequence to interpret. */
+{
+    Interp *iPtr = (Interp *) interp;
+    ExecEnv *eePtr = iPtr->execEnvPtr;
+    				/* Points to the execution environment. */
+    register StackItem *stackPtr = eePtr->stackPtr;
+    				/* Cached evaluation stack base pointer. */
+    register int stackTop = eePtr->stackTop;
+    				/* Cached top index of evaluation stack. */
+    Tcl_Obj **objArrayPtr = codePtr->objArrayPtr;
+    				/* Points to the ByteCode's object array. */
+    unsigned char *pc = codePtr->codeStart;
+				/* The current program counter. */
+    unsigned char opCode;	/* The current instruction code. */
+    int opnd;			/* Current instruction's operand byte. */
+    int pcAdjustment;		/* Hold pc adjustment after instruction. */
+    int initStackTop = stackTop;/* Stack top at start of execution. */
+    ExceptionRange *rangePtr;	/* Points to closest loop or catch exception
+				 * range enclosing the pc. Used by various
+				 * instructions and processCatch to
+				 * process break, continue, and errors. */
+    int result = TCL_OK;	/* Return code returned after execution. */
+    int traceInstructions = (tclTraceExec == 3);
+    Tcl_Obj *valuePtr, *value2Ptr, *namePtr, *objPtr;
+    char *bytes;
+    int length;
+    long i;
+    Tcl_DString command;	/* Used for debugging. If tclTraceExec >= 2
+				 * holds a string representing the last
+				 * command invoked. */
+
+    /*
+     * This procedure uses a stack to hold information about catch commands.
+     * This information is the current operand stack top when starting to
+     * execute the code for each catch command. It starts out with stack-
+     * allocated space but uses dynamically-allocated storage if needed.
+     */
+
+#define STATIC_CATCH_STACK_SIZE 5
+    int (catchStackStorage[STATIC_CATCH_STACK_SIZE]);
+    int *catchStackPtr = catchStackStorage;
+    int catchTop = -1;
+
+    /*
+     * THIS PROC FAILS IF AN OBJECT'S STRING REP HAS A NULL BYTE.
+     */
+
+    if (tclTraceExec >= 2) {
+	PrintByteCodeInfo(codePtr);
+#ifdef TCL_COMPILE_STATS
+	fprintf(stdout, "  Starting stack top=%d, system objects=%ld\n",
+		eePtr->stackTop, (tclObjsAlloced - tclObjsFreed));
+#else
+	fprintf(stdout, "  Starting stack top=%d\n", eePtr->stackTop);
+#endif /* TCL_COMPILE_STATS */
+	fflush(stdout);
+    }
+
+#ifdef TCL_COMPILE_STATS
+    numExecutions++;
+#endif /* TCL_COMPILE_STATS */
+
+    /*
+     * Make sure the catch stack is large enough to hold the maximum number
+     * of catch commands that could ever be executing at the same time. This
+     * will be no more than the exception range array's depth.
+     */
+
+    if (codePtr->maxExcRangeDepth > STATIC_CATCH_STACK_SIZE) {
+	catchStackPtr = (int *)
+	        ckalloc(codePtr->maxExcRangeDepth * sizeof(int));
+    }
+
+    /*
+     * Make sure the stack has enough room to execute this ByteCode.
+     */
+
+    while ((stackTop + codePtr->maxStackDepth) > eePtr->stackEnd) {
+        GrowEvaluationStack(eePtr); 
+        stackPtr = eePtr->stackPtr;
+    }
+
+    /*
+     * Initialize the buffer that holds a string containing the name and
+     * arguments for the last invoked command.
+     */
+
+    Tcl_DStringInit(&command);
+
+    /*
+     * Loop executing instructions until a "done" instruction, a TCL_RETURN,
+     * or some error.
+     */
+
+    for (;;) {
+#ifdef TCL_COMPILE_DEBUG
+	ValidatePcAndStackTop(codePtr, pc, stackTop, initStackTop,
+		eePtr->stackEnd);
+#else /* not TCL_COMPILE_DEBUG */
+	if (traceInstructions) {
+#ifdef TCL_COMPILE_STATS
+	    fprintf(stdout, "%d: %d,%ld ", iPtr->numLevels, stackTop,
+		    (tclObjsAlloced - tclObjsFreed));
+#else /* TCL_COMPILE_STATS */
+	    fprintf(stdout, "%d: %d ", iPtr->numLevels, stackTop);
+#endif /* TCL_COMPILE_STATS */
+	    TclPrintInstruction(codePtr, pc);
+	    fflush(stdout);
+	}
+#endif /* TCL_COMPILE_DEBUG */
+	
+	opCode = *pc;
+#ifdef TCL_COMPILE_STATS    
+	instructionCount[opCode]++;
+#endif /* TCL_COMPILE_STATS */
+
+        switch (opCode) {
+	case INST_DONE:
+	    /*
+	     * Pop the topmost object from the stack, set the interpreter's
+	     * object result to point to it, and return.
+	     */
+	    valuePtr = POP_OBJECT();
+	    Tcl_SetObjResult(interp, valuePtr);
+	    TclDecrRefCount(valuePtr);
+	    if (stackTop != initStackTop) {
+		fprintf(stderr, "\nTclExecuteByteCode: done instruction at pc %u: stack top %d != entry stack top %d\n",
+			(unsigned int)(pc - codePtr->codeStart),
+			(unsigned int) stackTop,
+			(unsigned int) initStackTop);
+		fprintf(stderr, "  Source: ");
+		TclPrintSource(stderr, codePtr->source, 150);
+		panic("TclExecuteByteCode execution failure: end stack top != start stack top");
+	    }
+	    TRACE_WITH_OBJ(("done => return code=%d, result is ", result),
+		    iPtr->objResultPtr);
+	    goto done;
+	    
+	case INST_PUSH1:
+	    valuePtr = objArrayPtr[TclGetUInt1AtPtr(pc+1)];
+	    PUSH_OBJECT(valuePtr);
+	    TRACE_WITH_OBJ(("push1 %u => ", TclGetUInt1AtPtr(pc+1)),
+	            valuePtr);
+	    ADJUST_PC(2);
+	    
+	case INST_PUSH4:
+	    valuePtr = objArrayPtr[TclGetUInt4AtPtr(pc+1)];
+	    PUSH_OBJECT(valuePtr);
+	    TRACE_WITH_OBJ(("push4 %u => ", TclGetUInt4AtPtr(pc+1)),
+		    valuePtr);
+	    ADJUST_PC(5);
+	    
+	case INST_POP:
+	    valuePtr = POP_OBJECT();
+	    TRACE_WITH_OBJ(("pop => discarding "), valuePtr);
+	    TclDecrRefCount(valuePtr); /* finished with pop'ed object. */
+	    ADJUST_PC(1);
+
+	case INST_DUP:
+	    valuePtr = stackPtr[stackTop].o;
+	    PUSH_OBJECT(Tcl_DuplicateObj(valuePtr));
+	    TRACE_WITH_OBJ(("dup => "), valuePtr);
+	    ADJUST_PC(1);
+
+	case INST_CONCAT1:
+	    opnd = TclGetUInt1AtPtr(pc+1);
+	    {
+		Tcl_Obj *concatObjPtr;
+		int totalLen = 0;
+
+		/*
+		 * Concatenate strings (with no separators) from the top
+		 * opnd items on the stack starting with the deepest item.
+		 * First, determine how many characters are needed.
+		 */
+
+		for (i = (stackTop - (opnd-1));  i <= stackTop;  i++) {
+		    valuePtr = stackPtr[i].o;
+		    bytes = TclGetStringFromObj(valuePtr, &length);
+		    if (bytes != NULL) {
+			totalLen += length;
+		    }
+                }
+
+		/*
+		 * Initialize the new append string object by appending the
+		 * strings of the opnd stack objects. Also pop the objects. 
+		 */
+
+		TclNewObj(concatObjPtr);
+		if (totalLen > 0) {
+		    char *p = (char *) ckalloc((unsigned) (totalLen + 1));
+		    concatObjPtr->bytes = p;
+		    concatObjPtr->length = totalLen;
+		    for (i = (stackTop - (opnd-1));  i <= stackTop;  i++) {
+			valuePtr = stackPtr[i].o;
+			bytes = TclGetStringFromObj(valuePtr, &length);
+			if (bytes != NULL) {
+			    memcpy((VOID *) p, (VOID *) bytes,
+			            (size_t) length);
+			    p += length;
+			}
+			TclDecrRefCount(valuePtr);
+		    }
+		    *p = '\0';
+		} else {
+		    for (i = (stackTop - (opnd-1));  i <= stackTop;  i++) {
+			valuePtr = stackPtr[i].o;
+			Tcl_DecrRefCount(valuePtr);
+		    }
+		}
+		stackTop -= opnd;
+		
+		PUSH_OBJECT(concatObjPtr);
+		TRACE_WITH_OBJ(("concat %u => ", opnd), concatObjPtr);
+		ADJUST_PC(2);
+            }
+	    
+	case INST_INVOKE_STK4:
+	    opnd = TclGetUInt4AtPtr(pc+1);
+	    pcAdjustment = 5;
+	    goto doInvocation;
+
+	case INST_INVOKE_STK1:
+	    opnd = TclGetUInt1AtPtr(pc+1);
+	    pcAdjustment = 2;
+	    
+	    doInvocation:
+	    {
+		char *cmdName;
+		Command *cmdPtr;   /* Points to command's Command struct. */
+		int objc = opnd;   /* The number of arguments. */
+		Tcl_Obj **objv;	   /* The array of argument objects. */
+		Tcl_Obj *objv0Ptr; /* Holds objv[0], the command name. */
+		int newPcOffset = 0;
+				   /* Instruction offset computed during
+				    * break, continue, error processing.
+				    * Init. to avoid compiler warning. */
+		Tcl_Command cmd;
+#ifdef TCL_COMPILE_DEBUG
+		int isUnknownCmd = 0;
+		char cmdNameBuf[30];
+#endif /* TCL_COMPILE_DEBUG */
+		
+		/*
+		 * If the interpreter was deleted, return an error.
+		 */
+		
+		if (iPtr->flags & DELETED) {
+		    Tcl_ResetResult(interp);
+		    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		            "attempt to call eval in deleted interpreter", -1);
+		    Tcl_SetErrorCode(interp, "CORE", "IDELETE",
+			    "attempt to call eval in deleted interpreter",
+			    (char *) NULL);
+		    result = TCL_ERROR;
+		    goto checkForCatch;
+		}
+    
+		objv = &(stackPtr[stackTop - (objc-1)].o);
+		objv0Ptr = objv[0];
+		cmdName = TclGetStringFromObj(objv0Ptr, (int *) NULL);
+		
+		/*
+		 * Find the procedure to execute this command. If there
+		 * isn't one, then see if there is a command "unknown". If
+		 * so, invoke it, passing it the original command words as
+		 * arguments.
+		 *
+		 * We convert the objv[0] object to be a CmdName object.
+		 * This caches a pointer to the Command structure for the
+		 * command; this pointer is held in a ResolvedCmdName
+		 * structure the object's internal rep. points to.
+		 */
+
+		cmd = Tcl_GetCommandFromObj(interp, objv0Ptr);
+		cmdPtr = (Command *) cmd;
+		
+		/*
+		 * If the command is still not found, handle it with the
+		 * "unknown" proc.
+		 */
+
+		if (cmdPtr == NULL) {
+		    cmd = Tcl_FindCommand(interp, "unknown",
+                            (Tcl_Namespace *) NULL, /*flags*/ TCL_GLOBAL_ONLY);
+                    if (cmd == (Tcl_Command) NULL) {
+			Tcl_ResetResult(interp);
+			Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+			        "invalid command name \"", cmdName, "\"",
+				(char *) NULL);
+			TRACE(("%s %u => unknown proc not found: ",
+			       opName[opCode], objc));
+			result = TCL_ERROR;
+			goto checkForCatch;
+		    }
+		    cmdPtr = (Command *) cmd;
+#ifdef TCL_COMPILE_DEBUG
+		    isUnknownCmd = 1;
+#endif /*TCL_COMPILE_DEBUG*/			
+		    stackTop++; /* need room for new inserted objv[0] */
+		    for (i = objc;  i >= 0;  i--) {
+			objv[i+1] = objv[i];
+		    }
+		    objc++;
+		    objv[0] = Tcl_NewStringObj("unknown", -1);
+		    Tcl_IncrRefCount(objv[0]);
+		}
+		
+		/*
+		 * Call any trace procedures.
+		 */
+
+		if (iPtr->tracePtr != NULL) {
+		    Trace *tracePtr, *nextTracePtr;
+
+		    for (tracePtr = iPtr->tracePtr;  tracePtr != NULL;
+		            tracePtr = nextTracePtr) {
+			nextTracePtr = tracePtr->nextPtr;
+			if (iPtr->numLevels <= tracePtr->level) {
+			    int numChars;
+			    char *cmd = GetSrcInfoForPc(pc, codePtr,
+				    &numChars);
+			    if (cmd != NULL) {
+				DECACHE_STACK_INFO();
+				CallTraceProcedure(interp, tracePtr, cmdPtr,
+				        cmd, numChars, objc, objv);
+				CACHE_STACK_INFO();
+			    }
+			}
+		    }
+		}
+		
+		/*
+		 * Finally, invoke the command's Tcl_ObjCmdProc. First reset
+		 * the interpreter's string and object results to their
+		 * default empty values since they could have gotten changed
+		 * by earlier invocations.
+		 */
+		
+		Tcl_ResetResult(interp);
+
+		if (tclTraceExec >= 2) {
+		    char buffer[50];
+
+		    sprintf(buffer, "%d: (%u) invoking ", iPtr->numLevels,
+			    (unsigned int)(pc - codePtr->codeStart));
+		    Tcl_DStringAppend(&command, buffer, -1);
+		    
+#ifdef TCL_COMPILE_DEBUG
+		    if (traceInstructions) { /* tclTraceExec == 3 */
+			strncpy(cmdNameBuf, cmdName, 20);
+			TRACE(("%s %u => call ", opName[opCode],
+			       (isUnknownCmd? objc-1 : objc)));
+		    } else {
+			fprintf(stdout, "%s", buffer);
+		    }
+#else /* TCL_COMPILE_DEBUG */
+		    fprintf(stdout, "%s", buffer);
+#endif /*TCL_COMPILE_DEBUG*/
+
+		    for (i = 0;  i < objc;  i++) {
+			bytes = TclGetStringFromObj(objv[i], &length);
+			TclPrintSource(stdout, bytes, TclMin(length, 15));
+			fprintf(stdout, " ");
+
+			sprintf(buffer, "\"%.*s\" ", TclMin(length, 15), bytes);
+			Tcl_DStringAppend(&command, buffer, -1);
+		    }
+		    fprintf(stdout, "\n");
+		    fflush(stdout);
+
+		    Tcl_DStringFree(&command);
+		}
+
+		iPtr->cmdCount++;
+		DECACHE_STACK_INFO();
+		result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp,
+					    objc, objv);
+		if (Tcl_AsyncReady()) {
+		    result = Tcl_AsyncInvoke(interp, result);
+		}
+		CACHE_STACK_INFO();
+
+		/*
+		 * If the interpreter has a non-empty string result, the
+		 * result object is either empty or stale because some
+		 * procedure set interp->result directly. If so, move the
+		 * string result to the result object, then reset the
+		 * string result.
+		 */
+
+		if (*(iPtr->result) != 0) {
+		    (void) Tcl_GetObjResult(interp);
+		}
+		
+		/*
+		 * Pop the objc top stack elements and decrement their ref
+		 * counts. 
+		 */
+		
+		i = (stackTop - (objc-1));
+		while (i <= stackTop) {
+		    valuePtr = stackPtr[i].o;
+		    TclDecrRefCount(valuePtr);
+		    i++;
+		}
+		stackTop -= objc;
+
+		/*
+		 * Process the result of the Tcl_ObjCmdProc call.
+		 */
+		
+		switch (result) {
+		case TCL_OK:
+		    /*
+		     * Push the call's object result and continue execution
+		     * with the next instruction.
+		     */
+		    PUSH_OBJECT(Tcl_GetObjResult(interp));
+		    TRACE_WITH_OBJ(("%s %u => ...after \"%.20s\", result=",
+		            opName[opCode], objc, cmdNameBuf),
+			    Tcl_GetObjResult(interp));
+		    ADJUST_PC(pcAdjustment);
+		    
+		case TCL_BREAK:
+		case TCL_CONTINUE:
+		    /*
+		     * The invoked command requested a break or continue.
+		     * Find the closest enclosing loop or catch exception
+		     * range, if any. If a loop is found, terminate its
+		     * execution or skip to its next iteration. If the
+		     * closest is a catch exception range, jump to its
+		     * catchOffset. If no enclosing range is found, stop
+		     * execution and return the TCL_BREAK or TCL_CONTINUE.
+		     */
+		    rangePtr = TclGetExceptionRangeForPc(pc,
+                            /*catchOnly*/ 0, codePtr);
+		    if (rangePtr == NULL) {
+		        TRACE(("%s %u => ... after \"%.20s\", no encl. loop or catch, returning %s\n",
+		                opName[opCode], objc, cmdNameBuf,
+			        StringForResultCode(result)));
+			goto abnormalReturn; /* no catch exists to check */
+		    }
+		    switch (rangePtr->type) {
+		    case LOOP_EXCEPTION_RANGE:
+			if (result == TCL_BREAK) {
+			    newPcOffset = rangePtr->breakOffset;
+			} else if (rangePtr->continueOffset == -1) {
+			    TRACE(("%s %u => ... after \"%.20s\", %s, loop w/o continue, checking for catch\n",
+				   opName[opCode], objc, cmdNameBuf,
+				   StringForResultCode(result)));
+			    goto checkForCatch;
+			} else {
+			    newPcOffset = rangePtr->continueOffset;
+			}
+			TRACE(("%s %u => ... after \"%.20s\", %s, range at %d, new pc %d\n",
+			       opName[opCode], objc, cmdNameBuf,
+			       StringForResultCode(result),
+			       rangePtr->codeOffset, newPcOffset));
+			break;
+		    case CATCH_EXCEPTION_RANGE:
+			TRACE(("%s %u => ... after \"%.20s\", %s...\n",
+			       opName[opCode], objc, cmdNameBuf,
+			       StringForResultCode(result)));
+			goto processCatch; /* it will use rangePtr */
+		    default:
+			panic("TclExecuteByteCode: unrecognized ExceptionRange type %d\n", rangePtr->type);
+		    }
+		    result = TCL_OK;
+		    pc = (codePtr->codeStart + newPcOffset);
+		    continue;	/* restart outer instruction loop at pc */
+		    
+		case TCL_ERROR:
+		    /*
+		     * The invoked command returned an error. Look for an
+		     * enclosing catch exception range, if any.
+		     */
+		    TRACE_WITH_OBJ(("%s %u => ... after \"%.20s\", TCL_ERROR ",
+		            opName[opCode], objc, cmdNameBuf),
+			    Tcl_GetObjResult(interp));
+		    goto checkForCatch;
+
+		case TCL_RETURN:
+		    /*
+		     * The invoked command requested that the current
+		     * procedure stop execution and return. First check
+		     * for an enclosing catch exception range, if any.
+		     */
+		    TRACE(("%s %u => ... after \"%.20s\", TCL_RETURN\n",
+		            opName[opCode], objc, cmdNameBuf));
+		    goto checkForCatch;
+
+		default:
+		    TRACE_WITH_OBJ(("%s %u => ... after \"%.20s\", OTHER RETURN CODE %d ",
+		            opName[opCode], objc, cmdNameBuf, result),
+			    Tcl_GetObjResult(interp));
+		    goto checkForCatch;
+		} /* end of switch on result from invoke instruction */
+	    }
+	    
+	case INST_EVAL_STK:
+	    objPtr = POP_OBJECT();
+	    DECACHE_STACK_INFO();
+	    result = Tcl_EvalObj(interp, objPtr);
+	    CACHE_STACK_INFO();
+	    if (result == TCL_OK) {
+		/*
+		 * Normal return; push the eval's object result.
+		 */
+		
+		PUSH_OBJECT(Tcl_GetObjResult(interp));
+		TRACE_WITH_OBJ(("evalStk \"%.30s\" => ", O2S(objPtr)),
+			Tcl_GetObjResult(interp));
+		TclDecrRefCount(objPtr);
+		ADJUST_PC(1);
+	    } else if ((result == TCL_BREAK) || (result == TCL_CONTINUE)) {
+		/*
+		 * Find the closest enclosing loop or catch exception range,
+		 * if any. If a loop is found, terminate its execution or
+		 * skip to its next iteration. If the closest is a catch
+		 * exception range, jump to its catchOffset. If no enclosing
+		 * range is found, stop execution and return that same
+		 * TCL_BREAK or TCL_CONTINUE.
+		 */
+
+		int newPcOffset = 0; /* Pc offset computed during break,
+				      * continue, error processing. Init.
+				      * to avoid compiler warning. */
+
+		rangePtr = TclGetExceptionRangeForPc(pc, /*catchOnly*/ 0,
+			codePtr);
+		if (rangePtr == NULL) {
+		    TRACE(("evalStk \"%.30s\" => no encl. loop or catch, returning %s\n",
+			    O2S(objPtr), StringForResultCode(result)));
+		    Tcl_DecrRefCount(objPtr);
+		    goto abnormalReturn;    /* no catch exists to check */
+		}
+		switch (rangePtr->type) {
+		case LOOP_EXCEPTION_RANGE:
+		    if (result == TCL_BREAK) {
+			newPcOffset = rangePtr->breakOffset;
+		    } else if (rangePtr->continueOffset == -1) {
+			TRACE(("evalStk \"%.30s\" => %s, loop w/o continue, checking for catch\n",
+			       O2S(objPtr), StringForResultCode(result)));
+			Tcl_DecrRefCount(objPtr);
+			goto checkForCatch;
+		    } else {
+			newPcOffset = rangePtr->continueOffset;
+		    }
+		    result = TCL_OK;
+		    TRACE_WITH_OBJ(("evalStk \"%.30s\" => %s, range at %d, new pc %d ",
+			    O2S(objPtr), StringForResultCode(result),
+			    rangePtr->codeOffset, newPcOffset), valuePtr);
+		    break;
+		case CATCH_EXCEPTION_RANGE:
+		    TRACE_WITH_OBJ(("evalStk \"%.30s\" => %s ",
+			    O2S(objPtr), StringForResultCode(result)),
+			    valuePtr);
+		    Tcl_DecrRefCount(objPtr);
+		    goto processCatch;  /* it will use rangePtr */
+		default:
+		    panic("TclExecuteByteCode: unrecognized ExceptionRange type %d\n", rangePtr->type);
+		}
+		Tcl_DecrRefCount(objPtr);
+		pc = (codePtr->codeStart + newPcOffset);
+		continue;	/* restart outer instruction loop at pc */
+	    } else { /* eval returned TCL_ERROR, TCL_RETURN, unknown code */
+		TRACE_WITH_OBJ(("evalStk \"%.30s\" => ERROR: ", O2S(objPtr)),
+		        Tcl_GetObjResult(interp));
+		Tcl_DecrRefCount(objPtr);
+		goto checkForCatch;
+	    }
+
+	case INST_EXPR_STK:
+	    objPtr = POP_OBJECT();
+	    Tcl_ResetResult(interp);
+	    DECACHE_STACK_INFO();
+	    result = Tcl_ExprObj(interp, objPtr, &valuePtr);
+	    CACHE_STACK_INFO();
+	    if (result != TCL_OK) {
+		TRACE_WITH_OBJ(("exprStk \"%.30s\" => ERROR: ", 
+		        O2S(objPtr)), Tcl_GetObjResult(interp));
+		Tcl_DecrRefCount(objPtr);
+		goto checkForCatch;
+	    }
+	    stackPtr[++stackTop].o = valuePtr; /* already has right refct */
+	    TRACE_WITH_OBJ(("exprStk \"%.30s\" => ", O2S(objPtr)), valuePtr);
+	    TclDecrRefCount(objPtr);
+	    ADJUST_PC(1);
+
+	case INST_LOAD_SCALAR4:
+	    opnd = TclGetInt4AtPtr(pc+1);
+	    pcAdjustment = 5;
+	    goto doLoadScalar;
+
+	case INST_LOAD_SCALAR1:
+	    opnd = TclGetUInt1AtPtr(pc+1);
+	    pcAdjustment = 2;
+	    
+	    doLoadScalar:
+	    DECACHE_STACK_INFO();
+	    valuePtr = TclGetIndexedScalar(interp, opnd,
+					   /*leaveErrorMsg*/ 1);
+	    CACHE_STACK_INFO();
+	    if (valuePtr == NULL) {
+		TRACE_WITH_OBJ(("%s %u => ERROR: ", opName[opCode], opnd),
+			Tcl_GetObjResult(interp));
+		result = TCL_ERROR;
+		goto checkForCatch;
+            }
+	    PUSH_OBJECT(valuePtr);
+	    TRACE_WITH_OBJ(("%s %u => ", opName[opCode], opnd), valuePtr);
+	    ADJUST_PC(pcAdjustment);
+
+	case INST_LOAD_SCALAR_STK:
+	    namePtr = POP_OBJECT();
+	    DECACHE_STACK_INFO();
+	    valuePtr = Tcl_ObjGetVar2(interp, namePtr, (Tcl_Obj *) NULL, 
+				      TCL_LEAVE_ERR_MSG);
+	    CACHE_STACK_INFO();
+	    if (valuePtr == NULL) {
+		TRACE_WITH_OBJ(("loadScalarStk \"%.30s\" => ERROR: ",
+		        O2S(namePtr)), Tcl_GetObjResult(interp));
+		Tcl_DecrRefCount(namePtr);
+		result = TCL_ERROR;
+		goto checkForCatch;
+            }
+	    PUSH_OBJECT(valuePtr);
+	    TRACE_WITH_OBJ(("loadScalarStk \"%.30s\" => ",
+		    O2S(namePtr)), valuePtr);
+	    TclDecrRefCount(namePtr);
+	    ADJUST_PC(1);
+
+	case INST_LOAD_ARRAY4:
+	    opnd = TclGetUInt4AtPtr(pc+1);
+	    pcAdjustment = 5;
+	    goto doLoadArray;
+
+	case INST_LOAD_ARRAY1:
+	    opnd = TclGetUInt1AtPtr(pc+1);
+	    pcAdjustment = 2;
+	    
+	    doLoadArray:
+	    {
+		Tcl_Obj *elemPtr = POP_OBJECT();
+		
+		DECACHE_STACK_INFO();
+		valuePtr = TclGetElementOfIndexedArray(interp, opnd,
+	                elemPtr, /*leaveErrorMsg*/ 1);
+		CACHE_STACK_INFO();
+		if (valuePtr == NULL) {
+		    TRACE_WITH_OBJ(("%s %u \"%.30s\" => ERROR: ",
+			    opName[opCode], opnd, O2S(elemPtr)),
+			    Tcl_GetObjResult(interp));
+		    Tcl_DecrRefCount(elemPtr);
+		    result = TCL_ERROR;
+		    goto checkForCatch;
+		}
+		PUSH_OBJECT(valuePtr);
+		TRACE_WITH_OBJ(("%s %u \"%.30s\" => ",
+		        opName[opCode], opnd, O2S(elemPtr)), valuePtr);
+		TclDecrRefCount(elemPtr);
+	    }
+	    ADJUST_PC(pcAdjustment);
+
+	case INST_LOAD_ARRAY_STK:
+	    {
+		Tcl_Obj *elemPtr = POP_OBJECT();
+		
+		namePtr = POP_OBJECT();
+		DECACHE_STACK_INFO();
+		valuePtr = Tcl_ObjGetVar2(interp, namePtr, elemPtr,
+		        TCL_LEAVE_ERR_MSG);
+		CACHE_STACK_INFO();
+		if (valuePtr == NULL) {
+		    TRACE_WITH_OBJ(("loadArrayStk \"%.30s(%.30s)\" => ERROR: ",
+		            O2S(namePtr), O2S(elemPtr)),
+			    Tcl_GetObjResult(interp));
+		    Tcl_DecrRefCount(namePtr);
+		    Tcl_DecrRefCount(elemPtr);
+		    result = TCL_ERROR;
+		    goto checkForCatch;
+		}
+		PUSH_OBJECT(valuePtr);
+		TRACE_WITH_OBJ(("loadArrayStk \"%.30s(%.30s)\" => ",
+		        O2S(namePtr), O2S(elemPtr)), valuePtr);
+		TclDecrRefCount(namePtr);
+		TclDecrRefCount(elemPtr);
+	    }
+	    ADJUST_PC(1);
+
+	case INST_LOAD_STK:
+	    namePtr = POP_OBJECT();
+	    DECACHE_STACK_INFO();
+	    valuePtr = Tcl_ObjGetVar2(interp, namePtr, NULL,
+		    TCL_PARSE_PART1|TCL_LEAVE_ERR_MSG);
+	    CACHE_STACK_INFO();
+	    if (valuePtr == NULL) {
+		TRACE_WITH_OBJ(("loadStk \"%.30s\" => ERROR: ",
+		        O2S(namePtr)), Tcl_GetObjResult(interp));
+		Tcl_DecrRefCount(namePtr);
+		result = TCL_ERROR;
+		goto checkForCatch;
+	    }
+	    PUSH_OBJECT(valuePtr);
+	    TRACE_WITH_OBJ(("loadStk \"%.30s\" => ", O2S(namePtr)),
+		    valuePtr);
+	    TclDecrRefCount(namePtr);
+	    ADJUST_PC(1);
+	    
+	case INST_STORE_SCALAR4:
+	    opnd = TclGetUInt4AtPtr(pc+1);
+	    pcAdjustment = 5;
+	    goto doStoreScalar;
+
+	case INST_STORE_SCALAR1:
+	    opnd = TclGetUInt1AtPtr(pc+1);
+	    pcAdjustment = 2;
+	    
+	  doStoreScalar:
+	    valuePtr = POP_OBJECT();
+	    DECACHE_STACK_INFO();
+	    value2Ptr = TclSetIndexedScalar(interp, opnd, valuePtr,
+					      /*leaveErrorMsg*/ 1);
+	    CACHE_STACK_INFO();
+	    if (value2Ptr == NULL) {
+		TRACE_WITH_OBJ(("%s %u <- \"%.30s\" => ERROR: ",
+			opName[opCode], opnd, O2S(valuePtr)),
+			Tcl_GetObjResult(interp));
+		Tcl_DecrRefCount(valuePtr);
+		result = TCL_ERROR;
+		goto checkForCatch;
+	    }
+	    PUSH_OBJECT(value2Ptr);
+	    TRACE_WITH_OBJ(("%s %u <- \"%.30s\" => ",
+		    opName[opCode], opnd, O2S(valuePtr)), value2Ptr);
+	    TclDecrRefCount(valuePtr);
+	    ADJUST_PC(pcAdjustment);
+
+	case INST_STORE_SCALAR_STK:
+	    valuePtr = POP_OBJECT();
+	    namePtr = POP_OBJECT();
+	    DECACHE_STACK_INFO();
+	    value2Ptr = Tcl_ObjSetVar2(interp, namePtr, NULL, valuePtr,
+	            TCL_LEAVE_ERR_MSG);
+	    CACHE_STACK_INFO();
+	    if (value2Ptr == NULL) {
+		TRACE_WITH_OBJ(
+			("storeScalarStk \"%.30s\" <- \"%.30s\" => ERROR: ",
+		        O2S(namePtr), O2S(valuePtr)),
+			Tcl_GetObjResult(interp));
+		Tcl_DecrRefCount(namePtr);
+		Tcl_DecrRefCount(valuePtr);
+		result = TCL_ERROR;
+		goto checkForCatch;
+	    }
+	    PUSH_OBJECT(value2Ptr);
+	    TRACE_WITH_OBJ(
+		    ("storeScalarStk \"%.30s\" <- \"%.30s\" => ",
+		    O2S(namePtr),
+		    O2S(valuePtr)),
+		    value2Ptr);
+	    TclDecrRefCount(namePtr);
+	    TclDecrRefCount(valuePtr);
+	    ADJUST_PC(1);
+
+	case INST_STORE_ARRAY4:
+	    opnd = TclGetUInt4AtPtr(pc+1);
+	    pcAdjustment = 5;
+	    goto doStoreArray;
+
+	case INST_STORE_ARRAY1:
+	    opnd = TclGetUInt1AtPtr(pc+1);
+	    pcAdjustment = 2;
+	    
+	    doStoreArray:
+	    {
+		Tcl_Obj *elemPtr;
+
+		valuePtr = POP_OBJECT();
+		elemPtr = POP_OBJECT();
+		DECACHE_STACK_INFO();
+		value2Ptr = TclSetElementOfIndexedArray(interp, opnd,
+		        elemPtr, valuePtr, TCL_LEAVE_ERR_MSG);
+		CACHE_STACK_INFO();
+		if (value2Ptr == NULL) {
+		    TRACE_WITH_OBJ(
+			    ("%s %u \"%.30s\" <- \"%.30s\" => ERROR: ",
+			    opName[opCode], opnd, O2S(elemPtr),
+			    O2S(valuePtr)), Tcl_GetObjResult(interp));
+		    Tcl_DecrRefCount(elemPtr);
+		    Tcl_DecrRefCount(valuePtr);
+		    result = TCL_ERROR;
+		    goto checkForCatch;
+		}
+		PUSH_OBJECT(value2Ptr);
+		TRACE_WITH_OBJ(("%s %u \"%.30s\" <- \"%.30s\" => ",
+		        opName[opCode], opnd, O2S(elemPtr), O2S(valuePtr)),
+		        value2Ptr);
+		TclDecrRefCount(elemPtr);
+		TclDecrRefCount(valuePtr);
+	    }
+	    ADJUST_PC(pcAdjustment);
+
+	case INST_STORE_ARRAY_STK:
+	    {
+		Tcl_Obj *elemPtr;
+
+		valuePtr = POP_OBJECT();
+		elemPtr = POP_OBJECT();
+		namePtr = POP_OBJECT();
+		DECACHE_STACK_INFO();
+		value2Ptr = Tcl_ObjSetVar2(interp, namePtr, elemPtr,
+		        valuePtr, TCL_LEAVE_ERR_MSG);
+		CACHE_STACK_INFO();
+		if (value2Ptr == NULL) {
+		    TRACE_WITH_OBJ(("storeArrayStk \"%.30s(%.30s)\" <- \"%.30s\" => ERROR: ",
+		            O2S(namePtr), O2S(elemPtr), O2S(valuePtr)),
+			    Tcl_GetObjResult(interp));
+		    Tcl_DecrRefCount(namePtr);
+		    Tcl_DecrRefCount(elemPtr);
+		    Tcl_DecrRefCount(valuePtr);
+		    result = TCL_ERROR;
+		    goto checkForCatch;
+		}
+		PUSH_OBJECT(value2Ptr);
+		TRACE_WITH_OBJ(("storeArrayStk \"%.30s(%.30s)\" <- \"%.30s\" => ",
+		        O2S(namePtr), O2S(elemPtr), O2S(valuePtr)),
+			value2Ptr);
+		TclDecrRefCount(namePtr);
+		TclDecrRefCount(elemPtr);
+		TclDecrRefCount(valuePtr);
+	    }
+	    ADJUST_PC(1);
+
+	case INST_STORE_STK:
+	    valuePtr = POP_OBJECT();
+	    namePtr = POP_OBJECT();
+	    DECACHE_STACK_INFO();
+	    value2Ptr = Tcl_ObjSetVar2(interp, namePtr, NULL, valuePtr,
+		    TCL_PARSE_PART1|TCL_LEAVE_ERR_MSG);
+	    CACHE_STACK_INFO();
+	    if (value2Ptr == NULL) {
+		TRACE_WITH_OBJ(("storeStk \"%.30s\" <- \"%.30s\" => ERROR: ",
+		        O2S(namePtr), O2S(valuePtr)),
+			Tcl_GetObjResult(interp));
+		Tcl_DecrRefCount(namePtr);
+		Tcl_DecrRefCount(valuePtr);
+		result = TCL_ERROR;
+		goto checkForCatch;
+	    }
+	    PUSH_OBJECT(value2Ptr);
+	    TRACE_WITH_OBJ(("storeStk \"%.30s\" <- \"%.30s\" => ",
+		    O2S(namePtr), O2S(valuePtr)), value2Ptr);
+	    TclDecrRefCount(namePtr);
+	    TclDecrRefCount(valuePtr);
+	    ADJUST_PC(1);
+
+	case INST_INCR_SCALAR1:
+	    opnd = TclGetUInt1AtPtr(pc+1);
+	    valuePtr = POP_OBJECT(); 
+	    if (valuePtr->typePtr != &tclIntType) {
+		result = tclIntType.setFromAnyProc(interp, valuePtr);
+		if (result != TCL_OK) {
+		    TRACE_WITH_OBJ(("incrScalar1 %u (by %s) => ERROR converting increment amount to int: ",
+		            opnd, O2S(valuePtr)), Tcl_GetObjResult(interp));
+		    Tcl_DecrRefCount(valuePtr);
+		    goto checkForCatch;
+		}
+	    }
+	    i = valuePtr->internalRep.longValue;
+	    DECACHE_STACK_INFO();
+	    value2Ptr = TclIncrIndexedScalar(interp, opnd, i);
+	    CACHE_STACK_INFO();
+	    if (value2Ptr == NULL) {
+		TRACE_WITH_OBJ(("incrScalar1 %u (by %ld) => ERROR: ",
+		        opnd, i), Tcl_GetObjResult(interp));
+		Tcl_DecrRefCount(valuePtr);
+		result = TCL_ERROR;
+		goto checkForCatch;
+	    }
+	    PUSH_OBJECT(value2Ptr);
+	    TRACE_WITH_OBJ(("incrScalar1 %u (by %ld) => ", opnd, i),
+		    value2Ptr);
+	    TclDecrRefCount(valuePtr);
+	    ADJUST_PC(2);
+
+	case INST_INCR_SCALAR_STK:
+	case INST_INCR_STK:
+	    valuePtr = POP_OBJECT();
+	    namePtr = POP_OBJECT();
+	    if (valuePtr->typePtr != &tclIntType) {
+		result = tclIntType.setFromAnyProc(interp, valuePtr);
+		if (result != TCL_OK) {
+		    TRACE_WITH_OBJ(("%s \"%.30s\" (by %s) => ERROR converting increment amount to int: ",
+		            opName[opCode], O2S(namePtr), O2S(valuePtr)),
+			    Tcl_GetObjResult(interp));
+		    Tcl_DecrRefCount(namePtr);
+		    Tcl_DecrRefCount(valuePtr);
+		    goto checkForCatch;
+		}
+	    }
+	    i = valuePtr->internalRep.longValue;
+	    DECACHE_STACK_INFO();
+	    value2Ptr = TclIncrVar2(interp, namePtr, (Tcl_Obj *) NULL, i,
+	        /*part1NotParsed*/ (opCode == INST_INCR_STK));
+	    CACHE_STACK_INFO();
+	    if (value2Ptr == NULL) {
+		TRACE_WITH_OBJ(("%s \"%.30s\" (by %ld) => ERROR: ",
+		        opName[opCode], O2S(namePtr), i),
+			Tcl_GetObjResult(interp));
+		Tcl_DecrRefCount(namePtr);
+		Tcl_DecrRefCount(valuePtr);
+		result = TCL_ERROR;
+		goto checkForCatch;
+	    }
+	    PUSH_OBJECT(value2Ptr);
+	    TRACE_WITH_OBJ(("%s \"%.30s\" (by %ld) => ",
+	            opName[opCode], O2S(namePtr), i), value2Ptr);
+	    Tcl_DecrRefCount(namePtr);
+	    Tcl_DecrRefCount(valuePtr);
+	    ADJUST_PC(1);
+
+	case INST_INCR_ARRAY1:
+	    {
+		Tcl_Obj *elemPtr;
+
+		opnd = TclGetUInt1AtPtr(pc+1);
+		valuePtr = POP_OBJECT();
+		elemPtr = POP_OBJECT();
+		if (valuePtr->typePtr != &tclIntType) {
+		    result = tclIntType.setFromAnyProc(interp, valuePtr);
+		    if (result != TCL_OK) {
+			TRACE_WITH_OBJ(("incrArray1 %u \"%.30s\" (by %s) => ERROR converting increment amount to int: ",
+		                opnd, O2S(elemPtr), O2S(valuePtr)),
+			        Tcl_GetObjResult(interp));
+			Tcl_DecrRefCount(elemPtr);
+			Tcl_DecrRefCount(valuePtr);
+			goto checkForCatch;
+		    }
+		}
+		i = valuePtr->internalRep.longValue;
+		DECACHE_STACK_INFO();
+		value2Ptr = TclIncrElementOfIndexedArray(interp, opnd,
+		        elemPtr, i);
+		CACHE_STACK_INFO();
+		if (value2Ptr == NULL) {
+		    TRACE_WITH_OBJ(("incrArray1 %u \"%.30s\" (by %ld) => ERROR: ",
+		            opnd, O2S(elemPtr), i),
+			    Tcl_GetObjResult(interp));
+		    Tcl_DecrRefCount(elemPtr);
+		    Tcl_DecrRefCount(valuePtr);
+		    result = TCL_ERROR;
+		    goto checkForCatch;
+		}
+		PUSH_OBJECT(value2Ptr);
+		TRACE_WITH_OBJ(("incrArray1 %u \"%.30s\" (by %ld) => ",
+	                opnd, O2S(elemPtr), i), value2Ptr);
+		Tcl_DecrRefCount(elemPtr);
+		Tcl_DecrRefCount(valuePtr);
+	    }
+	    ADJUST_PC(2);
+	    
+	case INST_INCR_ARRAY_STK:
+	    {
+		Tcl_Obj *elemPtr;
+
+		valuePtr = POP_OBJECT();
+		elemPtr = POP_OBJECT();
+		namePtr = POP_OBJECT();
+		if (valuePtr->typePtr != &tclIntType) {
+		    result = tclIntType.setFromAnyProc(interp, valuePtr);
+		    if (result != TCL_OK) {
+		        TRACE_WITH_OBJ(("incrArrayStk \"%.30s(%.30s)\" (by %s) => ERROR converting increment amount to int: ",
+		                O2S(namePtr), O2S(elemPtr), O2S(valuePtr)),
+			        Tcl_GetObjResult(interp));
+			Tcl_DecrRefCount(namePtr);
+			Tcl_DecrRefCount(elemPtr);
+			Tcl_DecrRefCount(valuePtr);
+			goto checkForCatch;
+		    }
+		}
+		i = valuePtr->internalRep.longValue;
+		DECACHE_STACK_INFO();
+		value2Ptr = TclIncrVar2(interp, namePtr, elemPtr, i,
+					/*part1NotParsed*/ 0);
+		CACHE_STACK_INFO();
+		if (value2Ptr == NULL) {
+		    TRACE_WITH_OBJ(("incrArrayStk \"%.30s(%.30s)\" (by %ld) => ERROR: ",
+		            O2S(namePtr), O2S(elemPtr), i),
+			    Tcl_GetObjResult(interp));
+		    Tcl_DecrRefCount(namePtr);
+		    Tcl_DecrRefCount(elemPtr);
+		    Tcl_DecrRefCount(valuePtr);
+		    result = TCL_ERROR;
+		    goto checkForCatch;
+		}
+		PUSH_OBJECT(value2Ptr);
+		TRACE_WITH_OBJ(("incrArrayStk \"%.30s(%.30s)\" (by %ld) => ",
+	                O2S(namePtr), O2S(elemPtr), i), value2Ptr);
+		Tcl_DecrRefCount(namePtr);
+		Tcl_DecrRefCount(elemPtr);
+		Tcl_DecrRefCount(valuePtr);
+	    }
+	    ADJUST_PC(1);
+	    
+	case INST_INCR_SCALAR1_IMM:
+	    opnd = TclGetUInt1AtPtr(pc+1);
+	    i = TclGetInt1AtPtr(pc+2);
+	    DECACHE_STACK_INFO();
+	    value2Ptr = TclIncrIndexedScalar(interp, opnd, i);
+	    CACHE_STACK_INFO();
+	    if (value2Ptr == NULL) {
+		TRACE_WITH_OBJ(("incrScalar1Imm %u %ld => ERROR: ",
+		        opnd, i), Tcl_GetObjResult(interp));
+		result = TCL_ERROR;
+		goto checkForCatch;
+	    }
+	    PUSH_OBJECT(value2Ptr);
+	    TRACE_WITH_OBJ(("incrScalar1Imm %u %ld => ", opnd, i),
+		    value2Ptr);
+	    ADJUST_PC(3);
+
+	case INST_INCR_SCALAR_STK_IMM:
+	case INST_INCR_STK_IMM:
+	    namePtr = POP_OBJECT();
+	    i = TclGetInt1AtPtr(pc+1);
+	    DECACHE_STACK_INFO();
+	    value2Ptr = TclIncrVar2(interp, namePtr, (Tcl_Obj *) NULL, i,
+		    /*part1NotParsed*/ (opCode == INST_INCR_STK_IMM));
+	    CACHE_STACK_INFO();
+	    if (value2Ptr == NULL) {
+		TRACE_WITH_OBJ(("%s \"%.30s\" %ld => ERROR: ",
+		        opName[opCode], O2S(namePtr), i),
+			Tcl_GetObjResult(interp));
+		result = TCL_ERROR;
+		Tcl_DecrRefCount(namePtr);
+		goto checkForCatch;
+	    }
+	    PUSH_OBJECT(value2Ptr);
+	    TRACE_WITH_OBJ(("%s \"%.30s\" %ld => ",
+	            opName[opCode], O2S(namePtr), i), value2Ptr);
+	    TclDecrRefCount(namePtr);
+	    ADJUST_PC(2);
+
+	case INST_INCR_ARRAY1_IMM:
+	    {
+		Tcl_Obj *elemPtr;
+
+		opnd = TclGetUInt1AtPtr(pc+1);
+		i = TclGetInt1AtPtr(pc+2);
+		elemPtr = POP_OBJECT();
+		DECACHE_STACK_INFO();
+		value2Ptr = TclIncrElementOfIndexedArray(interp, opnd,
+		        elemPtr, i);
+		CACHE_STACK_INFO();
+		if (value2Ptr == NULL) {
+		    TRACE_WITH_OBJ(("incrArray1Imm %u \"%.30s\" (by %ld) => ERROR: ",
+		            opnd, O2S(elemPtr), i),
+			    Tcl_GetObjResult(interp));
+		    Tcl_DecrRefCount(elemPtr);
+		    result = TCL_ERROR;
+		    goto checkForCatch;
+		}
+		PUSH_OBJECT(value2Ptr);
+		TRACE_WITH_OBJ(("incrArray1Imm %u \"%.30s\" (by %ld) => ",
+	                opnd, O2S(elemPtr), i), value2Ptr);
+		Tcl_DecrRefCount(elemPtr);
+	    }
+	    ADJUST_PC(3);
+	    
+	case INST_INCR_ARRAY_STK_IMM:
+	    {
+		Tcl_Obj *elemPtr;
+
+		i = TclGetInt1AtPtr(pc+1);
+		elemPtr = POP_OBJECT();
+		namePtr = POP_OBJECT();
+		DECACHE_STACK_INFO();
+		value2Ptr = TclIncrVar2(interp, namePtr, elemPtr, i,
+		        /*part1NotParsed*/ 0);
+		CACHE_STACK_INFO();
+		if (value2Ptr == NULL) {
+		    TRACE_WITH_OBJ(("incrArrayStkImm \"%.30s(%.30s)\" (by %ld) => ERROR: ",
+		            O2S(namePtr), O2S(elemPtr), i),
+			    Tcl_GetObjResult(interp));
+		    Tcl_DecrRefCount(namePtr);
+		    Tcl_DecrRefCount(elemPtr);
+		    result = TCL_ERROR;
+		    goto checkForCatch;
+		}
+		PUSH_OBJECT(value2Ptr);
+		TRACE_WITH_OBJ(("incrArrayStkImm \"%.30s(%.30s)\" (by %ld) => ",
+	                O2S(namePtr), O2S(elemPtr), i), value2Ptr);
+		Tcl_DecrRefCount(namePtr);
+		Tcl_DecrRefCount(elemPtr);
+	    }
+	    ADJUST_PC(2);
+
+	case INST_JUMP1:
+	    opnd = TclGetInt1AtPtr(pc+1);
+	    TRACE(("jump1 %d => new pc %u\n", opnd,
+		   (unsigned int)(pc + opnd - codePtr->codeStart)));
+	    ADJUST_PC(opnd);
+
+	case INST_JUMP4:
+	    opnd = TclGetInt4AtPtr(pc+1);
+	    TRACE(("jump4 %d => new pc %u\n", opnd,
+		   (unsigned int)(pc + opnd - codePtr->codeStart)));
+	    ADJUST_PC(opnd);
+
+	case INST_JUMP_TRUE4:
+	    opnd = TclGetInt4AtPtr(pc+1);
+	    pcAdjustment = 5;
+	    goto doJumpTrue;
+
+	case INST_JUMP_TRUE1:
+	    opnd = TclGetInt1AtPtr(pc+1);
+	    pcAdjustment = 2;
+	    
+	    doJumpTrue:
+	    {
+		int b;
+		
+		valuePtr = POP_OBJECT();
+		if (valuePtr->typePtr == &tclIntType) {
+		    b = (valuePtr->internalRep.longValue != 0);
+		} else if (valuePtr->typePtr == &tclDoubleType) {
+		    b = (valuePtr->internalRep.doubleValue != 0.0);
+		} else {
+		    result = Tcl_GetBooleanFromObj(interp, valuePtr, &b);
+		    if (result != TCL_OK) {
+			TRACE_WITH_OBJ(("%s %d => ERROR: ", opName[opCode],
+				opnd), Tcl_GetObjResult(interp));
+			Tcl_DecrRefCount(valuePtr);
+			goto checkForCatch;
+		    }
+		}
+		if (b) {
+		    TRACE(("%s %d => %.20s true, new pc %u\n",
+			    opName[opCode], opnd, O2S(valuePtr),
+		            (unsigned int)(pc+opnd - codePtr->codeStart)));
+		    TclDecrRefCount(valuePtr);
+		    ADJUST_PC(opnd);
+		} else {
+		    TRACE(("%s %d => %.20s false\n", opName[opCode], opnd,
+		            O2S(valuePtr)));
+		    TclDecrRefCount(valuePtr);
+		    ADJUST_PC(pcAdjustment);
+		}
+	    }
+	    
+	case INST_JUMP_FALSE4:
+	    opnd = TclGetInt4AtPtr(pc+1);
+	    pcAdjustment = 5;
+	    goto doJumpFalse;
+
+	case INST_JUMP_FALSE1:
+	    opnd = TclGetInt1AtPtr(pc+1);
+	    pcAdjustment = 2;
+	    
+	    doJumpFalse:
+	    {
+		int b;
+		
+		valuePtr = POP_OBJECT();
+		if (valuePtr->typePtr == &tclIntType) {
+		    b = (valuePtr->internalRep.longValue != 0);
+		} else if (valuePtr->typePtr == &tclDoubleType) {
+		    b = (valuePtr->internalRep.doubleValue != 0.0);
+		} else {
+		    result = Tcl_GetBooleanFromObj(interp, valuePtr, &b);
+		    if (result != TCL_OK) {
+			TRACE_WITH_OBJ(("%s %d => ERROR: ", opName[opCode],
+				opnd), Tcl_GetObjResult(interp));
+			Tcl_DecrRefCount(valuePtr);
+			goto checkForCatch;
+		    }
+		}
+		if (b) {
+		    TRACE(("%s %d => %.20s true\n", opName[opCode], opnd,
+		            O2S(valuePtr)));
+		    TclDecrRefCount(valuePtr);
+		    ADJUST_PC(pcAdjustment);
+		} else {
+		    TRACE(("%s %d => %.20s false, new pc %u\n",
+			    opName[opCode], opnd, O2S(valuePtr),
+			   (unsigned int)(pc + opnd - codePtr->codeStart)));
+		    TclDecrRefCount(valuePtr);
+		    ADJUST_PC(opnd);
+		}
+	    }
+	    
+	case INST_LOR:
+	case INST_LAND:
+	    {
+		/*
+		 * Operands must be boolean or numeric. No int->double
+		 * conversions are performed.
+		 */
+		
+		int i1, i2;
+		int iResult;
+		char *s;
+		Tcl_ObjType *t1Ptr, *t2Ptr;
+		
+		value2Ptr = POP_OBJECT();
+		valuePtr  = POP_OBJECT();
+		t1Ptr = valuePtr->typePtr;
+		t2Ptr = value2Ptr->typePtr;
+		
+		if ((t1Ptr == &tclIntType) || (t1Ptr == &tclBooleanType)) {
+		    i1 = (valuePtr->internalRep.longValue != 0);
+		} else if (t1Ptr == &tclDoubleType) {
+		    i1 = (valuePtr->internalRep.doubleValue != 0.0);
+		} else {	/* FAILS IF NULL STRING REP */
+		    s = Tcl_GetStringFromObj(valuePtr, (int *) NULL);
+		    if (TclLooksLikeInt(s)) {
+			result = Tcl_GetLongFromObj((Tcl_Interp *) NULL,
+				valuePtr, &i);
+			i1 = (i != 0);
+		    } else {
+			result = Tcl_GetBooleanFromObj((Tcl_Interp *) NULL,
+				valuePtr, &i1);
+			i1 = (i1 != 0);
+		    }
+		    if (result != TCL_OK) {
+			TRACE(("%s \"%.20s\" => ILLEGAL TYPE %s \n",
+			        opName[opCode], O2S(valuePtr),
+			        (t1Ptr? t1Ptr->name : "null")));
+			IllegalExprOperandType(interp, opCode, valuePtr);
+			Tcl_DecrRefCount(valuePtr);
+			Tcl_DecrRefCount(value2Ptr);
+			goto checkForCatch;
+		    }
+		}
+		
+		if ((t2Ptr == &tclIntType) || (t2Ptr == &tclBooleanType)) {
+		    i2 = (value2Ptr->internalRep.longValue != 0);
+		} else if (t2Ptr == &tclDoubleType) {
+		    i2 = (value2Ptr->internalRep.doubleValue != 0.0);
+		} else {	/* FAILS IF NULL STRING REP */
+		    s = Tcl_GetStringFromObj(value2Ptr, (int *) NULL);
+		    if (TclLooksLikeInt(s)) {
+			result = Tcl_GetLongFromObj((Tcl_Interp *) NULL,
+				value2Ptr, &i);
+			i2 = (i != 0);
+		    } else {
+			result = Tcl_GetBooleanFromObj((Tcl_Interp *) NULL,
+				value2Ptr, &i2);
+			i2 = (i2 != 0);
+		    }
+		    if (result != TCL_OK) {
+			TRACE(("%s \"%.20s\" => ILLEGAL TYPE %s \n",
+			        opName[opCode], O2S(value2Ptr),
+			        (t2Ptr? t2Ptr->name : "null")));
+			IllegalExprOperandType(interp, opCode, value2Ptr);
+			Tcl_DecrRefCount(valuePtr);
+			Tcl_DecrRefCount(value2Ptr);
+			goto checkForCatch;
+		    }
+		}
+		
+		/*
+		 * Reuse the valuePtr object already on stack if possible.
+		 */
+
+		if (opCode == INST_LOR) {
+		    iResult = (i1 || i2);
+		} else {
+		    iResult = (i1 && i2);
+		}
+		if (Tcl_IsShared(valuePtr)) {
+		    PUSH_OBJECT(Tcl_NewLongObj(iResult));
+		    TRACE(("%s %.20s %.20s => %d\n", opName[opCode],
+			   O2S(valuePtr), O2S(value2Ptr), iResult));
+		    TclDecrRefCount(valuePtr);
+		} else {	/* reuse the valuePtr object */
+		    TRACE(("%s %.20s %.20s => %d\n", 
+			   opName[opCode], /* NB: stack top is off by 1 */
+			   O2S(valuePtr), O2S(value2Ptr), iResult));
+		    Tcl_SetLongObj(valuePtr, iResult);
+		    ++stackTop; /* valuePtr now on stk top has right r.c. */
+		}
+		TclDecrRefCount(value2Ptr);
+	    }
+	    ADJUST_PC(1);
+
+	case INST_EQ:
+	case INST_NEQ:
+	case INST_LT:
+	case INST_GT:
+	case INST_LE:
+	case INST_GE:
+	    {
+		/*
+		 * Any type is allowed but the two operands must have the
+	         * same type. We will compute value op value2.
+		 */
+
+		Tcl_ObjType *t1Ptr, *t2Ptr;
+		char *s1 = NULL;   /* Init. avoids compiler warning. */
+		char *s2 = NULL;   /* Init. avoids compiler warning. */
+		long i2 = 0;	   /* Init. avoids compiler warning. */
+		double d1 = 0.0;   /* Init. avoids compiler warning. */
+		double d2 = 0.0;   /* Init. avoids compiler warning. */
+		long iResult = 0;  /* Init. avoids compiler warning. */
+
+		value2Ptr = POP_OBJECT();
+		valuePtr  = POP_OBJECT();
+		t1Ptr = valuePtr->typePtr;
+		t2Ptr = value2Ptr->typePtr;
+		
+		if ((t1Ptr != &tclIntType) && (t1Ptr != &tclDoubleType)) {
+		    s1 = Tcl_GetStringFromObj(valuePtr, &length);
+		    if (TclLooksLikeInt(s1)) { /* FAILS IF NULLS */
+			(void) Tcl_GetLongFromObj((Tcl_Interp *) NULL,
+				valuePtr, &i);
+		    } else {
+			(void) Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
+				valuePtr, &d1);
+		    }
+		    t1Ptr = valuePtr->typePtr;
+		}
+		if ((t2Ptr != &tclIntType) && (t2Ptr != &tclDoubleType)) {
+		    s2 = Tcl_GetStringFromObj(value2Ptr, &length);
+		    if (TclLooksLikeInt(s2)) { /* FAILS IF NULLS */
+			(void) Tcl_GetLongFromObj((Tcl_Interp *) NULL,
+				value2Ptr, &i2);
+		    } else {
+			(void) Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
+				value2Ptr, &d2);
+		    }
+		    t2Ptr = value2Ptr->typePtr;
+		}
+
+		if (((t1Ptr != &tclIntType) && (t1Ptr != &tclDoubleType))
+		        || ((t2Ptr != &tclIntType) && (t2Ptr != &tclDoubleType))) {
+		    /*
+		     * One operand is not numeric. Compare as strings.
+		     * THIS FAILS IF AN OBJECT'S STRING REP CONTAINS NULLS.
+		     */
+		    int cmpValue;
+		    s1 = TclGetStringFromObj(valuePtr, &length);
+		    s2 = TclGetStringFromObj(value2Ptr, &length);
+		    cmpValue = strcmp(s1, s2);
+		    switch (opCode) {
+		    case INST_EQ:
+			iResult = (cmpValue == 0);
+			break;
+		    case INST_NEQ:
+			iResult = (cmpValue != 0);
+			break;
+		    case INST_LT:
+			iResult = (cmpValue < 0);
+			break;
+		    case INST_GT:
+			iResult = (cmpValue > 0);
+			break;
+		    case INST_LE:
+			iResult = (cmpValue <= 0);
+			break;
+		    case INST_GE:
+			iResult = (cmpValue >= 0);
+			break;
+		    }
+		} else if ((t1Ptr == &tclDoubleType)
+		        || (t2Ptr == &tclDoubleType)) {
+		    /*
+		     * Compare as doubles.
+		     */
+		    if (t1Ptr == &tclDoubleType) {
+			d1 = valuePtr->internalRep.doubleValue;
+			if (t2Ptr == &tclIntType) {
+			    d2 = value2Ptr->internalRep.longValue;
+			} else {
+			    d2 = value2Ptr->internalRep.doubleValue;
+			}
+		    } else {	/* t1Ptr is int, t2Ptr is double */
+			d1 = valuePtr->internalRep.longValue;
+			d2 = value2Ptr->internalRep.doubleValue;
+		    }
+		    switch (opCode) {
+		    case INST_EQ:
+			iResult = d1 == d2;
+			break;
+		    case INST_NEQ:
+			iResult = d1 != d2;
+			break;
+		    case INST_LT:
+			iResult = d1 < d2;
+			break;
+		    case INST_GT:
+			iResult = d1 > d2;
+			break;
+		    case INST_LE:
+			iResult = d1 <= d2;
+			break;
+		    case INST_GE:
+			iResult = d1 >= d2;
+			break;
+		    }
+		} else {
+		    /*
+		     * Compare as ints.
+		     */
+		    i  = valuePtr->internalRep.longValue;
+		    i2 = value2Ptr->internalRep.longValue;
+		    switch (opCode) {
+		    case INST_EQ:
+			iResult = i == i2;
+			break;
+		    case INST_NEQ:
+			iResult = i != i2;
+			break;
+		    case INST_LT:
+			iResult = i < i2;
+			break;
+		    case INST_GT:
+			iResult = i > i2;
+			break;
+		    case INST_LE:
+			iResult = i <= i2;
+			break;
+		    case INST_GE:
+			iResult = i >= i2;
+			break;
+		    }
+		}
+
+		/*
+		 * Reuse the valuePtr object already on stack if possible.
+		 */
+		
+		if (Tcl_IsShared(valuePtr)) {
+		    PUSH_OBJECT(Tcl_NewLongObj(iResult));
+		    TRACE(("%s %.20s %.20s => %ld\n", opName[opCode],
+		        O2S(valuePtr), O2S(value2Ptr), iResult));
+		    TclDecrRefCount(valuePtr);
+		} else {	/* reuse the valuePtr object */
+		    TRACE(("%s %.20s %.20s => %ld\n",
+			opName[opCode], /* NB: stack top is off by 1 */
+		        O2S(valuePtr), O2S(value2Ptr), iResult));
+		    Tcl_SetLongObj(valuePtr, iResult);
+		    ++stackTop; /* valuePtr now on stk top has right r.c. */
+		}
+		TclDecrRefCount(value2Ptr);
+	    }
+	    ADJUST_PC(1);
+	    
+	case INST_MOD:
+	case INST_LSHIFT:
+	case INST_RSHIFT:
+	case INST_BITOR:
+	case INST_BITXOR:
+	case INST_BITAND:
+	    {
+		/*
+		 * Only integers are allowed. We compute value op value2.
+		 */
+
+		long i2, rem, negative;
+		long iResult = 0; /* Init. avoids compiler warning. */
+		
+		value2Ptr = POP_OBJECT();
+		valuePtr  = POP_OBJECT(); 
+		if (valuePtr->typePtr == &tclIntType) {
+		    i = valuePtr->internalRep.longValue;
+		} else {	/* try to convert to int */
+		    result = Tcl_GetLongFromObj((Tcl_Interp *) NULL,
+			    valuePtr, &i);
+		    if (result != TCL_OK) {
+			TRACE(("%s %.20s %.20s => ILLEGAL 1st TYPE %s\n",
+			      opName[opCode], O2S(valuePtr), O2S(value2Ptr),
+			      (valuePtr->typePtr?
+				   valuePtr->typePtr->name : "null")));
+			IllegalExprOperandType(interp, opCode, valuePtr);
+			Tcl_DecrRefCount(valuePtr);
+			Tcl_DecrRefCount(value2Ptr);
+			goto checkForCatch;
+		    }
+		}
+		if (value2Ptr->typePtr == &tclIntType) {
+		    i2 = value2Ptr->internalRep.longValue;
+		} else {
+		    result = Tcl_GetLongFromObj((Tcl_Interp *) NULL,
+			    value2Ptr, &i2);
+		    if (result != TCL_OK) {
+			TRACE(("%s %.20s %.20s => ILLEGAL 2nd TYPE %s\n",
+			      opName[opCode], O2S(valuePtr), O2S(value2Ptr),
+			      (value2Ptr->typePtr?
+				   value2Ptr->typePtr->name : "null")));
+			IllegalExprOperandType(interp, opCode, value2Ptr);
+			Tcl_DecrRefCount(valuePtr);
+			Tcl_DecrRefCount(value2Ptr);
+			goto checkForCatch;
+		    }
+		}
+
+		switch (opCode) {
+		case INST_MOD:
+		    /*
+		     * This code is tricky: C doesn't guarantee much about
+		     * the quotient or remainder, but Tcl does. The
+		     * remainder always has the same sign as the divisor and
+		     * a smaller absolute value.
+		     */
+		    if (i2 == 0) {
+			TRACE(("mod %ld %ld => DIVIDE BY ZERO\n", i, i2));
+			Tcl_DecrRefCount(valuePtr);
+			Tcl_DecrRefCount(value2Ptr);
+			goto divideByZero;
+		    }
+		    negative = 0;
+		    if (i2 < 0) {
+			i2 = -i2;
+			i = -i;
+			negative = 1;
+		    }
+		    rem  = i % i2;
+		    if (rem < 0) {
+			rem += i2;
+		    }
+		    if (negative) {
+			rem = -rem;
+		    }
+		    iResult = rem;
+		    break;
+		case INST_LSHIFT:
+		    iResult = i << i2;
+		    break;
+		case INST_RSHIFT:
+		    /*
+		     * The following code is a bit tricky: it ensures that
+		     * right shifts propagate the sign bit even on machines
+		     * where ">>" won't do it by default.
+		     */
+		    if (i < 0) {
+			iResult = ~((~i) >> i2);
+		    } else {
+			iResult = i >> i2;
+		    }
+		    break;
+		case INST_BITOR:
+		    iResult = i | i2;
+		    break;
+		case INST_BITXOR:
+		    iResult = i ^ i2;
+		    break;
+		case INST_BITAND:
+		    iResult = i & i2;
+		    break;
+		}
+
+		/*
+		 * Reuse the valuePtr object already on stack if possible.
+		 */
+		
+		if (Tcl_IsShared(valuePtr)) {
+		    PUSH_OBJECT(Tcl_NewLongObj(iResult));
+		    TRACE(("%s %ld %ld => %ld\n", opName[opCode], i, i2,
+			   iResult));
+		    TclDecrRefCount(valuePtr);
+		} else {	/* reuse the valuePtr object */
+		    TRACE(("%s %ld %ld => %ld\n", opName[opCode], i, i2,
+		        iResult)); /* NB: stack top is off by 1 */
+		    Tcl_SetLongObj(valuePtr, iResult);
+		    ++stackTop; /* valuePtr now on stk top has right r.c. */
+		}
+		TclDecrRefCount(value2Ptr);
+	    }
+	    ADJUST_PC(1);
+	    
+	case INST_ADD:
+	case INST_SUB:
+	case INST_MULT:
+	case INST_DIV:
+	    {
+		/*
+		 * Operands must be numeric and ints get converted to floats
+		 * if necessary. We compute value op value2.
+		 */
+
+		Tcl_ObjType *t1Ptr, *t2Ptr;
+		long i2, quot, rem;
+		double d1, d2;
+		long iResult = 0;     /* Init. avoids compiler warning. */
+		double dResult = 0.0; /* Init. avoids compiler warning. */
+		int doDouble = 0;     /* 1 if doing floating arithmetic */
+		
+		value2Ptr = POP_OBJECT();
+		valuePtr  = POP_OBJECT();
+		t1Ptr = valuePtr->typePtr;
+		t2Ptr = value2Ptr->typePtr;
+		
+		if (t1Ptr == &tclIntType) {
+		    i  = valuePtr->internalRep.longValue;
+		} else if (t1Ptr == &tclDoubleType) {
+		    d1 = valuePtr->internalRep.doubleValue;
+		} else {	     /* try to convert; FAILS IF NULLS */
+		    char *s = Tcl_GetStringFromObj(valuePtr, &length);
+		    if (TclLooksLikeInt(s)) {
+			result = Tcl_GetLongFromObj((Tcl_Interp *) NULL,
+				valuePtr, &i);
+		    } else {
+			result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
+				valuePtr, &d1);
+		    }
+		    if (result != TCL_OK) {
+			TRACE(("%s %.20s %.20s => ILLEGAL 1st TYPE %s\n",
+			       opName[opCode], s, O2S(value2Ptr),
+			       (valuePtr->typePtr?
+				    valuePtr->typePtr->name : "null")));
+			IllegalExprOperandType(interp, opCode, valuePtr);
+			Tcl_DecrRefCount(valuePtr);
+			Tcl_DecrRefCount(value2Ptr);
+			goto checkForCatch;
+		    }
+		    t1Ptr = valuePtr->typePtr;
+		}
+		
+		if (t2Ptr == &tclIntType) {
+		    i2 = value2Ptr->internalRep.longValue;
+		} else if (t2Ptr == &tclDoubleType) {
+		    d2 = value2Ptr->internalRep.doubleValue;
+		} else {	     /* try to convert; FAILS IF NULLS */
+		    char *s = Tcl_GetStringFromObj(value2Ptr, &length);
+		    if (TclLooksLikeInt(s)) {
+			result = Tcl_GetLongFromObj((Tcl_Interp *) NULL,
+				value2Ptr, &i2);
+		    } else {
+			result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
+				value2Ptr, &d2);
+		    }
+		    if (result != TCL_OK) {
+			TRACE(("%s %.20s %.20s => ILLEGAL 2nd TYPE %s\n",
+			       opName[opCode], O2S(valuePtr), s,
+			       (value2Ptr->typePtr?
+				    value2Ptr->typePtr->name : "null")));
+			IllegalExprOperandType(interp, opCode, value2Ptr);
+			Tcl_DecrRefCount(valuePtr);
+			Tcl_DecrRefCount(value2Ptr);
+			goto checkForCatch;
+		    }
+		    t2Ptr = value2Ptr->typePtr;
+		}
+
+		if ((t1Ptr == &tclDoubleType) || (t2Ptr == &tclDoubleType)) {
+		    /*
+		     * Do double arithmetic.
+		     */
+		    doDouble = 1;
+		    if (t1Ptr == &tclIntType) {
+			d1 = i;       /* promote value 1 to double */
+		    } else if (t2Ptr == &tclIntType) {
+			d2 = i2;      /* promote value 2 to double */
+		    }
+		    switch (opCode) {
+		    case INST_ADD:
+			dResult = d1 + d2;
+			break;
+		    case INST_SUB:
+			dResult = d1 - d2;
+			break;
+		    case INST_MULT:
+			dResult = d1 * d2;
+			break;
+		    case INST_DIV:
+			if (d2 == 0.0) {
+			    TRACE(("div %.6g %.6g => DIVIDE BY ZERO\n",
+				   d1, d2));
+			    Tcl_DecrRefCount(valuePtr);
+			    Tcl_DecrRefCount(value2Ptr);
+			    goto divideByZero;
+			}
+			dResult = d1 / d2;
+			break;
+		    }
+		    
+		    /*
+		     * Check now for IEEE floating-point error.
+		     */
+		    
+		    if (IS_NAN(dResult) || IS_INF(dResult)) {
+			TRACE(("%s %.20s %.20s => IEEE FLOATING PT ERROR\n",
+			       opName[opCode], O2S(valuePtr), O2S(value2Ptr)));
+			TclExprFloatError(interp, dResult);
+			result = TCL_ERROR;
+			Tcl_DecrRefCount(valuePtr);
+			Tcl_DecrRefCount(value2Ptr);
+			goto checkForCatch;
+		    }
+		} else {
+		    /*
+		     * Do integer arithmetic.
+		     */
+		    switch (opCode) {
+		    case INST_ADD:
+			iResult = i + i2;
+			break;
+		    case INST_SUB:
+			iResult = i - i2;
+			break;
+		    case INST_MULT:
+			iResult = i * i2;
+			break;
+		    case INST_DIV:
+			/*
+			 * This code is tricky: C doesn't guarantee much
+			 * about the quotient or remainder, but Tcl does.
+			 * The remainder always has the same sign as the
+			 * divisor and a smaller absolute value.
+			 */
+			if (i2 == 0) {
+			    TRACE(("div %ld %ld => DIVIDE BY ZERO\n",
+				    i, i2));
+			    Tcl_DecrRefCount(valuePtr);
+			    Tcl_DecrRefCount(value2Ptr);
+			    goto divideByZero;
+			}
+			if (i2 < 0) {
+			    i2 = -i2;
+			    i = -i;
+			}
+			quot = i / i2;
+			rem  = i % i2;
+			if (rem < 0) {
+			    quot -= 1;
+			}
+			iResult = quot;
+			break;
+		    }
+		}
+
+		/*
+		 * Reuse the valuePtr object already on stack if possible.
+		 */
+		
+		if (Tcl_IsShared(valuePtr)) {
+		    if (doDouble) {
+			PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
+			TRACE(("%s %.6g %.6g => %.6g\n", opName[opCode],
+			       d1, d2, dResult));
+		    } else {
+			PUSH_OBJECT(Tcl_NewLongObj(iResult));
+			TRACE(("%s %ld %ld => %ld\n", opName[opCode],
+			       i, i2, iResult));
+		    } 
+		    TclDecrRefCount(valuePtr);
+		} else {	    /* reuse the valuePtr object */
+		    if (doDouble) { /* NB: stack top is off by 1 */
+			TRACE(("%s %.6g %.6g => %.6g\n", opName[opCode],
+			       d1, d2, dResult));
+			Tcl_SetDoubleObj(valuePtr, dResult);
+		    } else {
+			TRACE(("%s %ld %ld => %ld\n", opName[opCode],
+			       i, i2, iResult));
+			Tcl_SetLongObj(valuePtr, iResult);
+		    }
+		    ++stackTop; /* valuePtr now on stk top has right r.c. */
+		}
+		TclDecrRefCount(value2Ptr);
+	    }
+	    ADJUST_PC(1);
+	    
+	case INST_UPLUS:
+	    {
+	        /*
+	         * Operand must be numeric.
+	         */
+
+		double d;
+		Tcl_ObjType *tPtr;
+		
+		valuePtr = stackPtr[stackTop].o;
+		tPtr = valuePtr->typePtr;
+		if ((tPtr != &tclIntType) && (tPtr != &tclDoubleType)) {
+		    char *s = Tcl_GetStringFromObj(valuePtr, (int *) NULL);
+		    if (TclLooksLikeInt(s)) { /* FAILS IF NULLS */
+			result = Tcl_GetLongFromObj((Tcl_Interp *) NULL,
+				valuePtr, &i);
+		    } else {
+			result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
+				valuePtr, &d);
+		    }
+		    if (result != TCL_OK) { 
+			TRACE(("%s \"%.20s\" => ILLEGAL TYPE %s \n",
+			        opName[opCode], s,
+			        (tPtr? tPtr->name : "null")));
+			IllegalExprOperandType(interp, opCode, valuePtr);
+			goto checkForCatch;
+		    }
+		}
+		TRACE_WITH_OBJ(("uplus %s => ", O2S(valuePtr)), valuePtr);
+	    }
+	    ADJUST_PC(1);
+	    
+	case INST_UMINUS:
+	case INST_LNOT:
+	    {
+		/*
+		 * The operand must be numeric. If the operand object is
+		 * unshared modify it directly, otherwise create a copy to
+		 * modify: this is "copy on write". free any old string
+		 * representation since it is now invalid.
+		 */
+		
+		double d;
+		Tcl_ObjType *tPtr;
+		
+		valuePtr = POP_OBJECT();
+		tPtr = valuePtr->typePtr;
+		if ((tPtr != &tclIntType) && (tPtr != &tclDoubleType)) {
+		    char *s = Tcl_GetStringFromObj(valuePtr, (int *) NULL);
+		    if (TclLooksLikeInt(s)) { /* FAILS IF NULLS */
+			result = Tcl_GetLongFromObj((Tcl_Interp *) NULL,
+				valuePtr, &i);
+		    } else {
+			result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
+				valuePtr, &d);
+		    }
+		    if (result != TCL_OK) {
+			TRACE(("%s \"%.20s\" => ILLEGAL TYPE %s\n",
+			        opName[opCode], s,
+			       (tPtr? tPtr->name : "null")));
+			IllegalExprOperandType(interp, opCode, valuePtr);
+			Tcl_DecrRefCount(valuePtr);
+			goto checkForCatch;
+		    }
+		    tPtr = valuePtr->typePtr;
+		}
+		
+		if (Tcl_IsShared(valuePtr)) {
+		    /*
+		     * Create a new object.
+		     */
+		    if (tPtr == &tclIntType) {
+			i = valuePtr->internalRep.longValue;
+			objPtr = Tcl_NewLongObj(
+			        (opCode == INST_UMINUS)? -i : !i);
+			TRACE_WITH_OBJ(("%s %ld => ", opName[opCode], i),
+		                objPtr); /* NB: stack top is off by 1 */
+		    } else {
+			d = valuePtr->internalRep.doubleValue;
+			if (opCode == INST_UMINUS) {
+			    objPtr = Tcl_NewDoubleObj(-d);
+			} else {
+			    /*
+			     * Should be able to use "!d", but apparently
+			     * some compilers can't handle it.
+			     */
+			    objPtr = Tcl_NewLongObj((d==0.0)? 1 : 0);
+			}
+			TRACE_WITH_OBJ(("%s %.6g => ", opName[opCode], d),
+		                objPtr); /* NB: stack top is off by 1 */
+		    }
+		    PUSH_OBJECT(objPtr);
+		    TclDecrRefCount(valuePtr);
+		} else {
+		    /*
+		     * valuePtr is unshared. Modify it directly.
+		     */
+		    if (tPtr == &tclIntType) {
+			i = valuePtr->internalRep.longValue;
+			Tcl_SetLongObj(valuePtr,
+			        (opCode == INST_UMINUS)? -i : !i);
+			TRACE_WITH_OBJ(("%s %ld => ", opName[opCode], i),
+		                valuePtr); /* NB: stack top is off by 1 */
+		    } else {
+			d = valuePtr->internalRep.doubleValue;
+			if (opCode == INST_UMINUS) {
+			    Tcl_SetDoubleObj(valuePtr, -d);
+			} else {
+			    /*
+			     * Should be able to use "!d", but apparently
+			     * some compilers can't handle it.
+			     */
+			    Tcl_SetLongObj(valuePtr, (d==0.0)? 1 : 0);
+			}
+			TRACE_WITH_OBJ(("%s %.6g => ", opName[opCode], d),
+		                valuePtr); /* NB: stack top is off by 1 */
+		    }
+		    ++stackTop; /* valuePtr now on stk top has right r.c. */
+		}
+	    }
+	    ADJUST_PC(1);
+	    
+	case INST_BITNOT:
+	    {
+		/*
+		 * The operand must be an integer. If the operand object is
+		 * unshared modify it directly, otherwise modify a copy. 
+		 * Free any old string representation since it is now
+		 * invalid.
+		 */
+		
+		Tcl_ObjType *tPtr;
+		
+		valuePtr = POP_OBJECT();
+		tPtr = valuePtr->typePtr;
+		if (tPtr != &tclIntType) {
+		    result = Tcl_GetLongFromObj((Tcl_Interp *) NULL,
+			    valuePtr, &i);
+		    if (result != TCL_OK) {   /* try to convert to double */
+			TRACE(("bitnot \"%.20s\" => ILLEGAL TYPE %s\n",
+			       O2S(valuePtr), (tPtr? tPtr->name : "null")));
+			IllegalExprOperandType(interp, opCode, valuePtr);
+			Tcl_DecrRefCount(valuePtr);
+			goto checkForCatch;
+		    }
+		}
+		
+		i = valuePtr->internalRep.longValue;
+		if (Tcl_IsShared(valuePtr)) {
+		    PUSH_OBJECT(Tcl_NewLongObj(~i));
+		    TRACE(("bitnot 0x%lx => (%lu)\n", i, ~i));
+		    TclDecrRefCount(valuePtr);
+		} else {
+		    /*
+		     * valuePtr is unshared. Modify it directly.
+		     */
+		    Tcl_SetLongObj(valuePtr, ~i);
+		    ++stackTop; /* valuePtr now on stk top has right r.c. */
+		    TRACE(("bitnot 0x%lx => (%lu)\n", i, ~i));
+		}
+	    }
+	    ADJUST_PC(1);
+	    
+	case INST_CALL_BUILTIN_FUNC1:
+	    opnd = TclGetUInt1AtPtr(pc+1);
+	    {
+		/*
+		 * Call one of the built-in Tcl math functions.
+		 */
+
+		BuiltinFunc *mathFuncPtr;
+
+		if ((opnd < 0) || (opnd > LAST_BUILTIN_FUNC)) {
+		    TRACE(("UNRECOGNIZED BUILTIN FUNC CODE %d\n", opnd));
+		    panic("TclExecuteByteCode: unrecognized builtin function code %d", opnd);
+		}
+		mathFuncPtr = &(builtinFuncTable[opnd]);
+		DECACHE_STACK_INFO();
+		tcl_MathInProgress++;
+		result = (*mathFuncPtr->proc)(interp, eePtr,
+		        mathFuncPtr->clientData);
+		tcl_MathInProgress--;
+		CACHE_STACK_INFO();
+		if (result != TCL_OK) {
+		    goto checkForCatch;
+		}
+		TRACE_WITH_OBJ(("callBuiltinFunc1 %d => ", opnd),
+		        stackPtr[stackTop].o);
+	    }
+	    ADJUST_PC(2);
+		    
+	case INST_CALL_FUNC1:
+	    opnd = TclGetUInt1AtPtr(pc+1);
+	    {
+		/*
+		 * Call a non-builtin Tcl math function previously
+		 * registered by a call to Tcl_CreateMathFunc.
+		 */
+		
+		int objc = opnd;   /* Number of arguments. The function name
+				    * is the 0-th argument. */
+		Tcl_Obj **objv;	   /* The array of arguments. The function
+				    * name is objv[0]. */
+		
+		objv = &(stackPtr[stackTop - (objc-1)].o); /* "objv[0]" */
+		DECACHE_STACK_INFO();
+		tcl_MathInProgress++;
+		result = ExprCallMathFunc(interp, eePtr, objc, objv);
+		tcl_MathInProgress--;
+		CACHE_STACK_INFO();
+		if (result != TCL_OK) {
+		    goto checkForCatch;
+		}
+		TRACE_WITH_OBJ(("callFunc1 %d => ", objc),
+		        stackPtr[stackTop].o);
+		ADJUST_PC(2);
+	    }
+
+	case INST_TRY_CVT_TO_NUMERIC:
+	    {
+		/*
+		 * Try to convert the topmost stack object to an int or
+		 * double object. This is done in order to support Tcl's
+		 * policy of interpreting operands if at all possible as
+		 * first integers, else floating-point numbers.
+		 */
+		
+		double d;
+		char *s;
+		Tcl_ObjType *tPtr;
+		int converted, shared;
+
+		valuePtr = stackPtr[stackTop].o;
+		tPtr = valuePtr->typePtr;
+		converted = 0;
+		if ((tPtr != &tclIntType) && (tPtr != &tclDoubleType)) {
+		    s = Tcl_GetStringFromObj(valuePtr, (int *) NULL);
+		    if (TclLooksLikeInt(s)) { /* FAILS IF NULLS */
+			result = Tcl_GetLongFromObj((Tcl_Interp *) NULL,
+				valuePtr, &i);
+		    } else {
+			result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
+				valuePtr, &d);
+		    }
+		    if (result == TCL_OK) {
+			converted = 1;
+		    }
+		    result = TCL_OK; /* reset the result variable */
+		    tPtr = valuePtr->typePtr;
+		}
+
+		/*
+		 * Ensure that the topmost stack object, if numeric, has a
+		 * string rep the same as the formatted version of its
+		 * internal rep. This is used, e.g., to make sure that "expr
+		 * {0001}" yields "1", not "0001". We implement this by
+		 * _discarding_ the string rep since we know it will be
+		 * regenerated, if needed later, by formatting the internal
+		 * rep's value. Also check if there has been an IEEE
+		 * floating point error.
+		 */
+
+		if ((tPtr == &tclIntType) || (tPtr == &tclDoubleType)) {
+		    shared = 0;
+		    if (Tcl_IsShared(valuePtr)) {
+			shared = 1;
+			if (tPtr == &tclIntType) {
+			    i = valuePtr->internalRep.longValue;
+			    objPtr = Tcl_NewLongObj(i);
+			} else {
+			    d = valuePtr->internalRep.doubleValue;
+			    objPtr = Tcl_NewDoubleObj(d);
+			}
+			Tcl_IncrRefCount(objPtr);
+			TclDecrRefCount(valuePtr);
+			valuePtr = objPtr;
+			tPtr = valuePtr->typePtr;
+		    } else {
+			Tcl_InvalidateStringRep(valuePtr);
+		    }
+		    stackPtr[stackTop].o = valuePtr;
+		
+		    if (tPtr == &tclDoubleType) {
+			d = valuePtr->internalRep.doubleValue;
+			if (IS_NAN(d) || IS_INF(d)) {
+			    TRACE(("tryCvtToNumeric \"%.20s\" => IEEE FLOATING PT ERROR\n",
+			           O2S(valuePtr)));
+			    TclExprFloatError(interp, d);
+			    result = TCL_ERROR;
+			    goto checkForCatch;
+			}
+		    }
+		    shared = shared;		/* lint, shared not used. */
+		    converted = converted;	/* lint, converted not used. */
+		    TRACE(("tryCvtToNumeric \"%.20s\" => numeric, %s, %s\n",
+			   O2S(valuePtr),
+			   (converted? "converted" : "not converted"),
+			   (shared? "shared" : "not shared")));
+		} else {
+		    TRACE(("tryCvtToNumeric \"%.20s\" => not numeric\n",
+			   O2S(valuePtr)));
+		}
+	    }
+	    ADJUST_PC(1);
+
+	case INST_BREAK:
+	    /*
+	     * First reset the interpreter's result. Then find the closest
+	     * enclosing loop or catch exception range, if any. If a loop is
+	     * found, terminate its execution. If the closest is a catch
+	     * exception range, jump to its catchOffset. If no enclosing
+	     * range is found, stop execution and return TCL_BREAK.
+	     */
+
+	    Tcl_ResetResult(interp);
+	    rangePtr = TclGetExceptionRangeForPc(pc, /*catchOnly*/ 0,
+		    codePtr);
+	    if (rangePtr == NULL) {
+		TRACE(("break => no encl. loop or catch, returning TCL_BREAK\n"));
+		result = TCL_BREAK;
+		goto abnormalReturn; /* no catch exists to check */
+	    }
+	    switch (rangePtr->type) {
+	    case LOOP_EXCEPTION_RANGE:
+		result = TCL_OK;
+		TRACE(("break => range at %d, new pc %d\n",
+		       rangePtr->codeOffset, rangePtr->breakOffset));
+		break;
+	    case CATCH_EXCEPTION_RANGE:
+		result = TCL_BREAK;
+		TRACE(("break => ...\n"));
+		goto processCatch; /* it will use rangePtr */
+	    default:
+		panic("TclExecuteByteCode: unrecognized ExceptionRange type %d\n", rangePtr->type);
+	    }
+	    pc = (codePtr->codeStart + rangePtr->breakOffset);
+	    continue;	/* restart outer instruction loop at pc */
+
+	case INST_CONTINUE:
+            /*
+	     * Find the closest enclosing loop or catch exception range,
+	     * if any. If a loop is found, skip to its next iteration.
+	     * If the closest is a catch exception range, jump to its
+	     * catchOffset. If no enclosing range is found, stop
+	     * execution and return TCL_CONTINUE.
+	     */
+
+	    Tcl_ResetResult(interp);
+	    rangePtr = TclGetExceptionRangeForPc(pc, /*catchOnly*/ 0,
+		    codePtr);
+	    if (rangePtr == NULL) {
+		TRACE(("continue => no encl. loop or catch, returning TCL_CONTINUE\n"));
+		result = TCL_CONTINUE;
+		goto abnormalReturn;
+	    }
+	    switch (rangePtr->type) {
+	    case LOOP_EXCEPTION_RANGE:
+		if (rangePtr->continueOffset == -1) {
+		    TRACE(("continue => loop w/o continue, checking for catch\n"));
+		    goto checkForCatch;
+		} else {
+		    result = TCL_OK;
+		    TRACE(("continue => range at %d, new pc %d\n",
+			   rangePtr->codeOffset, rangePtr->continueOffset));
+		}
+		break;
+	    case CATCH_EXCEPTION_RANGE:
+		result = TCL_CONTINUE;
+		TRACE(("continue => ...\n"));
+		goto processCatch; /* it will use rangePtr */
+	    default:
+		panic("TclExecuteByteCode: unrecognized ExceptionRange type %d\n", rangePtr->type);
+	    }
+	    pc = (codePtr->codeStart + rangePtr->continueOffset);
+	    continue;	/* restart outer instruction loop at pc */
+
+	case INST_FOREACH_START4:
+	    opnd = TclGetUInt4AtPtr(pc+1);
+	    {
+	        /*
+		 * Initialize the temporary local var that holds the count
+		 * of the number of iterations of the loop body to -1.
+		 */
+
+		ForeachInfo *infoPtr = (ForeachInfo *)
+		    codePtr->auxDataArrayPtr[opnd].clientData;
+		int iterTmpIndex = infoPtr->loopIterNumTmp;
+		CallFrame *varFramePtr = iPtr->varFramePtr;
+		Var *compiledLocals = varFramePtr->compiledLocals;
+		Var *iterVarPtr;
+		Tcl_Obj *oldValuePtr;
+
+		iterVarPtr = &(compiledLocals[iterTmpIndex]);
+		oldValuePtr = iterVarPtr->value.objPtr;
+		if (oldValuePtr == NULL) {
+		    iterVarPtr->value.objPtr = Tcl_NewLongObj(-1);
+		    Tcl_IncrRefCount(iterVarPtr->value.objPtr);
+		} else {
+		    Tcl_SetLongObj(oldValuePtr, -1);
+		}
+		TclSetVarScalar(iterVarPtr);
+		TclClearVarUndefined(iterVarPtr);
+		TRACE(("foreach_start4 %u => loop iter count temp %d\n", 
+		        opnd, iterTmpIndex));
+	    }
+	    ADJUST_PC(5);
+	
+	case INST_FOREACH_STEP4:
+	    opnd = TclGetUInt4AtPtr(pc+1);
+	    {
+	        /*
+		 * "Step" a foreach loop (i.e., begin its next iteration) by
+		 * assigning the next value list element to each loop var.
+		 */
+
+		ForeachInfo *infoPtr = (ForeachInfo *)
+		    codePtr->auxDataArrayPtr[opnd].clientData;
+		ForeachVarList *varListPtr;
+		int numLists = infoPtr->numLists;
+		int iterTmpIndex = infoPtr->loopIterNumTmp;
+		CallFrame *varFramePtr = iPtr->varFramePtr;
+		Var *compiledLocals = varFramePtr->compiledLocals;
+		int iterNum, listTmpIndex, listLen, numVars;
+		int varIndex, valIndex, j;
+		Tcl_Obj *listPtr, *elemPtr, *oldValuePtr;
+		List *listRepPtr;
+		Var *iterVarPtr, *listVarPtr;
+		int continueLoop = 0;
+
+		/*
+		 * Increment the temp holding the loop iteration number.
+		 */
+
+		iterVarPtr = &(compiledLocals[iterTmpIndex]);
+		oldValuePtr = iterVarPtr->value.objPtr;
+		iterNum = (oldValuePtr->internalRep.longValue + 1);
+		Tcl_SetLongObj(oldValuePtr, iterNum);
+		
+		/*
+		 * Check whether all value lists are exhausted and we should
+		 * stop the loop.
+		 */
+
+		listTmpIndex = infoPtr->firstListTmp;
+		for (i = 0;  i < numLists;  i++) {
+		    varListPtr = infoPtr->varLists[i];
+		    numVars = varListPtr->numVars;
+
+		    listVarPtr = &(compiledLocals[listTmpIndex]);
+		    listPtr = listVarPtr->value.objPtr;
+		    result = Tcl_ListObjLength(interp, listPtr, &listLen);
+		    if (result != TCL_OK) {
+			TRACE_WITH_OBJ(("foreach_step4 %u => ERROR converting list %ld, \"%s\": ",
+			        opnd, i, O2S(listPtr)),
+				Tcl_GetObjResult(interp));
+			goto checkForCatch;
+		    }
+		    if (listLen > (iterNum * numVars)) {
+			continueLoop = 1;
+		    }
+		    listTmpIndex++;
+		}
+
+		/*
+		 * If some var in some var list still has a remaining list
+		 * element iterate one more time. Assign to var the next
+		 * element from its value list. We already checked above
+		 * that each list temp holds a valid list object.
+		 */
+		
+		if (continueLoop) {
+		    listTmpIndex = infoPtr->firstListTmp;
+		    for (i = 0;  i < numLists;  i++) {
+			varListPtr = infoPtr->varLists[i];
+			numVars = varListPtr->numVars;
+
+			listVarPtr = &(compiledLocals[listTmpIndex]);
+			listPtr = listVarPtr->value.objPtr;
+			listRepPtr = (List *)
+			        listPtr->internalRep.otherValuePtr;
+			listLen = listRepPtr->elemCount;
+			
+			valIndex = (iterNum * numVars);
+			for (j = 0;  j < numVars;  j++) {
+			    int setEmptyStr = 0;
+			    if (valIndex >= listLen) {
+				setEmptyStr = 1;
+				elemPtr = Tcl_NewObj();
+			    } else {
+				elemPtr = listRepPtr->elements[valIndex];
+			    }
+			    
+			    varIndex = varListPtr->varIndexes[j];
+			    DECACHE_STACK_INFO();
+			    value2Ptr = TclSetIndexedScalar(interp,
+			           varIndex, elemPtr, /*leaveErrorMsg*/ 1);
+			    CACHE_STACK_INFO();
+			    if (value2Ptr == NULL) {
+				TRACE_WITH_OBJ(("foreach_step4 %u => ERROR init. index temp %d: ",
+				       opnd, varIndex),
+				       Tcl_GetObjResult(interp));
+				if (setEmptyStr) {
+				    Tcl_DecrRefCount(elemPtr); /* unneeded */
+				}
+				result = TCL_ERROR;
+				goto checkForCatch;
+			    }
+			    valIndex++;
+			}
+			listTmpIndex++;
+		    }
+		}
+		
+		/*
+		 * Now push a "1" object if at least one value list had a
+		 * remaining element and the loop should continue.
+		 * Otherwise push "0".
+		 */
+
+		PUSH_OBJECT(Tcl_NewLongObj(continueLoop));
+		TRACE(("foreach_step4 %u => %d lists, iter %d, %s loop\n", 
+		        opnd, numLists, iterNum,
+		        (continueLoop? "continue" : "exit")));
+	    }
+	    ADJUST_PC(5);
+
+	case INST_BEGIN_CATCH4:
+	    /*
+	     * Record start of the catch command with exception range index
+	     * equal to the operand. Push the current stack depth onto the
+	     * special catch stack.
+	     */
+	    catchStackPtr[++catchTop] = stackTop;
+	    TRACE(("beginCatch4 %u => catchTop=%d, stackTop=%d\n",
+		    TclGetUInt4AtPtr(pc+1), catchTop, stackTop));
+	    ADJUST_PC(5);
+
+	case INST_END_CATCH:
+	    catchTop--;
+	    result = TCL_OK;
+	    TRACE(("endCatch => catchTop=%d\n", catchTop));
+	    ADJUST_PC(1);
+
+	case INST_PUSH_RESULT:
+	    PUSH_OBJECT(Tcl_GetObjResult(interp));
+	    TRACE_WITH_OBJ(("pushResult => "), Tcl_GetObjResult(interp));
+	    ADJUST_PC(1);
+
+	case INST_PUSH_RETURN_CODE:
+	    PUSH_OBJECT(Tcl_NewLongObj(result));
+	    TRACE(("pushReturnCode => %u\n", result));
+	    ADJUST_PC(1);
+
+	default:
+	    TRACE(("UNRECOGNIZED INSTRUCTION %u\n", opCode));
+	    panic("TclExecuteByteCode: unrecognized opCode %u", opCode);
+	} /* end of switch on opCode */
+
+	/*
+	 * Division by zero in an expression. Control only reaches this
+	 * point by "goto divideByZero".
+	 */
+	
+        divideByZero:
+	Tcl_ResetResult(interp);
+	Tcl_AppendToObj(Tcl_GetObjResult(interp), "divide by zero", -1);
+	Tcl_SetErrorCode(interp, "ARITH", "DIVZERO", "divide by zero",
+			 (char *) NULL);
+	result = TCL_ERROR;
+	
+	/*
+	 * Execution has generated an "exception" such as TCL_ERROR. If the
+	 * exception is an error, record information about what was being
+	 * executed when the error occurred. Find the closest enclosing
+	 * catch range, if any. If no enclosing catch range is found, stop
+	 * execution and return the "exception" code.
+	 */
+	
+        checkForCatch:
+	if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
+	    RecordTracebackInfo(interp, pc, codePtr);
+        }
+	rangePtr = TclGetExceptionRangeForPc(pc, /*catchOnly*/ 1, codePtr);
+	if (rangePtr == NULL) {
+	    TRACE(("   ... no enclosing catch, returning %s\n",
+		    StringForResultCode(result)));
+	    goto abnormalReturn;
+	}
+
+	/*
+	 * A catch exception range (rangePtr) was found to handle an
+	 * "exception". It was found either by checkForCatch just above or
+	 * by an instruction during break, continue, or error processing.
+	 * Jump to its catchOffset after unwinding the operand stack to
+	 * the depth it had when starting to execute the range's catch
+	 * command.
+	 */
+
+        processCatch:
+	while (stackTop > catchStackPtr[catchTop]) {
+	    valuePtr = POP_OBJECT();
+	    TclDecrRefCount(valuePtr);
+	}
+	TRACE(("  ... found catch at %d, catchTop=%d, unwound to %d, new pc %u\n",
+	        rangePtr->codeOffset, catchTop, catchStackPtr[catchTop],
+	        (unsigned int)(rangePtr->catchOffset)));
+	pc = (codePtr->codeStart + rangePtr->catchOffset);
+	continue;		/* restart the execution loop at pc */
+    } /* end of infinite loop dispatching on instructions */
+
+    /*
+     * Abnormal return code. Restore the stack to state it had when starting
+     * to execute the ByteCode.
+     */
+
+    abnormalReturn:
+    while (stackTop > initStackTop) {
+	valuePtr = POP_OBJECT();
+	Tcl_DecrRefCount(valuePtr);
+    }
+
+    /*
+     * Free the catch stack array if malloc'ed storage was used.
+     */
+
+    done:
+    if (catchStackPtr != catchStackStorage) {
+	ckfree((char *) catchStackPtr);
+    }
+    eePtr->stackTop = initStackTop;
+    return result;
+#undef STATIC_CATCH_STACK_SIZE
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PrintByteCodeInfo --
+ *
+ *	This procedure prints a summary about a bytecode object to stdout.
+ *	It is called by TclExecuteByteCode when starting to execute the
+ *	bytecode object if tclTraceExec has the value 2 or more.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+PrintByteCodeInfo(codePtr)
+    register ByteCode *codePtr;	/* The bytecode whose summary is printed
+				 * to stdout. */
+{
+    Proc *procPtr = codePtr->procPtr;
+    int numCmds = codePtr->numCommands;
+    int numObjs = codePtr->numObjects;
+    int objBytes, i;
+
+    objBytes = (numObjs * sizeof(Tcl_Obj));
+    for (i = 0;  i < numObjs;  i++) {
+	Tcl_Obj *litObjPtr = codePtr->objArrayPtr[i];
+	if (litObjPtr->bytes != NULL) {
+	    objBytes += litObjPtr->length;
+	}
+    }
+    
+    fprintf(stdout, "\nExecuting ByteCode 0x%x, ref ct %u, epoch %u, interp 0x%x(epoch %u)\n",
+	    (unsigned int) codePtr, codePtr->refCount,
+	    codePtr->compileEpoch, (unsigned int) codePtr->iPtr,
+	    codePtr->iPtr->compileEpoch);
+    
+    fprintf(stdout, "  Source: ");
+    TclPrintSource(stdout, codePtr->source, 70);
+
+    fprintf(stdout, "\n  Cmds %d, chars %d, inst %u, objs %u, aux %d, stk depth %u, code/src %.2fn",
+            numCmds, codePtr->numSrcChars, codePtr->numCodeBytes, numObjs,
+	    codePtr->numAuxDataItems, codePtr->maxStackDepth,
+	    (codePtr->numSrcChars?
+	            ((float)codePtr->totalSize)/((float)codePtr->numSrcChars) : 0.0));
+
+    fprintf(stdout, "  Code %zu = %u(header)+%d(inst)+%d(objs)+%u(exc)+%u(aux)+%d(cmd map)\n",
+	    codePtr->totalSize, sizeof(ByteCode), codePtr->numCodeBytes,
+	    objBytes, (codePtr->numExcRanges * sizeof(ExceptionRange)),
+	    (codePtr->numAuxDataItems * sizeof(AuxData)),
+	    codePtr->numCmdLocBytes);
+
+    if (procPtr != NULL) {
+	fprintf(stdout,
+		"  Proc 0x%x, ref ct %d, args %d, compiled locals %d\n",
+		(unsigned int) procPtr, procPtr->refCount,
+		procPtr->numArgs, procPtr->numCompiledLocals);
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ValidatePcAndStackTop --
+ *
+ *	This procedure is called by TclExecuteByteCode when debugging to
+ *	verify that the program counter and stack top are valid during
+ *	execution.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Prints a message to stderr and panics if either the pc or stack
+ *	top are invalid.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_COMPILE_DEBUG
+static void
+ValidatePcAndStackTop(codePtr, pc, stackTop, stackLowerBound, stackUpperBound)
+    register ByteCode *codePtr; /* The bytecode whose summary is printed
+				 * to stdout. */
+    unsigned char *pc;		/* Points to first byte of a bytecode
+				 * instruction. The program counter. */
+    int stackTop;		/* Current stack top. Must be between
+				 * stackLowerBound and stackUpperBound
+				 * (inclusive). */
+    int stackLowerBound;	/* Smallest legal value for stackTop. */
+    int stackUpperBound;	/* Greatest legal value for stackTop. */
+{
+    unsigned int relativePc = (unsigned int) (pc - codePtr->codeStart);
+    unsigned int codeStart = (unsigned int) codePtr->codeStart;
+    unsigned int codeEnd = (unsigned int)
+	    (codePtr->codeStart + codePtr->numCodeBytes);
+    unsigned char opCode = *pc;
+
+    if (((unsigned int) pc < codeStart) || ((unsigned int) pc > codeEnd)) {
+	fprintf(stderr, "\nBad instruction pc 0x%x in TclExecuteByteCode\n",
+		(unsigned int) pc);
+	panic("TclExecuteByteCode execution failure: bad pc");
+    }
+    if ((unsigned int) opCode > LAST_INST_OPCODE) {
+	fprintf(stderr, "\nBad opcode %d at pc %u in TclExecuteByteCode\n",
+		(unsigned int) opCode, relativePc);
+	panic("TclExecuteByteCode execution failure: bad opcode");
+    }
+    if ((stackTop < stackLowerBound) || (stackTop > stackUpperBound)) {
+	int numChars;
+	char *cmd = GetSrcInfoForPc(pc, codePtr, &numChars);
+	char *ellipsis = "";
+	
+	fprintf(stderr, "\nBad stack top %d at pc %u in TclExecuteByteCode",
+		stackTop, relativePc);
+	if (cmd != NULL) {
+	    if (numChars > 100) {
+		numChars = 100;
+		ellipsis = "...";
+	    }
+	    fprintf(stderr, "\n executing %.*s%s\n", numChars, cmd,
+		    ellipsis);
+	} else {
+	    fprintf(stderr, "\n");
+	}
+	panic("TclExecuteByteCode execution failure: bad stack top");
+    }
+}
+#endif /* TCL_COMPILE_DEBUG */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * IllegalExprOperandType --
+ *
+ *	Used by TclExecuteByteCode to add an error message to errorInfo
+ *	when an illegal operand type is detected by an expression
+ *	instruction. The argument opCode holds the failing instruction's
+ *	opcode and opndPtr holds the operand object in error.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	An error message is appended to errorInfo.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+IllegalExprOperandType(interp, opCode, opndPtr)
+    Tcl_Interp *interp;		/* Interpreter to which error information
+				 * pertains. */
+    unsigned int opCode;	/* The instruction opcode being executed
+				 * when the illegal type was found. */
+    Tcl_Obj *opndPtr;		/* Points to the operand holding the value
+				 * with the illegal type. */
+{
+    Tcl_ResetResult(interp);
+    if ((opndPtr->bytes == NULL) || (opndPtr->length == 0)) {
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		"can't use empty string as operand of \"",
+		operatorStrings[opCode - INST_LOR], "\"", (char *) NULL);
+    } else {
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "can't use ",
+		((opndPtr->typePtr == &tclDoubleType) ?
+		    "floating-point value" : "non-numeric string"),
+		" as operand of \"", operatorStrings[opCode - INST_LOR],
+		"\"", (char *) NULL);
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CallTraceProcedure --
+ *
+ *	Invokes a trace procedure registered with an interpreter. These
+ *	procedures trace command execution. Currently this trace procedure
+ *	is called with the address of the string-based Tcl_CmdProc for the
+ *	command, not the Tcl_ObjCmdProc.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Those side effects made by the trace procedure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CallTraceProcedure(interp, tracePtr, cmdPtr, command, numChars, objc, objv)
+    Tcl_Interp *interp;		/* The current interpreter. */
+    register Trace *tracePtr;	/* Describes the trace procedure to call. */
+    Command *cmdPtr;		/* Points to command's Command struct. */
+    char *command;		/* Points to the first character of the
+				 * command's source before substitutions. */
+    int numChars;		/* The number of characters in the
+				 * command's source. */
+    register int objc;		/* Number of arguments for the command. */
+    Tcl_Obj *objv[];		/* Pointers to Tcl_Obj of each argument. */
+{
+    Interp *iPtr = (Interp *) interp;
+    register char **argv;
+    register int i;
+    int length;
+    char *p;
+
+    /*
+     * Get the string rep from the objv argument objects and place their
+     * pointers in argv. First make sure argv is large enough to hold the
+     * objc args plus 1 extra word for the zero end-of-argv word.
+     * THIS FAILS IF AN OBJECT'S STRING REP CONTAINS NULLS.
+     */
+    
+    argv = (char **) ckalloc((unsigned)(objc + 1) * sizeof(char *));
+    for (i = 0;  i < objc;  i++) {
+	argv[i] = Tcl_GetStringFromObj(objv[i], &length);
+    }
+    argv[objc] = 0;
+
+    /*
+     * Copy the command characters into a new string.
+     */
+
+    p = (char *) ckalloc((unsigned) (numChars + 1));
+    memcpy((VOID *) p, (VOID *) command, (size_t) numChars);
+    p[numChars] = '\0';
+    
+    /*
+     * Call the trace procedure then free allocated storage.
+     */
+    
+    (*tracePtr->proc)(tracePtr->clientData, interp, iPtr->numLevels,
+                      p, cmdPtr->proc, cmdPtr->clientData, objc, argv);
+
+    ckfree((char *) argv);
+    ckfree((char *) p);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RecordTracebackInfo --
+ *
+ *      Procedure called by TclExecuteByteCode to record information
+ *      about what was being executed when the error occurred.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      Appends information about the command being executed to the
+ *      "errorInfo" variable. Sets the errorLine field in the interpreter
+ *      to the line number of that command. Sets the ERR_ALREADY_LOGGED
+ *      bit in the interpreter's execution flags.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RecordTracebackInfo(interp, pc, codePtr)
+    Tcl_Interp *interp;         /* The interpreter in which the error
+                                 * occurred. */
+    unsigned char *pc;          /* The program counter value where the error                                 * occurred. This points to a bytecode
+                                 * instruction in codePtr's code. */
+    ByteCode *codePtr;          /* The bytecode sequence being executed. */
+{
+    register Interp *iPtr = (Interp *) interp;
+    char *cmd, *ellipsis;
+    char buf[200];
+    register char *p;
+    int numChars;
+    
+    /*
+     * Record the command in errorInfo (up to a certain number of
+     * characters, or up to the first newline).
+     */
+    
+    iPtr->errorLine = 1;
+    cmd = GetSrcInfoForPc(pc, codePtr, &numChars);
+    if (cmd != NULL) {
+        for (p = codePtr->source;  p != cmd;  p++) {
+            if (*p == '\n') {
+                iPtr->errorLine++;
+            }
+        }
+        for ( ;  (isspace(UCHAR(*p)) || (*p == ';'));  p++) {
+            if (*p == '\n') {
+                iPtr->errorLine++;
+            }
+        }
+	
+        ellipsis = "";
+        if (numChars > 150) {
+            numChars = 150;
+            ellipsis = "...";
+        }
+        if (!(iPtr->flags & ERR_IN_PROGRESS)) {
+            sprintf(buf, "\n    while executing\n\"%.*s%s\"",
+                    numChars, cmd, ellipsis);
+        } else {
+            sprintf(buf, "\n    invoked from within\n\"%.*s%s\"",
+                    numChars, cmd, ellipsis);
+        }
+        Tcl_AddObjErrorInfo(interp, buf, -1);
+        iPtr->flags |= ERR_ALREADY_LOGGED;
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetSrcInfoForPc --
+ *
+ *	Given a program counter value, finds the closest command in the
+ *	bytecode code unit's CmdLocation array and returns information about
+ *	that command's source: a pointer to its first byte and the number of
+ *	characters.
+ *
+ * Results:
+ *	If a command is found that encloses the program counter value, a
+ *	pointer to the command's source is returned and the length of the
+ *	source is stored at *lengthPtr. If multiple commands resulted in
+ *	code at pc, information about the closest enclosing command is
+ *	returned. If no matching command is found, NULL is returned and
+ *	*lengthPtr is unchanged.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+GetSrcInfoForPc(pc, codePtr, lengthPtr)
+    unsigned char *pc;		/* The program counter value for which to
+				 * return the closest command's source info.
+				 * This points to a bytecode instruction
+				 * in codePtr's code. */
+    ByteCode *codePtr;		/* The bytecode sequence in which to look
+				 * up the command source for the pc. */
+    int *lengthPtr;		/* If non-NULL, the location where the
+				 * length of the command's source should be
+				 * stored. If NULL, no length is stored. */
+{
+    register int pcOffset = (pc - codePtr->codeStart);
+    int numCmds = codePtr->numCommands;
+    unsigned char *codeDeltaNext, *codeLengthNext;
+    unsigned char *srcDeltaNext, *srcLengthNext;
+    int codeOffset, codeLen, codeEnd, srcOffset, srcLen, delta, i;
+    int bestDist = INT_MAX;	/* Distance of pc to best cmd's start pc. */
+    int bestSrcOffset = -1;	/* Initialized to avoid compiler warning. */
+    int bestSrcLength = -1;	/* Initialized to avoid compiler warning. */
+
+    if ((pcOffset < 0) || (pcOffset >= codePtr->numCodeBytes)) {
+	return NULL;
+    }
+
+    /*
+     * Decode the code and source offset and length for each command. The
+     * closest enclosing command is the last one whose code started before
+     * pcOffset.
+     */
+
+    codeDeltaNext = codePtr->codeDeltaStart;
+    codeLengthNext = codePtr->codeLengthStart;
+    srcDeltaNext  = codePtr->srcDeltaStart;
+    srcLengthNext = codePtr->srcLengthStart;
+    codeOffset = srcOffset = 0;
+    for (i = 0;  i < numCmds;  i++) {
+	if ((unsigned int) (*codeDeltaNext) == (unsigned int) 0xFF) {
+	    codeDeltaNext++;
+	    delta = TclGetInt4AtPtr(codeDeltaNext);
+	    codeDeltaNext += 4;
+	} else {
+	    delta = TclGetInt1AtPtr(codeDeltaNext);
+	    codeDeltaNext++;
+	}
+	codeOffset += delta;
+
+	if ((unsigned int) (*codeLengthNext) == (unsigned int) 0xFF) {
+	    codeLengthNext++;
+	    codeLen = TclGetInt4AtPtr(codeLengthNext);
+	    codeLengthNext += 4;
+	} else {
+	    codeLen = TclGetInt1AtPtr(codeLengthNext);
+	    codeLengthNext++;
+	}
+	codeEnd = (codeOffset + codeLen - 1);
+
+	if ((unsigned int) (*srcDeltaNext) == (unsigned int) 0xFF) {
+	    srcDeltaNext++;
+	    delta = TclGetInt4AtPtr(srcDeltaNext);
+	    srcDeltaNext += 4;
+	} else {
+	    delta = TclGetInt1AtPtr(srcDeltaNext);
+	    srcDeltaNext++;
+	}
+	srcOffset += delta;
+
+	if ((unsigned int) (*srcLengthNext) == (unsigned int) 0xFF) {
+	    srcLengthNext++;
+	    srcLen = TclGetInt4AtPtr(srcLengthNext);
+	    srcLengthNext += 4;
+	} else {
+	    srcLen = TclGetInt1AtPtr(srcLengthNext);
+	    srcLengthNext++;
+	}
+	
+	if (codeOffset > pcOffset) {      /* best cmd already found */
+	    break;
+	} else if (pcOffset <= codeEnd) { /* this cmd's code encloses pc */
+	    int dist = (pcOffset - codeOffset);
+	    if (dist <= bestDist) {
+		bestDist = dist;
+		bestSrcOffset = srcOffset;
+		bestSrcLength = srcLen;
+	    }
+	}
+    }
+
+    if (bestDist == INT_MAX) {
+	return NULL;
+    }
+    
+    if (lengthPtr != NULL) {
+	*lengthPtr = bestSrcLength;
+    }
+    return (codePtr->source + bestSrcOffset);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetExceptionRangeForPc --
+ *
+ *	Procedure that given a program counter value, returns the closest
+ *	enclosing ExceptionRange that matches the kind requested.
+ *
+ * Results:
+ *	In the normal case, catchOnly is 0 (false) and this procedure
+ *	returns a pointer to the most closely enclosing ExceptionRange
+ *	structure regardless of whether it is a loop or catch exception
+ *	range. This is appropriate when processing a TCL_BREAK or
+ *	TCL_CONTINUE, which will be "handled" either by a loop exception
+ *	range or a closer catch range. If catchOnly is nonzero (true), this
+ *	procedure ignores loop exception ranges and returns a pointer to the
+ *	closest catch range. If no matching ExceptionRange is found that
+ *	encloses pc, a NULL is returned.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ExceptionRange *
+TclGetExceptionRangeForPc(pc, catchOnly, codePtr)
+    unsigned char *pc;		/* The program counter value for which to
+				 * search for a closest enclosing exception
+				 * range. This points to a bytecode
+				 * instruction in codePtr's code. */
+    int catchOnly;		/* If 0, consider either loop or catch
+				 * ExceptionRanges in search. Otherwise
+				 * consider only catch ranges (and ignore
+				 * any closer loop ranges). */
+    ByteCode* codePtr;		/* Points to the ByteCode in which to search
+				 * for the enclosing ExceptionRange. */
+{
+    ExceptionRange *rangeArrayPtr;
+    int numRanges = codePtr->numExcRanges;
+    register ExceptionRange *rangePtr;
+    int codeOffset = (pc - codePtr->codeStart);
+    register int i, level;
+
+    if (numRanges == 0) {
+	return NULL;
+    }
+    rangeArrayPtr = codePtr->excRangeArrayPtr;
+
+    for (level = codePtr->maxExcRangeDepth;  level >= 0;  level--) {
+	for (i = 0;  i < numRanges;  i++) {
+	    rangePtr = &(rangeArrayPtr[i]);
+	    if (rangePtr->nestingLevel == level) {
+		int start = rangePtr->codeOffset;
+		int end   = (start + rangePtr->numCodeBytes);
+		if ((start <= codeOffset) && (codeOffset < end)) {
+		    if ((!catchOnly)
+			    || (rangePtr->type == CATCH_EXCEPTION_RANGE)) {
+			return rangePtr;
+		    }
+		}
+	    }
+	}
+    }
+    return NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Math Functions --
+ *
+ *	This page contains the procedures that implement all of the
+ *	built-in math functions for expressions.
+ *
+ * Results:
+ *	Each procedure returns TCL_OK if it succeeds and pushes an
+ *	Tcl object holding the result. If it fails it returns TCL_ERROR
+ *	and leaves an error message in the interpreter's result.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ExprUnaryFunc(interp, eePtr, clientData)
+    Tcl_Interp *interp;		/* The interpreter in which to execute the
+				 * function. */
+    ExecEnv *eePtr;		/* Points to the environment for executing
+				 * the function. */
+    ClientData clientData;	/* Contains the address of a procedure that
+				 * takes one double argument and returns a
+				 * double result. */
+{
+    StackItem *stackPtr;        /* Cached evaluation stack base pointer. */
+    register int stackTop;	/* Cached top index of evaluation stack. */
+    register Tcl_Obj *valuePtr;
+    Tcl_ObjType *tPtr;
+    double d, dResult;
+    long i;
+    int result = TCL_OK;
+    
+    double (*func) _ANSI_ARGS_((double)) =
+	(double (*)_ANSI_ARGS_((double))) clientData;
+
+    /*
+     * Set stackPtr and stackTop from eePtr.
+     */
+    
+    CACHE_STACK_INFO();
+
+    /*
+     * Pop the function's argument from the evaluation stack. Convert it
+     * to a double if necessary.
+     */
+
+    valuePtr = POP_OBJECT();
+    tPtr = valuePtr->typePtr;
+    
+    if (tPtr == &tclIntType) {
+	d = (double) valuePtr->internalRep.longValue;
+    } else if (tPtr == &tclDoubleType) {
+	d = valuePtr->internalRep.doubleValue;
+    } else {			/* FAILS IF STRING REP HAS NULLS */
+	char *s = Tcl_GetStringFromObj(valuePtr, (int *) NULL);
+	
+	if (TclLooksLikeInt(s)) {
+	    result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i);
+	    d = (double) valuePtr->internalRep.longValue;
+	} else {
+	    result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d);
+	}
+	if (result != TCL_OK) {
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	            "argument to math function didn't have numeric value", -1);
+	    goto done;
+	}
+    }
+
+    errno = 0;
+    dResult = (*func)(d);
+    if ((errno != 0) || IS_NAN(dResult) || IS_INF(dResult)) {
+	TclExprFloatError(interp, dResult);
+	result = TCL_ERROR;
+	goto done;
+    }
+    
+    /*
+     * Push a Tcl object holding the result.
+     */
+
+    PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
+    
+    /*
+     * Reflect the change to stackTop back in eePtr.
+     */
+
+    done:
+    Tcl_DecrRefCount(valuePtr);
+    DECACHE_STACK_INFO();
+    return result;
+}
+
+static int
+ExprBinaryFunc(interp, eePtr, clientData)
+    Tcl_Interp *interp;		/* The interpreter in which to execute the
+				 * function. */
+    ExecEnv *eePtr;		/* Points to the environment for executing
+				 * the function. */
+    ClientData clientData;	/* Contains the address of a procedure that
+				 * takes two double arguments and
+				 * returns a double result. */
+{
+    StackItem *stackPtr;        /* Cached evaluation stack base pointer. */
+    register int stackTop;	/* Cached top index of evaluation stack. */
+    register Tcl_Obj *valuePtr, *value2Ptr;
+    Tcl_ObjType *tPtr;
+    double d1, d2, dResult;
+    long i;
+    char *s;
+    int result = TCL_OK;
+    
+    double (*func) _ANSI_ARGS_((double, double))
+	= (double (*)_ANSI_ARGS_((double, double))) clientData;
+
+    /*
+     * Set stackPtr and stackTop from eePtr.
+     */
+    
+    CACHE_STACK_INFO();
+
+    /*
+     * Pop the function's two arguments from the evaluation stack. Convert
+     * them to doubles if necessary.
+     */
+
+    value2Ptr = POP_OBJECT();
+    valuePtr  = POP_OBJECT();
+
+    tPtr = valuePtr->typePtr;
+    if (tPtr == &tclIntType) {
+	d1 = (double) valuePtr->internalRep.longValue;
+    } else if (tPtr == &tclDoubleType) {
+	d1 = valuePtr->internalRep.doubleValue;
+    } else {			/* FAILS IF STRING REP HAS NULLS */
+	s = Tcl_GetStringFromObj(valuePtr, (int *) NULL);
+	if (TclLooksLikeInt(s)) {
+	    result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i);
+	    d1 = (double) valuePtr->internalRep.longValue;
+	} else {
+	    result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d1);
+	}
+	if (result != TCL_OK) {
+            badArg:
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	            "argument to math function didn't have numeric value", -1);
+	    goto done;
+	}
+    }
+
+    tPtr = value2Ptr->typePtr;
+    if (tPtr == &tclIntType) {
+	d2 = value2Ptr->internalRep.longValue;
+    } else if (tPtr == &tclDoubleType) {
+	d2 = value2Ptr->internalRep.doubleValue;
+    } else {			/* FAILS IF STRING REP HAS NULLS */
+	s = Tcl_GetStringFromObj(value2Ptr, (int *) NULL);
+	if (TclLooksLikeInt(s)) {
+	    result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, value2Ptr, &i);
+	    d2 = (double) value2Ptr->internalRep.longValue;
+	} else {
+	    result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, value2Ptr, &d2);
+	}
+	if (result != TCL_OK) {
+	    goto badArg;
+	}
+    }
+
+    errno = 0;
+    dResult = (*func)(d1, d2);
+    if ((errno != 0) || IS_NAN(dResult) || IS_INF(dResult)) {
+	TclExprFloatError(interp, dResult);
+	result = TCL_ERROR;
+	goto done;
+    }
+
+    /*
+     * Push a Tcl object holding the result.
+     */
+
+    PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
+    
+    /*
+     * Reflect the change to stackTop back in eePtr.
+     */
+
+    done:
+    Tcl_DecrRefCount(valuePtr);
+    Tcl_DecrRefCount(value2Ptr);
+    DECACHE_STACK_INFO();
+    return result;
+}
+
+static int
+ExprAbsFunc(interp, eePtr, clientData)
+    Tcl_Interp *interp;		/* The interpreter in which to execute the
+				 * function. */
+    ExecEnv *eePtr;		/* Points to the environment for executing
+				 * the function. */
+    ClientData clientData;	/* Ignored. */
+{
+    StackItem *stackPtr;        /* Cached evaluation stack base pointer. */
+    register int stackTop;	/* Cached top index of evaluation stack. */
+    register Tcl_Obj *valuePtr;
+    Tcl_ObjType *tPtr;
+    long i, iResult;
+    double d, dResult;
+    int result = TCL_OK;
+
+    /*
+     * Set stackPtr and stackTop from eePtr.
+     */
+    
+    CACHE_STACK_INFO();
+
+    /*
+     * Pop the argument from the evaluation stack.
+     */
+
+    valuePtr = POP_OBJECT();
+    tPtr = valuePtr->typePtr;
+    
+    if (tPtr == &tclIntType) {
+	i = valuePtr->internalRep.longValue;
+    } else if (tPtr == &tclDoubleType) {
+	d = valuePtr->internalRep.doubleValue;
+    } else {			/* FAILS IF STRING REP HAS NULLS */
+	char *s = Tcl_GetStringFromObj(valuePtr, (int *) NULL);
+	
+	if (TclLooksLikeInt(s)) {
+	    result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i);
+	} else {
+	    result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d);
+	}
+	if (result != TCL_OK) {
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	            "argument to math function didn't have numeric value", -1);
+	    goto done;
+	}
+	tPtr = valuePtr->typePtr;
+    }
+
+    /*
+     * Push a Tcl object with the result.
+     */
+    
+    if (tPtr == &tclIntType) {
+	if (i < 0) {
+	    iResult = -i;
+	    if (iResult < 0) {
+		Tcl_ResetResult(interp);
+		Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		        "integer value too large to represent", -1);
+		Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
+			"integer value too large to represent", (char *) NULL);
+		result = TCL_ERROR;
+		goto done;
+	    }
+	} else {
+	    iResult = i;
+	}	    
+	PUSH_OBJECT(Tcl_NewLongObj(iResult));
+    } else {
+	if (d < 0.0) {
+	    dResult = -d;
+	} else {
+	    dResult = d;
+	}
+	if (IS_NAN(dResult) || IS_INF(dResult)) {
+	    TclExprFloatError(interp, dResult);
+	    result = TCL_ERROR;
+	    goto done;
+	}
+	PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
+    }
+    
+    /*
+     * Reflect the change to stackTop back in eePtr.
+     */
+
+    done:
+    Tcl_DecrRefCount(valuePtr);
+    DECACHE_STACK_INFO();
+    return result;
+}
+
+static int
+ExprDoubleFunc(interp, eePtr, clientData)
+    Tcl_Interp *interp;		/* The interpreter in which to execute the
+				 * function. */
+    ExecEnv *eePtr;		/* Points to the environment for executing
+				 * the function. */
+    ClientData clientData;	/* Ignored. */
+{
+    StackItem *stackPtr;        /* Cached evaluation stack base pointer. */
+    register int stackTop;	/* Cached top index of evaluation stack. */
+    register Tcl_Obj *valuePtr;
+    double dResult;
+    long i;
+    int result = TCL_OK;
+
+    /*
+     * Set stackPtr and stackTop from eePtr.
+     */
+    
+    CACHE_STACK_INFO();
+
+    /*
+     * Pop the argument from the evaluation stack.
+     */
+
+    valuePtr = POP_OBJECT();
+    if (valuePtr->typePtr == &tclIntType) {
+	dResult = (double) valuePtr->internalRep.longValue;
+    } else if (valuePtr->typePtr == &tclDoubleType) {
+	dResult = valuePtr->internalRep.doubleValue;
+    } else {			/* FAILS IF STRING REP HAS NULLS */
+	char *s = Tcl_GetStringFromObj(valuePtr, (int *) NULL);
+	
+	if (TclLooksLikeInt(s)) {
+	    result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i);
+	    dResult = (double) valuePtr->internalRep.longValue;
+	} else {
+	    result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr,
+		    &dResult);
+	}
+	if (result != TCL_OK) {
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		    "argument to math function didn't have numeric value", -1);
+	    goto done;
+	}
+    }
+
+    /*
+     * Push a Tcl object with the result.
+     */
+
+    PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
+
+    /*
+     * Reflect the change to stackTop back in eePtr.
+     */
+
+    done:
+    Tcl_DecrRefCount(valuePtr);
+    DECACHE_STACK_INFO();
+    return result;
+}
+
+static int
+ExprIntFunc(interp, eePtr, clientData)
+    Tcl_Interp *interp;		/* The interpreter in which to execute the
+				 * function. */
+    ExecEnv *eePtr;		/* Points to the environment for executing
+				 * the function. */
+    ClientData clientData;	/* Ignored. */
+{
+    StackItem *stackPtr;        /* Cached evaluation stack base pointer. */
+    register int stackTop;	/* Cached top index of evaluation stack. */
+    register Tcl_Obj *valuePtr;
+    Tcl_ObjType *tPtr;
+    long i = 0;			/* Initialized to avoid compiler warning. */
+    long iResult;
+    double d;
+    int result = TCL_OK;
+
+    /*
+     * Set stackPtr and stackTop from eePtr.
+     */
+    
+    CACHE_STACK_INFO();
+
+    /*
+     * Pop the argument from the evaluation stack.
+     */
+
+    valuePtr = POP_OBJECT();
+    tPtr = valuePtr->typePtr;
+    
+    if (tPtr == &tclIntType) {
+	i = valuePtr->internalRep.longValue;
+    } else if (tPtr == &tclDoubleType) {
+	d = valuePtr->internalRep.doubleValue;
+    } else {			/* FAILS IF STRING REP HAS NULLS */
+	char *s = Tcl_GetStringFromObj(valuePtr, (int *) NULL);
+	
+	if (TclLooksLikeInt(s)) {
+	    result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i);
+	} else {
+	    result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d);
+	}
+	if (result != TCL_OK) {
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		    "argument to math function didn't have numeric value", -1);
+	    goto done;
+	}
+	tPtr = valuePtr->typePtr;
+    }
+
+    /*
+     * Push a Tcl object with the result.
+     */
+    
+    if (tPtr == &tclIntType) {
+	iResult = i;
+    } else {
+	if (d < 0.0) {
+	    if (d < (double) (long) LONG_MIN) {
+		tooLarge:
+		Tcl_ResetResult(interp);
+		Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		        "integer value too large to represent", -1);
+		Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
+			"integer value too large to represent", (char *) NULL);
+		result = TCL_ERROR;
+		goto done;
+	    }
+	} else {
+	    if (d > (double) LONG_MAX) {
+		goto tooLarge;
+	    }
+	}
+	if (IS_NAN(d) || IS_INF(d)) {
+	    TclExprFloatError(interp, d);
+	    result = TCL_ERROR;
+	    goto done;
+	}
+	iResult = (long) d;
+    }
+    PUSH_OBJECT(Tcl_NewLongObj(iResult));
+
+    /*
+     * Reflect the change to stackTop back in eePtr.
+     */
+
+    done:
+    Tcl_DecrRefCount(valuePtr);
+    DECACHE_STACK_INFO();
+    return result;
+}
+
+static int
+ExprRoundFunc(interp, eePtr, clientData)
+    Tcl_Interp *interp;		/* The interpreter in which to execute the
+				 * function. */
+    ExecEnv *eePtr;		/* Points to the environment for executing
+				 * the function. */
+    ClientData clientData;	/* Ignored. */
+{
+    StackItem *stackPtr;        /* Cached evaluation stack base pointer. */
+    register int stackTop;	/* Cached top index of evaluation stack. */
+    Tcl_Obj *valuePtr;
+    Tcl_ObjType *tPtr;
+    long i = 0;			/* Initialized to avoid compiler warning. */
+    long iResult;
+    double d, temp;
+    int result = TCL_OK;
+
+    /*
+     * Set stackPtr and stackTop from eePtr.
+     */
+    
+    CACHE_STACK_INFO();
+
+    /*
+     * Pop the argument from the evaluation stack.
+     */
+
+    valuePtr = POP_OBJECT();
+    tPtr = valuePtr->typePtr;
+    
+    if (tPtr == &tclIntType) {
+	i = valuePtr->internalRep.longValue;
+    } else if (tPtr == &tclDoubleType) {
+	d = valuePtr->internalRep.doubleValue;
+    } else {			/* FAILS IF STRING REP HAS NULLS */
+	char *s = Tcl_GetStringFromObj(valuePtr, (int *) NULL);
+	
+	if (TclLooksLikeInt(s)) {
+	    result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i);
+	} else {
+	    result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d);
+	}
+	if (result != TCL_OK) {
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		    "argument to math function didn't have numeric value", -1);
+	    goto done;
+	}
+	tPtr = valuePtr->typePtr;
+    }
+
+    /*
+     * Push a Tcl object with the result.
+     */
+    
+    if (tPtr == &tclIntType) {
+	iResult = i;
+    } else {
+	if (d < 0.0) {
+	    if (d <= (((double) (long) LONG_MIN) - 0.5)) {
+		tooLarge:
+		Tcl_ResetResult(interp);
+		Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		        "integer value too large to represent", -1);
+		Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
+			"integer value too large to represent",
+			(char *) NULL);
+		result = TCL_ERROR;
+		goto done;
+	    }
+	    temp = (long) (d - 0.5);
+	} else {
+	    if (d >= (((double) LONG_MAX + 0.5))) {
+		goto tooLarge;
+	    }
+	    temp = (long) (d + 0.5);
+	}
+	if (IS_NAN(temp) || IS_INF(temp)) {
+	    TclExprFloatError(interp, temp);
+	    result = TCL_ERROR;
+	    goto done;
+	}
+	iResult = (long) temp;
+    }
+    PUSH_OBJECT(Tcl_NewLongObj(iResult));
+
+    /*
+     * Reflect the change to stackTop back in eePtr.
+     */
+
+    done:
+    Tcl_DecrRefCount(valuePtr);
+    DECACHE_STACK_INFO();
+    return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ExprCallMathFunc --
+ *
+ *	This procedure is invoked to call a non-builtin math function
+ *	during the execution of an expression. 
+ *
+ * Results:
+ *	TCL_OK is returned if all went well and the function's value
+ *	was computed successfully. If an error occurred, TCL_ERROR
+ *	is returned and an error message is left in the interpreter's
+ *	result.	After a successful return this procedure pushes a Tcl object
+ *	holding the result. 
+ *
+ * Side effects:
+ *	None, unless the called math function has side effects.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ExprCallMathFunc(interp, eePtr, objc, objv)
+    Tcl_Interp *interp;		/* The interpreter in which to execute the
+				 * function. */
+    ExecEnv *eePtr;		/* Points to the environment for executing
+				 * the function. */
+    int objc;			/* Number of arguments. The function name is
+				 * the 0-th argument. */
+    Tcl_Obj **objv;		/* The array of arguments. The function name
+				 * is objv[0]. */
+{
+    Interp *iPtr = (Interp *) interp;
+    StackItem *stackPtr;        /* Cached evaluation stack base pointer. */
+    register int stackTop;	/* Cached top index of evaluation stack. */
+    char *funcName;
+    Tcl_HashEntry *hPtr;
+    MathFunc *mathFuncPtr;	/* Information about math function. */
+    Tcl_Value args[MAX_MATH_ARGS]; /* Arguments for function call. */
+    Tcl_Value funcResult;	/* Result of function call as Tcl_Value. */
+    register Tcl_Obj *valuePtr;
+    Tcl_ObjType *tPtr;
+    long i;
+    double d;
+    int j, k, result;
+    
+    Tcl_ResetResult(interp);
+    
+    /*
+     * Set stackPtr and stackTop from eePtr.
+     */
+    
+    CACHE_STACK_INFO();
+
+    /*
+     * Look up the MathFunc record for the function.
+     * THIS FAILS IF THE OBJECT'S STRING REP CONTAINS NULLS.
+     */
+
+    funcName = Tcl_GetStringFromObj(objv[0], (int *) NULL);
+    hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcName);
+    if (hPtr == NULL) {
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		"unknown math function \"", funcName, "\"", (char *) NULL);
+	result = TCL_ERROR;
+	goto done;
+    }
+    mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
+    if (mathFuncPtr->numArgs != (objc-1)) {
+	panic("ExprCallMathFunc: expected number of args %d != actual number %d",
+	        mathFuncPtr->numArgs, objc);
+	result = TCL_ERROR;
+	goto done;
+    }
+
+    /*
+     * Collect the arguments for the function, if there are any, into the
+     * array "args". Note that args[0] will have the Tcl_Value that
+     * corresponds to objv[1].
+     */
+
+    for (j = 1, k = 0;  j < objc;  j++, k++) {
+	valuePtr = objv[j];
+	tPtr = valuePtr->typePtr;
+	
+	if (tPtr == &tclIntType) {
+	    i = valuePtr->internalRep.longValue;
+	} else if (tPtr == &tclDoubleType) {
+	    d = valuePtr->internalRep.doubleValue;
+	} else {
+	    /*
+	     * Try to convert to int first then double.
+	     * FAILS IF STRING REP HAS NULLS.
+	     */
+	    
+	    char *s = Tcl_GetStringFromObj(valuePtr, (int *) NULL);
+	    
+	    if (TclLooksLikeInt(s)) {
+		result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i);
+	    } else {
+		result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
+			valuePtr, &d);
+	    }
+	    if (result != TCL_OK) {
+		Tcl_AppendToObj(Tcl_GetObjResult(interp),
+			"argument to math function didn't have numeric value", -1);
+		goto done;
+	    }
+	    tPtr = valuePtr->typePtr;
+	}
+
+	/*
+	 * Copy the object's numeric value to the argument record,
+	 * converting it if necessary. 
+	 */
+	
+	if (tPtr == &tclIntType) {
+	    if (mathFuncPtr->argTypes[k] == TCL_DOUBLE) {
+		args[k].type = TCL_DOUBLE;
+		args[k].doubleValue = i;
+	    } else {
+		args[k].type = TCL_INT;
+		args[k].intValue = i;
+	    }
+	} else {
+	    if (mathFuncPtr->argTypes[k] == TCL_INT) {
+		args[k].type = TCL_INT;
+		args[k].intValue = (long) d;
+	    } else {
+		args[k].type = TCL_DOUBLE;
+		args[k].doubleValue = d;
+	    }
+	}
+    }
+
+    /*
+     * Invoke the function and copy its result back into valuePtr.
+     */
+
+    tcl_MathInProgress++;
+    result = (*mathFuncPtr->proc)(mathFuncPtr->clientData, interp, args,
+	    &funcResult);
+    tcl_MathInProgress--;
+    if (result != TCL_OK) {
+	goto done;
+    }
+
+    /*
+     * Pop the objc top stack elements and decrement their ref counts.
+     */
+		
+    i = (stackTop - (objc-1));
+    while (i <= stackTop) {
+	valuePtr = stackPtr[i].o;
+	Tcl_DecrRefCount(valuePtr);
+	i++;
+    }
+    stackTop -= objc;
+    
+    /*
+     * Push the call's object result.
+     */
+    
+    if (funcResult.type == TCL_INT) {
+	PUSH_OBJECT(Tcl_NewLongObj(funcResult.intValue));
+    } else {
+	d = funcResult.doubleValue;
+	if (IS_NAN(d) || IS_INF(d)) {
+	    TclExprFloatError(interp, d);
+	    result = TCL_ERROR;
+	    goto done;
+	}
+	PUSH_OBJECT(Tcl_NewDoubleObj(d));
+    }
+
+    /*
+     * Reflect the change to stackTop back in eePtr.
+     */
+
+    done:
+    DECACHE_STACK_INFO();
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclExprFloatError --
+ *
+ *	This procedure is called when an error occurs during a
+ *	floating-point operation. It reads errno and sets
+ *	interp->objResultPtr accordingly.
+ *
+ * Results:
+ *	interp->objResultPtr is set to hold an error message.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclExprFloatError(interp, value)
+    Tcl_Interp *interp;		/* Where to store error message. */
+    double value;		/* Value returned after error;  used to
+				 * distinguish underflows from overflows. */
+{
+    char *s;
+
+    Tcl_ResetResult(interp);
+    if ((errno == EDOM) || (value != value)) {
+	s = "domain error: argument not in valid range";
+	Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
+	Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", s, (char *) NULL);
+    } else if ((errno == ERANGE) || IS_INF(value)) {
+	if (value == 0.0) {
+	    s = "floating-point value too small to represent";
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
+	    Tcl_SetErrorCode(interp, "ARITH", "UNDERFLOW", s, (char *) NULL);
+	} else {
+	    s = "floating-point value too large to represent";
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
+	    Tcl_SetErrorCode(interp, "ARITH", "OVERFLOW", s, (char *) NULL);
+	}
+    } else {			/* FAILS IF STRING REP CONTAINS NULLS */
+	char msg[100];
+	
+	sprintf(msg, "unknown floating-point error, errno = %d", errno);
+	Tcl_AppendToObj(Tcl_GetObjResult(interp), msg, -1);
+	Tcl_SetErrorCode(interp, "ARITH", "UNKNOWN", msg, (char *) NULL);
+    }
+}
+
+
+#ifdef TCL_COMPILE_STATS
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclLog2 --
+ *
+ *	Procedure used while collecting compilation statistics to determine
+ *	the log base 2 of an integer.
+ *
+ * Results:
+ *	Returns the log base 2 of the operand. If the argument is less
+ *	than or equal to zero, a zero is returned.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclLog2(value)
+    register int value;		/* The integer for which to compute the
+				 * log base 2. */
+{
+    register int n = value;
+    register int result = 0;
+
+    while (n > 1) {
+	n = n >> 1;
+	result++;
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EvalStatsCmd --
+ *
+ *	Implements the "evalstats" command that prints instruction execution
+ *	counts to stdout.
+ *
+ * Results:
+ *	Standard Tcl results.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+EvalStatsCmd(unused, interp, argc, argv)
+    ClientData unused;		/* Unused. */
+    Tcl_Interp *interp;		/* The current interpreter. */
+    int argc;			/* The number of arguments. */
+    char **argv;		/* The argument strings. */
+{
+    register double total = 0.0;
+    register int i;
+    int maxSizeDecade = 0;
+    double totalHeaderBytes = (tclNumCompilations * sizeof(ByteCode));
+
+    for (i = 0;  i < 256;  i++) {
+        if (instructionCount[i] != 0) {
+            total += instructionCount[i];
+        }
+    }
+
+    for (i = 31;  i >= 0;  i--) {
+        if ((tclSourceCount[i] > 0) && (tclByteCodeCount[i] > 0)) {
+            maxSizeDecade = i;
+	    break;
+        }
+    } 
+
+    fprintf(stdout, "\nNumber of compilations		%ld\n",
+	    tclNumCompilations);
+    fprintf(stdout, "Number of executions		%ld\n",
+	    numExecutions);
+    fprintf(stdout, "Average executions/compilation	%.0f\n",
+	    ((float) numExecutions/tclNumCompilations));
+    
+    fprintf(stdout, "\nInstructions executed		%.0f\n",
+	    total);
+    fprintf(stdout, "Average instructions/compile	%.0f\n",
+	    total/tclNumCompilations);
+    fprintf(stdout, "Average instructions/execution	%.0f\n",
+	    total/numExecutions);
+    
+    fprintf(stdout, "\nTotal source bytes		%.6g\n",
+	    tclTotalSourceBytes);
+    fprintf(stdout, "Total code bytes		%.6g\n",
+	    tclTotalCodeBytes);
+    fprintf(stdout, "Average code/compilation	%.0f\n",
+	    tclTotalCodeBytes/tclNumCompilations);
+    fprintf(stdout, "Average code/source		%.2f\n",
+	    tclTotalCodeBytes/tclTotalSourceBytes);
+    fprintf(stdout, "Current source bytes		%.6g\n",
+	    tclCurrentSourceBytes);
+    fprintf(stdout, "Current code bytes		%.6g\n",
+	    tclCurrentCodeBytes);
+    fprintf(stdout, "Current code/source		%.2f\n",
+	    tclCurrentCodeBytes/tclCurrentSourceBytes);
+    
+    fprintf(stdout, "\nTotal objects allocated		%ld\n",
+	    tclObjsAlloced);
+    fprintf(stdout, "Total objects freed		%ld\n",
+	    tclObjsFreed);
+    fprintf(stdout, "Current objects:	 	%ld\n",
+	    (tclObjsAlloced - tclObjsFreed));
+
+    fprintf(stdout, "\nBreakdown of code byte requirements:\n");
+    fprintf(stdout, "                   Total bytes      Pct of    Avg per\n");
+    fprintf(stdout, "                                  all code    compile\n");
+    fprintf(stdout, "Total code        %12.6g        100%%   %8.2f\n",
+	    tclTotalCodeBytes, tclTotalCodeBytes/tclNumCompilations);
+    fprintf(stdout, "Header            %12.6g   %8.2f%%   %8.2f\n",
+	    totalHeaderBytes,
+	    ((totalHeaderBytes * 100.0) / tclTotalCodeBytes),
+	    totalHeaderBytes/tclNumCompilations);
+    fprintf(stdout, "Instructions      %12.6g   %8.2f%%   %8.2f\n",
+	    tclTotalInstBytes,
+	    ((tclTotalInstBytes * 100.0) / tclTotalCodeBytes),
+	    tclTotalInstBytes/tclNumCompilations);
+    fprintf(stdout, "Objects           %12.6g   %8.2f%%   %8.2f\n",
+	    tclTotalObjBytes,
+	    ((tclTotalObjBytes * 100.0) / tclTotalCodeBytes),
+	    tclTotalObjBytes/tclNumCompilations);
+    fprintf(stdout, "Exception table   %12.6g   %8.2f%%   %8.2f\n",
+	    tclTotalExceptBytes,
+	    ((tclTotalExceptBytes * 100.0) / tclTotalCodeBytes),
+	    tclTotalExceptBytes/tclNumCompilations);
+    fprintf(stdout, "Auxiliary data    %12.6g   %8.2f%%   %8.2f\n",
+	    tclTotalAuxBytes,
+	    ((tclTotalAuxBytes * 100.0) / tclTotalCodeBytes),
+	    tclTotalAuxBytes/tclNumCompilations);
+    fprintf(stdout, "Command map       %12.6g   %8.2f%%   %8.2f\n",
+	    tclTotalCmdMapBytes,
+	    ((tclTotalCmdMapBytes * 100.0) / tclTotalCodeBytes),
+	    tclTotalCmdMapBytes/tclNumCompilations);
+    
+    fprintf(stdout, "\nSource and ByteCode size distributions:\n");
+    fprintf(stdout, "	 binary decade		source	  code\n");
+    for (i = 0;  i <= maxSizeDecade;  i++) {
+	int decadeLow, decadeHigh;
+
+	if (i == 0) {
+	    decadeLow = 0;
+	} else {
+	    decadeLow = 1 << i;
+	}
+	decadeHigh = (1 << (i+1)) - 1;
+        fprintf(stdout,	"	%6d -%6d		%6d	%6d\n",
+		decadeLow, decadeHigh,
+		tclSourceCount[i], tclByteCodeCount[i]);
+    }
+
+    fprintf(stdout, "\nInstruction counts:\n");
+    for (i = 0;  i < 256;  i++) {
+        if (instructionCount[i]) {
+            fprintf(stdout, "%20s %8d %6.2f%%\n",
+		    opName[i], instructionCount[i],
+		    (instructionCount[i] * 100.0)/total);
+        }
+    }
+
+#ifdef TCL_MEM_DEBUG
+    fprintf(stdout, "\nHeap Statistics:\n");
+    TclDumpMemoryInfo(stdout);
+#endif /* TCL_MEM_DEBUG */
+
+    return TCL_OK;
+}
+#endif /* TCL_COMPILE_STATS */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetCommandFromObj --
+ *
+ *      Returns the command specified by the name in a Tcl_Obj.
+ *
+ * Results:
+ *	Returns a token for the command if it is found. Otherwise, if it
+ *	can't be found or there is an error, returns NULL.
+ *
+ * Side effects:
+ *      May update the internal representation for the object, caching
+ *      the command reference so that the next time this procedure is
+ *	called with the same object, the command can be found quickly.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Command
+Tcl_GetCommandFromObj(interp, objPtr)
+    Tcl_Interp *interp;		/* The interpreter in which to resolve the
+				 * command and to report errors. */
+    register Tcl_Obj *objPtr;	/* The object containing the command's
+				 * name. If the name starts with "::", will
+				 * be looked up in global namespace. Else,
+				 * looked up first in the current namespace
+				 * if contextNsPtr is NULL, then in global
+				 * namespace. */
+{
+    Interp *iPtr = (Interp *) interp;
+    register ResolvedCmdName *resPtr;
+    register Command *cmdPtr;
+    Namespace *currNsPtr;
+    int result;
+
+    /*
+     * Get the internal representation, converting to a command type if
+     * needed. The internal representation is a ResolvedCmdName that points
+     * to the actual command.
+     */
+    
+    if (objPtr->typePtr != &tclCmdNameType) {
+        result = tclCmdNameType.setFromAnyProc(interp, objPtr);
+        if (result != TCL_OK) {
+            return (Tcl_Command) NULL;
+        }
+    }
+    resPtr = (ResolvedCmdName *) objPtr->internalRep.otherValuePtr;
+
+    /*
+     * Get the current namespace.
+     */
+    
+    if (iPtr->varFramePtr != NULL) {
+	currNsPtr = iPtr->varFramePtr->nsPtr;
+    } else {
+	currNsPtr = iPtr->globalNsPtr;
+    }
+
+    /*
+     * Check the context namespace and the namespace epoch of the resolved
+     * symbol to make sure that it is fresh. If not, then force another
+     * conversion to the command type, to discard the old rep and create a
+     * new one. Note that we verify that the namespace id of the context
+     * namespace is the same as the one we cached; this insures that the
+     * namespace wasn't deleted and a new one created at the same address
+     * with the same command epoch.
+     */
+    
+    cmdPtr = NULL;
+    if ((resPtr != NULL)
+	    && (resPtr->refNsPtr == currNsPtr)
+	    && (resPtr->refNsId == currNsPtr->nsId)
+	    && (resPtr->refNsCmdEpoch == currNsPtr->cmdRefEpoch)) {
+        cmdPtr = resPtr->cmdPtr;
+        if (cmdPtr->cmdEpoch != resPtr->cmdEpoch) {
+            cmdPtr = NULL;
+        }
+    }
+
+    if (cmdPtr == NULL) {
+        result = tclCmdNameType.setFromAnyProc(interp, objPtr);
+        if (result != TCL_OK) {
+            return (Tcl_Command) NULL;
+        }
+        resPtr = (ResolvedCmdName *) objPtr->internalRep.otherValuePtr;
+        if (resPtr != NULL) {
+            cmdPtr = resPtr->cmdPtr;
+        }
+    }
+
+    if (cmdPtr == NULL) {
+	return (Tcl_Command) NULL;
+    }
+    return (Tcl_Command) cmdPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeCmdNameInternalRep --
+ *
+ *	Frees the resources associated with a cmdName object's internal
+ *	representation.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Decrements the ref count of any cached ResolvedCmdName structure
+ *	pointed to by the cmdName's internal representation. If this is 
+ *	the last use of the ResolvedCmdName, it is freed. This in turn
+ *	decrements the ref count of the Command structure pointed to by 
+ *	the ResolvedSymbol, which may free the Command structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeCmdNameInternalRep(objPtr)
+    register Tcl_Obj *objPtr;	/* CmdName object with internal
+				 * representation to free. */
+{
+    register ResolvedCmdName *resPtr =
+	(ResolvedCmdName *) objPtr->internalRep.otherValuePtr;
+
+    if (resPtr != NULL) {
+	/*
+	 * Decrement the reference count of the ResolvedCmdName structure.
+	 * If there are no more uses, free the ResolvedCmdName structure.
+	 */
+    
+        resPtr->refCount--;
+        if (resPtr->refCount == 0) {
+            /*
+	     * Now free the cached command, unless it is still in its
+             * hash table or if there are other references to it
+             * from other cmdName objects.
+	     */
+	    
+            Command *cmdPtr = resPtr->cmdPtr;
+            TclCleanupCommand(cmdPtr);
+            ckfree((char *) resPtr);
+        }
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupCmdNameInternalRep --
+ *
+ *	Initialize the internal representation of an cmdName Tcl_Obj to a
+ *	copy of the internal representation of an existing cmdName object. 
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	"copyPtr"s internal rep is set to point to the ResolvedCmdName
+ *	structure corresponding to "srcPtr"s internal rep. Increments the
+ *	ref count of the ResolvedCmdName structure pointed to by the
+ *	cmdName's internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DupCmdNameInternalRep(srcPtr, copyPtr)
+    Tcl_Obj *srcPtr;		/* Object with internal rep to copy. */
+    register Tcl_Obj *copyPtr;	/* Object with internal rep to set. */
+{
+    register ResolvedCmdName *resPtr =
+        (ResolvedCmdName *) srcPtr->internalRep.otherValuePtr;
+
+    copyPtr->internalRep.twoPtrValue.ptr1 = (VOID *) resPtr;
+    copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
+    if (resPtr != NULL) {
+        resPtr->refCount++;
+    }
+    copyPtr->typePtr = &tclCmdNameType;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetCmdNameFromAny --
+ *
+ *	Generate an cmdName internal form for the Tcl object "objPtr".
+ *
+ * Results:
+ *	The return value is a standard Tcl result. The conversion always
+ *	succeeds and TCL_OK is returned.
+ *
+ * Side effects:
+ *	A pointer to a ResolvedCmdName structure that holds a cached pointer
+ *	to the command with a name that matches objPtr's string rep is
+ *	stored as objPtr's internal representation. This ResolvedCmdName
+ *	pointer will be NULL if no matching command was found. The ref count
+ *	of the cached Command's structure (if any) is also incremented.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetCmdNameFromAny(interp, objPtr)
+    Tcl_Interp *interp;		/* Used for error reporting if not NULL. */
+    register Tcl_Obj *objPtr;	/* The object to convert. */
+{
+    Interp *iPtr = (Interp *) interp;
+    char *name;
+    Tcl_Command cmd;
+    register Command *cmdPtr;
+    Namespace *currNsPtr;
+    register ResolvedCmdName *resPtr;
+
+    /*
+     * Get "objPtr"s string representation. Make it up-to-date if necessary.
+     */
+
+    name = objPtr->bytes;
+    if (name == NULL) {
+	name = Tcl_GetStringFromObj(objPtr, (int *) NULL);
+    }
+
+    /*
+     * Find the Command structure, if any, that describes the command called
+     * "name". Build a ResolvedCmdName that holds a cached pointer to this
+     * Command, and bump the reference count in the referenced Command
+     * structure. A Command structure will not be deleted as long as it is
+     * referenced from a CmdName object.
+     */
+
+    cmd = Tcl_FindCommand(interp, name, (Tcl_Namespace *) NULL,
+	    /*flags*/ 0);
+    cmdPtr = (Command *) cmd;
+    if (cmdPtr != NULL) {
+	/*
+	 * Get the current namespace.
+	 */
+	
+	if (iPtr->varFramePtr != NULL) {
+	    currNsPtr = iPtr->varFramePtr->nsPtr;
+	} else {
+	    currNsPtr = iPtr->globalNsPtr;
+	}
+	
+	cmdPtr->refCount++;
+        resPtr = (ResolvedCmdName *) ckalloc(sizeof(ResolvedCmdName));
+        resPtr->cmdPtr        = cmdPtr;
+        resPtr->refNsPtr      = currNsPtr;
+        resPtr->refNsId       = currNsPtr->nsId;
+        resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
+        resPtr->cmdEpoch      = cmdPtr->cmdEpoch;
+        resPtr->refCount      = 1;
+    } else {
+	resPtr = NULL;	/* no command named "name" was found */
+    }
+
+    /*
+     * Free the old internalRep before setting the new one. We do this as
+     * late as possible to allow the conversion code, in particular
+     * GetStringFromObj, to use that old internalRep. If no Command
+     * structure was found, leave NULL as the cached value.
+     */
+
+    if ((objPtr->typePtr != NULL)
+	    && (objPtr->typePtr->freeIntRepProc != NULL)) {
+	objPtr->typePtr->freeIntRepProc(objPtr);
+    }
+    
+    objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) resPtr;
+    objPtr->internalRep.twoPtrValue.ptr2 = NULL;
+    objPtr->typePtr = &tclCmdNameType;
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateStringOfCmdName --
+ *
+ *	Update the string representation for an cmdName object.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Generates a panic. 
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateStringOfCmdName(objPtr)
+    Tcl_Obj *objPtr;		/* CmdName obj to update string rep. */
+{
+    /*
+     * This procedure is never invoked since the internal representation of
+     * a cmdName object is never modified.
+     */
+
+    panic("UpdateStringOfCmdName should never be invoked");
+}
+
+
+#ifdef TCL_COMPILE_DEBUG
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringForResultCode --
+ *
+ *	Procedure that returns a human-readable string representing a
+ *	Tcl result code such as TCL_ERROR. 
+ *
+ * Results:
+ *	If the result code is one of the standard Tcl return codes, the
+ *	result is a string representing that code such as "TCL_ERROR".
+ *	Otherwise, the result string is that code formatted as a
+ *	sequence of decimal digit characters. Note that the resulting
+ *	string must not be modified by the caller.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+StringForResultCode(result)
+    int result;			/* The Tcl result code for which to
+				 * generate a string. */
+{
+    static char buf[20];
+    
+    if ((result >= TCL_OK) && (result <= TCL_CONTINUE)) {
+	return resultStrings[result];
+    }
+    TclFormatInt(buf, result);
+    return buf;
+}
+#endif /* TCL_COMPILE_DEBUG */
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclGet.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclGet.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclGet.c	(revision 5)
@@ -0,0 +1,332 @@
+/* 
+ * tclGet.c --
+ *
+ *	This file contains procedures to convert strings into
+ *	other forms, like integers or floating-point numbers or
+ *	booleans, doing syntax checking along the way.
+ *
+ * Copyright (c) 1990-1993 The Regents of the University of California.
+ * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclGet.c,v 1.1 2008-06-04 13:58:06 demin Exp $
+ */
+
+#include "tclInt.h"
+#include "tclPort.h"
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetInt --
+ *
+ *	Given a string, produce the corresponding integer value.
+ *
+ * Results:
+ *	The return value is normally TCL_OK;  in this case *intPtr
+ *	will be set to the integer value equivalent to string.  If
+ *	string is improperly formed then TCL_ERROR is returned and
+ *	an error message will be left in interp->result.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetInt(interp, string, intPtr)
+    Tcl_Interp *interp;		/* Interpreter to use for error reporting. */
+    char *string;		/* String containing a (possibly signed)
+				 * integer in a form acceptable to strtol. */
+    int *intPtr;		/* Place to store converted result. */
+{
+    char *end, *p;
+    long i;
+
+    /*
+     * Note: use strtoul instead of strtol for integer conversions
+     * to allow full-size unsigned numbers, but don't depend on strtoul
+     * to handle sign characters;  it won't in some implementations.
+     */
+
+    errno = 0;
+    for (p = string; isspace(UCHAR(*p)); p++) {
+	/* Empty loop body. */
+    }
+    if (*p == '-') {
+	p++;
+	i = -((long)strtoul(p, &end, 0));
+    } else if (*p == '+') {
+	p++;
+	i = strtoul(p, &end, 0);
+    } else {
+	i = strtoul(p, &end, 0);
+    }
+    if (end == p) {
+	badInteger:
+        if (interp != (Tcl_Interp *) NULL) {
+            Tcl_AppendResult(interp, "expected integer but got \"", string,
+                    "\"", (char *) NULL);
+        }
+	return TCL_ERROR;
+    }
+
+    /*
+     * The second test below is needed on platforms where "long" is
+     * larger than "int" to detect values that fit in a long but not in
+     * an int.
+     */
+
+    if ((errno == ERANGE) || (((long)(int) i) != i)) {
+        if (interp != (Tcl_Interp *) NULL) {
+	    Tcl_SetResult(interp, "integer value too large to represent",
+		    TCL_STATIC);
+            Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
+                    interp->result, (char *) NULL);
+        }
+	return TCL_ERROR;
+    }
+    while ((*end != '\0') && isspace(UCHAR(*end))) {
+	end++;
+    }
+    if (*end != 0) {
+	goto badInteger;
+    }
+    *intPtr = (int) i;
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetLong --
+ *
+ *	Given a string, produce the corresponding long integer value.
+ *	This routine is a version of Tcl_GetInt but returns a "long"
+ *	instead of an "int".
+ *
+ * Results:
+ *	The return value is normally TCL_OK; in this case *longPtr
+ *	will be set to the long integer value equivalent to string. If
+ *	string is improperly formed then TCL_ERROR is returned and
+ *	an error message will be left in interp->result.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclGetLong(interp, string, longPtr)
+    Tcl_Interp *interp;		/* Interpreter used for error reporting. */
+    char *string;		/* String containing a (possibly signed)
+				 * long integer in a form acceptable to
+				 * strtoul. */
+    long *longPtr;		/* Place to store converted long result. */
+{
+    char *end, *p;
+    long i;
+
+    /*
+     * Note: don't depend on strtoul to handle sign characters; it won't
+     * in some implementations.
+     */
+
+    errno = 0;
+    for (p = string; isspace(UCHAR(*p)); p++) {
+	/* Empty loop body. */
+    }
+    if (*p == '-') {
+	p++;
+	i = -(int)strtoul(p, &end, 0);
+    } else if (*p == '+') {
+	p++;
+	i = strtoul(p, &end, 0);
+    } else {
+	i = strtoul(p, &end, 0);
+    }
+    if (end == p) {
+	badInteger:
+        if (interp != (Tcl_Interp *) NULL) {
+            Tcl_AppendResult(interp, "expected integer but got \"", string,
+                    "\"", (char *) NULL);
+        }
+	return TCL_ERROR;
+    }
+    if (errno == ERANGE) {
+        if (interp != (Tcl_Interp *) NULL) {
+	    Tcl_SetResult(interp, "integer value too large to represent",
+		    TCL_STATIC);
+            Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
+                    interp->result, (char *) NULL);
+        }
+	return TCL_ERROR;
+    }
+    while ((*end != '\0') && isspace(UCHAR(*end))) {
+	end++;
+    }
+    if (*end != 0) {
+	goto badInteger;
+    }
+    *longPtr = i;
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetDouble --
+ *
+ *	Given a string, produce the corresponding double-precision
+ *	floating-point value.
+ *
+ * Results:
+ *	The return value is normally TCL_OK; in this case *doublePtr
+ *	will be set to the double-precision value equivalent to string.
+ *	If string is improperly formed then TCL_ERROR is returned and
+ *	an error message will be left in interp->result.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetDouble(interp, string, doublePtr)
+    Tcl_Interp *interp;		/* Interpreter used for error reporting. */
+    char *string;		/* String containing a floating-point number
+				 * in a form acceptable to strtod. */
+    double *doublePtr;		/* Place to store converted result. */
+{
+    char *end;
+    double d;
+
+    errno = 0;
+    d = strtod(string, &end);
+    if (end == string) {
+	badDouble:
+        if (interp != (Tcl_Interp *) NULL) {
+            Tcl_AppendResult(interp,
+                    "expected floating-point number but got \"",
+                    string, "\"", (char *) NULL);
+        }
+	return TCL_ERROR;
+    }
+    if (errno != 0) {
+        if (interp != (Tcl_Interp *) NULL) {
+            TclExprFloatError(interp, d); /* sets interp->objResult */
+
+	    /*
+	     * Move the interpreter's object result to the string result, 
+	     * then reset the object result.
+	     * FAILS IF OBJECT RESULT'S STRING REPRESENTATION HAS NULLS.
+	     */
+
+	    Tcl_SetResult(interp,
+	            TclGetStringFromObj(Tcl_GetObjResult(interp),
+			    (int *) NULL),
+	            TCL_VOLATILE);
+        }
+	return TCL_ERROR;
+    }
+    while ((*end != 0) && isspace(UCHAR(*end))) {
+	end++;
+    }
+    if (*end != 0) {
+	goto badDouble;
+    }
+    *doublePtr = d;
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetBoolean --
+ *
+ *	Given a string, return a 0/1 boolean value corresponding
+ *	to the string.
+ *
+ * Results:
+ *	The return value is normally TCL_OK;  in this case *boolPtr
+ *	will be set to the 0/1 value equivalent to string.  If
+ *	string is improperly formed then TCL_ERROR is returned and
+ *	an error message will be left in interp->result.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetBoolean(interp, string, boolPtr)
+    Tcl_Interp *interp;		/* Interpreter used for error reporting. */
+    char *string;		/* String containing a boolean number
+				 * specified either as 1/0 or true/false or
+				 * yes/no. */
+    int *boolPtr;		/* Place to store converted result, which
+				 * will be 0 or 1. */
+{
+    int i;
+    char lowerCase[10], c;
+    size_t length;
+
+    /*
+     * Convert the input string to all lower-case.
+     */
+
+    for (i = 0; i < 9; i++) {
+	c = string[i];
+	if (c == 0) {
+	    break;
+	}
+	if ((c >= 'A') && (c <= 'Z')) {
+	    c += (char) ('a' - 'A');
+	}
+	lowerCase[i] = c;
+    }
+    lowerCase[i] = 0;
+
+    length = strlen(lowerCase);
+    c = lowerCase[0];
+    if ((c == '0') && (lowerCase[1] == '\0')) {
+	*boolPtr = 0;
+    } else if ((c == '1') && (lowerCase[1] == '\0')) {
+	*boolPtr = 1;
+    } else if ((c == 'y') && (strncmp(lowerCase, "yes", length) == 0)) {
+	*boolPtr = 1;
+    } else if ((c == 'n') && (strncmp(lowerCase, "no", length) == 0)) {
+	*boolPtr = 0;
+    } else if ((c == 't') && (strncmp(lowerCase, "true", length) == 0)) {
+	*boolPtr = 1;
+    } else if ((c == 'f') && (strncmp(lowerCase, "false", length) == 0)) {
+	*boolPtr = 0;
+    } else if ((c == 'o') && (length >= 2)) {
+	if (strncmp(lowerCase, "on", length) == 0) {
+	    *boolPtr = 1;
+	} else if (strncmp(lowerCase, "off", length) == 0) {
+	    *boolPtr = 0;
+	} else {
+	    goto badBoolean;
+	}
+    } else {
+	badBoolean:
+        if (interp != (Tcl_Interp *) NULL) {
+            Tcl_AppendResult(interp, "expected boolean value but got \"",
+                    string, "\"", (char *) NULL);
+        }
+	return TCL_ERROR;
+    }
+    return TCL_OK;
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclHash.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclHash.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclHash.c	(revision 5)
@@ -0,0 +1,937 @@
+/* 
+ * tclHash.c --
+ *
+ *	Implementation of in-memory hash tables for Tcl and Tcl-based
+ *	applications.
+ *
+ * Copyright (c) 1991-1993 The Regents of the University of California.
+ * Copyright (c) 1994 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclHash.c,v 1.1 2008-06-04 13:58:06 demin Exp $
+ */
+
+#include "tclInt.h"
+
+/*
+ * When there are this many entries per bucket, on average, rebuild
+ * the hash table to make it larger.
+ */
+
+#define REBUILD_MULTIPLIER	3
+
+
+/*
+ * The following macro takes a preliminary integer hash value and
+ * produces an index into a hash tables bucket list.  The idea is
+ * to make it so that preliminary values that are arbitrarily similar
+ * will end up in different buckets.  The hash function was taken
+ * from a random-number generator.
+ */
+
+#define RANDOM_INDEX(tablePtr, i) \
+    (((((long) (i))*1103515245) >> (tablePtr)->downShift) & (tablePtr)->mask)
+
+/*
+ * Procedure prototypes for static procedures in this file:
+ */
+
+static Tcl_HashEntry *	ArrayFind _ANSI_ARGS_((Tcl_HashTable *tablePtr,
+			    CONST char *key));
+static Tcl_HashEntry *	ArrayCreate _ANSI_ARGS_((Tcl_HashTable *tablePtr,
+			    CONST char *key, int *newPtr));
+static Tcl_HashEntry *	BogusFind _ANSI_ARGS_((Tcl_HashTable *tablePtr,
+			    CONST char *key));
+static Tcl_HashEntry *	BogusCreate _ANSI_ARGS_((Tcl_HashTable *tablePtr,
+			    CONST char *key, int *newPtr));
+static unsigned int	HashString _ANSI_ARGS_((CONST char *string));
+static void		RebuildTable _ANSI_ARGS_((Tcl_HashTable *tablePtr));
+static Tcl_HashEntry *	StringFind _ANSI_ARGS_((Tcl_HashTable *tablePtr,
+			    CONST char *key));
+static Tcl_HashEntry *	StringCreate _ANSI_ARGS_((Tcl_HashTable *tablePtr,
+			    CONST char *key, int *newPtr));
+static Tcl_HashEntry *	OneWordFind _ANSI_ARGS_((Tcl_HashTable *tablePtr,
+			    CONST char *key));
+static Tcl_HashEntry *	OneWordCreate _ANSI_ARGS_((Tcl_HashTable *tablePtr,
+			    CONST char *key, int *newPtr));
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_InitHashTable --
+ *
+ *	Given storage for a hash table, set up the fields to prepare
+ *	the hash table for use.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	TablePtr is now ready to be passed to Tcl_FindHashEntry and
+ *	Tcl_CreateHashEntry.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_InitHashTable(tablePtr, keyType)
+    register Tcl_HashTable *tablePtr;	/* Pointer to table record, which
+					 * is supplied by the caller. */
+    int keyType;			/* Type of keys to use in table:
+					 * TCL_STRING_KEYS, TCL_ONE_WORD_KEYS,
+					 * or an integer >= 2. */
+{
+    tablePtr->buckets = tablePtr->staticBuckets;
+    tablePtr->staticBuckets[0] = tablePtr->staticBuckets[1] = 0;
+    tablePtr->staticBuckets[2] = tablePtr->staticBuckets[3] = 0;
+    tablePtr->numBuckets = TCL_SMALL_HASH_TABLE;
+    tablePtr->numEntries = 0;
+    tablePtr->rebuildSize = TCL_SMALL_HASH_TABLE*REBUILD_MULTIPLIER;
+    tablePtr->downShift = 28;
+    tablePtr->mask = 3;
+    tablePtr->keyType = keyType;
+    if (keyType == TCL_STRING_KEYS) {
+	tablePtr->findProc = StringFind;
+	tablePtr->createProc = StringCreate;
+    } else if (keyType == TCL_ONE_WORD_KEYS) {
+	tablePtr->findProc = OneWordFind;
+	tablePtr->createProc = OneWordCreate;
+    } else {
+	tablePtr->findProc = ArrayFind;
+	tablePtr->createProc = ArrayCreate;
+    };
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DeleteHashEntry --
+ *
+ *	Remove a single entry from a hash table.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The entry given by entryPtr is deleted from its table and
+ *	should never again be used by the caller.  It is up to the
+ *	caller to free the clientData field of the entry, if that
+ *	is relevant.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DeleteHashEntry(entryPtr)
+    Tcl_HashEntry *entryPtr;
+{
+    register Tcl_HashEntry *prevPtr;
+
+    if (*entryPtr->bucketPtr == entryPtr) {
+	*entryPtr->bucketPtr = entryPtr->nextPtr;
+    } else {
+	for (prevPtr = *entryPtr->bucketPtr; ; prevPtr = prevPtr->nextPtr) {
+	    if (prevPtr == NULL) {
+		panic("malformed bucket chain in Tcl_DeleteHashEntry");
+	    }
+	    if (prevPtr->nextPtr == entryPtr) {
+		prevPtr->nextPtr = entryPtr->nextPtr;
+		break;
+	    }
+	}
+    }
+    entryPtr->tablePtr->numEntries--;
+    ckfree((char *) entryPtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DeleteHashTable --
+ *
+ *	Free up everything associated with a hash table except for
+ *	the record for the table itself.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The hash table is no longer useable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DeleteHashTable(tablePtr)
+    register Tcl_HashTable *tablePtr;		/* Table to delete. */
+{
+    register Tcl_HashEntry *hPtr, *nextPtr;
+    int i;
+
+    /*
+     * Free up all the entries in the table.
+     */
+
+    for (i = 0; i < tablePtr->numBuckets; i++) {
+	hPtr = tablePtr->buckets[i];
+	while (hPtr != NULL) {
+	    nextPtr = hPtr->nextPtr;
+	    ckfree((char *) hPtr);
+	    hPtr = nextPtr;
+	}
+    }
+
+    /*
+     * Free up the bucket array, if it was dynamically allocated.
+     */
+
+    if (tablePtr->buckets != tablePtr->staticBuckets) {
+	ckfree((char *) tablePtr->buckets);
+    }
+
+    /*
+     * Arrange for panics if the table is used again without
+     * re-initialization.
+     */
+
+    tablePtr->findProc = BogusFind;
+    tablePtr->createProc = BogusCreate;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_FirstHashEntry --
+ *
+ *	Locate the first entry in a hash table and set up a record
+ *	that can be used to step through all the remaining entries
+ *	of the table.
+ *
+ * Results:
+ *	The return value is a pointer to the first entry in tablePtr,
+ *	or NULL if tablePtr has no entries in it.  The memory at
+ *	*searchPtr is initialized so that subsequent calls to
+ *	Tcl_NextHashEntry will return all of the entries in the table,
+ *	one at a time.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_HashEntry *
+Tcl_FirstHashEntry(tablePtr, searchPtr)
+    Tcl_HashTable *tablePtr;		/* Table to search. */
+    Tcl_HashSearch *searchPtr;		/* Place to store information about
+					 * progress through the table. */
+{
+    searchPtr->tablePtr = tablePtr;
+    searchPtr->nextIndex = 0;
+    searchPtr->nextEntryPtr = NULL;
+    return Tcl_NextHashEntry(searchPtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_NextHashEntry --
+ *
+ *	Once a hash table enumeration has been initiated by calling
+ *	Tcl_FirstHashEntry, this procedure may be called to return
+ *	successive elements of the table.
+ *
+ * Results:
+ *	The return value is the next entry in the hash table being
+ *	enumerated, or NULL if the end of the table is reached.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_HashEntry *
+Tcl_NextHashEntry(searchPtr)
+    register Tcl_HashSearch *searchPtr;	/* Place to store information about
+					 * progress through the table.  Must
+					 * have been initialized by calling
+					 * Tcl_FirstHashEntry. */
+{
+    Tcl_HashEntry *hPtr;
+
+    while (searchPtr->nextEntryPtr == NULL) {
+	if (searchPtr->nextIndex >= searchPtr->tablePtr->numBuckets) {
+	    return NULL;
+	}
+	searchPtr->nextEntryPtr =
+		searchPtr->tablePtr->buckets[searchPtr->nextIndex];
+	searchPtr->nextIndex++;
+    }
+    hPtr = searchPtr->nextEntryPtr;
+    searchPtr->nextEntryPtr = hPtr->nextPtr;
+    return hPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_HashStats --
+ *
+ *	Return statistics describing the layout of the hash table
+ *	in its hash buckets.
+ *
+ * Results:
+ *	The return value is a malloc-ed string containing information
+ *	about tablePtr.  It is the caller's responsibility to free
+ *	this string.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_HashStats(tablePtr)
+    Tcl_HashTable *tablePtr;		/* Table for which to produce stats. */
+{
+#define NUM_COUNTERS 10
+    int count[NUM_COUNTERS], overflow, i, j;
+    double average, tmp;
+    register Tcl_HashEntry *hPtr;
+    char *result, *p;
+
+    /*
+     * Compute a histogram of bucket usage.
+     */
+
+    for (i = 0; i < NUM_COUNTERS; i++) {
+	count[i] = 0;
+    }
+    overflow = 0;
+    average = 0.0;
+    for (i = 0; i < tablePtr->numBuckets; i++) {
+	j = 0;
+	for (hPtr = tablePtr->buckets[i]; hPtr != NULL; hPtr = hPtr->nextPtr) {
+	    j++;
+	}
+	if (j < NUM_COUNTERS) {
+	    count[j]++;
+	} else {
+	    overflow++;
+	}
+	tmp = j;
+	average += (tmp+1.0)*(tmp/tablePtr->numEntries)/2.0;
+    }
+
+    /*
+     * Print out the histogram and a few other pieces of information.
+     */
+
+    result = (char *) ckalloc((unsigned) ((NUM_COUNTERS*60) + 300));
+    sprintf(result, "%d entries in table, %d buckets\n",
+	    tablePtr->numEntries, tablePtr->numBuckets);
+    p = result + strlen(result);
+    for (i = 0; i < NUM_COUNTERS; i++) {
+	sprintf(p, "number of buckets with %d entries: %d\n",
+		i, count[i]);
+	p += strlen(p);
+    }
+    sprintf(p, "number of buckets with %d or more entries: %d\n",
+	    NUM_COUNTERS, overflow);
+    p += strlen(p);
+    sprintf(p, "average search distance for entry: %.1f", average);
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HashString --
+ *
+ *	Compute a one-word summary of a text string, which can be
+ *	used to generate a hash index.
+ *
+ * Results:
+ *	The return value is a one-word summary of the information in
+ *	string.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static unsigned int
+HashString(string)
+    register CONST char *string;/* String from which to compute hash value. */
+{
+    register unsigned int result;
+    register int c;
+
+    /*
+     * I tried a zillion different hash functions and asked many other
+     * people for advice.  Many people had their own favorite functions,
+     * all different, but no-one had much idea why they were good ones.
+     * I chose the one below (multiply by 9 and add new character)
+     * because of the following reasons:
+     *
+     * 1. Multiplying by 10 is perfect for keys that are decimal strings,
+     *    and multiplying by 9 is just about as good.
+     * 2. Times-9 is (shift-left-3) plus (old).  This means that each
+     *    character's bits hang around in the low-order bits of the
+     *    hash value for ever, plus they spread fairly rapidly up to
+     *    the high-order bits to fill out the hash value.  This seems
+     *    works well both for decimal and non-decimal strings.
+     */
+
+    result = 0;
+    while (1) {
+	c = *string;
+	string++;
+	if (c == 0) {
+	    break;
+	}
+	result += (result<<3) + c;
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringFind --
+ *
+ *	Given a hash table with string keys, and a string key, find
+ *	the entry with a matching key.
+ *
+ * Results:
+ *	The return value is a token for the matching entry in the
+ *	hash table, or NULL if there was no matching entry.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_HashEntry *
+StringFind(tablePtr, key)
+    Tcl_HashTable *tablePtr;	/* Table in which to lookup entry. */
+    CONST char *key;		/* Key to use to find matching entry. */
+{
+    register Tcl_HashEntry *hPtr;
+    register CONST char *p1, *p2;
+    int index;
+
+    index = HashString(key) & tablePtr->mask;
+
+    /*
+     * Search all of the entries in the appropriate bucket.
+     */
+
+    for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
+	    hPtr = hPtr->nextPtr) {
+	for (p1 = key, p2 = hPtr->key.string; ; p1++, p2++) {
+	    if (*p1 != *p2) {
+		break;
+	    }
+	    if (*p1 == '\0') {
+		return hPtr;
+	    }
+	}
+    }
+    return NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringCreate --
+ *
+ *	Given a hash table with string keys, and a string key, find
+ *	the entry with a matching key.  If there is no matching entry,
+ *	then create a new entry that does match.
+ *
+ * Results:
+ *	The return value is a pointer to the matching entry.  If this
+ *	is a newly-created entry, then *newPtr will be set to a non-zero
+ *	value;  otherwise *newPtr will be set to 0.  If this is a new
+ *	entry the value stored in the entry will initially be 0.
+ *
+ * Side effects:
+ *	A new entry may be added to the hash table.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_HashEntry *
+StringCreate(tablePtr, key, newPtr)
+    Tcl_HashTable *tablePtr;	/* Table in which to lookup entry. */
+    CONST char *key;		/* Key to use to find or create matching
+				 * entry. */
+    int *newPtr;		/* Store info here telling whether a new
+				 * entry was created. */
+{
+    register Tcl_HashEntry *hPtr;
+    register CONST char *p1, *p2;
+    int index;
+
+    index = HashString(key) & tablePtr->mask;
+
+    /*
+     * Search all of the entries in this bucket.
+     */
+
+    for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
+	    hPtr = hPtr->nextPtr) {
+	for (p1 = key, p2 = hPtr->key.string; ; p1++, p2++) {
+	    if (*p1 != *p2) {
+		break;
+	    }
+	    if (*p1 == '\0') {
+		*newPtr = 0;
+		return hPtr;
+	    }
+	}
+    }
+
+    /*
+     * Entry not found.  Add a new one to the bucket.
+     */
+
+    *newPtr = 1;
+    hPtr = (Tcl_HashEntry *) ckalloc((unsigned)
+	    (sizeof(Tcl_HashEntry) + strlen(key) - (sizeof(hPtr->key) -1)));
+    hPtr->tablePtr = tablePtr;
+    hPtr->bucketPtr = &(tablePtr->buckets[index]);
+    hPtr->nextPtr = *hPtr->bucketPtr;
+    hPtr->clientData = 0;
+    strcpy(hPtr->key.string, key);
+    *hPtr->bucketPtr = hPtr;
+    tablePtr->numEntries++;
+
+    /*
+     * If the table has exceeded a decent size, rebuild it with many
+     * more buckets.
+     */
+
+    if (tablePtr->numEntries >= tablePtr->rebuildSize) {
+	RebuildTable(tablePtr);
+    }
+    return hPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * OneWordFind --
+ *
+ *	Given a hash table with one-word keys, and a one-word key, find
+ *	the entry with a matching key.
+ *
+ * Results:
+ *	The return value is a token for the matching entry in the
+ *	hash table, or NULL if there was no matching entry.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_HashEntry *
+OneWordFind(tablePtr, key)
+    Tcl_HashTable *tablePtr;	/* Table in which to lookup entry. */
+    register CONST char *key;	/* Key to use to find matching entry. */
+{
+    register Tcl_HashEntry *hPtr;
+    int index;
+
+    index = RANDOM_INDEX(tablePtr, key);
+
+    /*
+     * Search all of the entries in the appropriate bucket.
+     */
+
+    for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
+	    hPtr = hPtr->nextPtr) {
+	if (hPtr->key.oneWordValue == key) {
+	    return hPtr;
+	}
+    }
+    return NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * OneWordCreate --
+ *
+ *	Given a hash table with one-word keys, and a one-word key, find
+ *	the entry with a matching key.  If there is no matching entry,
+ *	then create a new entry that does match.
+ *
+ * Results:
+ *	The return value is a pointer to the matching entry.  If this
+ *	is a newly-created entry, then *newPtr will be set to a non-zero
+ *	value;  otherwise *newPtr will be set to 0.  If this is a new
+ *	entry the value stored in the entry will initially be 0.
+ *
+ * Side effects:
+ *	A new entry may be added to the hash table.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_HashEntry *
+OneWordCreate(tablePtr, key, newPtr)
+    Tcl_HashTable *tablePtr;	/* Table in which to lookup entry. */
+    register CONST char *key;	/* Key to use to find or create matching
+				 * entry. */
+    int *newPtr;		/* Store info here telling whether a new
+				 * entry was created. */
+{
+    register Tcl_HashEntry *hPtr;
+    int index;
+
+    index = RANDOM_INDEX(tablePtr, key);
+
+    /*
+     * Search all of the entries in this bucket.
+     */
+
+    for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
+	    hPtr = hPtr->nextPtr) {
+	if (hPtr->key.oneWordValue == key) {
+	    *newPtr = 0;
+	    return hPtr;
+	}
+    }
+
+    /*
+     * Entry not found.  Add a new one to the bucket.
+     */
+
+    *newPtr = 1;
+    hPtr = (Tcl_HashEntry *) ckalloc(sizeof(Tcl_HashEntry));
+    hPtr->tablePtr = tablePtr;
+    hPtr->bucketPtr = &(tablePtr->buckets[index]);
+    hPtr->nextPtr = *hPtr->bucketPtr;
+    hPtr->clientData = 0;
+    hPtr->key.oneWordValue = (char *) key;	/* CONST XXXX */
+    *hPtr->bucketPtr = hPtr;
+    tablePtr->numEntries++;
+
+    /*
+     * If the table has exceeded a decent size, rebuild it with many
+     * more buckets.
+     */
+
+    if (tablePtr->numEntries >= tablePtr->rebuildSize) {
+	RebuildTable(tablePtr);
+    }
+    return hPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ArrayFind --
+ *
+ *	Given a hash table with array-of-int keys, and a key, find
+ *	the entry with a matching key.
+ *
+ * Results:
+ *	The return value is a token for the matching entry in the
+ *	hash table, or NULL if there was no matching entry.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_HashEntry *
+ArrayFind(tablePtr, key)
+    Tcl_HashTable *tablePtr;	/* Table in which to lookup entry. */
+    CONST char *key;		/* Key to use to find matching entry. */
+{
+    register Tcl_HashEntry *hPtr;
+    int *arrayPtr = (int *) key;
+    register int *iPtr1, *iPtr2;
+    int index, count;
+
+    for (index = 0, count = tablePtr->keyType, iPtr1 = arrayPtr;
+	    count > 0; count--, iPtr1++) {
+	index += *iPtr1;
+    }
+    index = RANDOM_INDEX(tablePtr, index);
+
+    /*
+     * Search all of the entries in the appropriate bucket.
+     */
+
+    for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
+	    hPtr = hPtr->nextPtr) {
+	for (iPtr1 = arrayPtr, iPtr2 = hPtr->key.words,
+		count = tablePtr->keyType; ; count--, iPtr1++, iPtr2++) {
+	    if (count == 0) {
+		return hPtr;
+	    }
+	    if (*iPtr1 != *iPtr2) {
+		break;
+	    }
+	}
+    }
+    return NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ArrayCreate --
+ *
+ *	Given a hash table with one-word keys, and a one-word key, find
+ *	the entry with a matching key.  If there is no matching entry,
+ *	then create a new entry that does match.
+ *
+ * Results:
+ *	The return value is a pointer to the matching entry.  If this
+ *	is a newly-created entry, then *newPtr will be set to a non-zero
+ *	value;  otherwise *newPtr will be set to 0.  If this is a new
+ *	entry the value stored in the entry will initially be 0.
+ *
+ * Side effects:
+ *	A new entry may be added to the hash table.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_HashEntry *
+ArrayCreate(tablePtr, key, newPtr)
+    Tcl_HashTable *tablePtr;	/* Table in which to lookup entry. */
+    register CONST char *key;	/* Key to use to find or create matching
+				 * entry. */
+    int *newPtr;		/* Store info here telling whether a new
+				 * entry was created. */
+{
+    register Tcl_HashEntry *hPtr;
+    int *arrayPtr = (int *) key;
+    register int *iPtr1, *iPtr2;
+    int index, count;
+
+    for (index = 0, count = tablePtr->keyType, iPtr1 = arrayPtr;
+	    count > 0; count--, iPtr1++) {
+	index += *iPtr1;
+    }
+    index = RANDOM_INDEX(tablePtr, index);
+
+    /*
+     * Search all of the entries in the appropriate bucket.
+     */
+
+    for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
+	    hPtr = hPtr->nextPtr) {
+	for (iPtr1 = arrayPtr, iPtr2 = hPtr->key.words,
+		count = tablePtr->keyType; ; count--, iPtr1++, iPtr2++) {
+	    if (count == 0) {
+		*newPtr = 0;
+		return hPtr;
+	    }
+	    if (*iPtr1 != *iPtr2) {
+		break;
+	    }
+	}
+    }
+
+    /*
+     * Entry not found.  Add a new one to the bucket.
+     */
+
+    *newPtr = 1;
+    hPtr = (Tcl_HashEntry *) ckalloc((unsigned) (sizeof(Tcl_HashEntry)
+	    + (tablePtr->keyType*sizeof(int)) - 4));
+    hPtr->tablePtr = tablePtr;
+    hPtr->bucketPtr = &(tablePtr->buckets[index]);
+    hPtr->nextPtr = *hPtr->bucketPtr;
+    hPtr->clientData = 0;
+    for (iPtr1 = arrayPtr, iPtr2 = hPtr->key.words, count = tablePtr->keyType;
+	    count > 0; count--, iPtr1++, iPtr2++) {
+	*iPtr2 = *iPtr1;
+    }
+    *hPtr->bucketPtr = hPtr;
+    tablePtr->numEntries++;
+
+    /*
+     * If the table has exceeded a decent size, rebuild it with many
+     * more buckets.
+     */
+
+    if (tablePtr->numEntries >= tablePtr->rebuildSize) {
+	RebuildTable(tablePtr);
+    }
+    return hPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BogusFind --
+ *
+ *	This procedure is invoked when an Tcl_FindHashEntry is called
+ *	on a table that has been deleted.
+ *
+ * Results:
+ *	If panic returns (which it shouldn't) this procedure returns
+ *	NULL.
+ *
+ * Side effects:
+ *	Generates a panic.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+static Tcl_HashEntry *
+BogusFind(tablePtr, key)
+    Tcl_HashTable *tablePtr;	/* Table in which to lookup entry. */
+    CONST char *key;		/* Key to use to find matching entry. */
+{
+    panic("called Tcl_FindHashEntry on deleted table");
+    return NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BogusCreate --
+ *
+ *	This procedure is invoked when an Tcl_CreateHashEntry is called
+ *	on a table that has been deleted.
+ *
+ * Results:
+ *	If panic returns (which it shouldn't) this procedure returns
+ *	NULL.
+ *
+ * Side effects:
+ *	Generates a panic.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+static Tcl_HashEntry *
+BogusCreate(tablePtr, key, newPtr)
+    Tcl_HashTable *tablePtr;	/* Table in which to lookup entry. */
+    CONST char *key;		/* Key to use to find or create matching
+				 * entry. */
+    int *newPtr;		/* Store info here telling whether a new
+				 * entry was created. */
+{
+    panic("called Tcl_CreateHashEntry on deleted table");
+    return NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RebuildTable --
+ *
+ *	This procedure is invoked when the ratio of entries to hash
+ *	buckets becomes too large.  It creates a new table with a
+ *	larger bucket array and moves all of the entries into the
+ *	new table.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Memory gets reallocated and entries get re-hashed to new
+ *	buckets.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RebuildTable(tablePtr)
+    register Tcl_HashTable *tablePtr;	/* Table to enlarge. */
+{
+    int oldSize, count, index;
+    Tcl_HashEntry **oldBuckets;
+    register Tcl_HashEntry **oldChainPtr, **newChainPtr;
+    register Tcl_HashEntry *hPtr;
+
+    oldSize = tablePtr->numBuckets;
+    oldBuckets = tablePtr->buckets;
+
+    /*
+     * Allocate and initialize the new bucket array, and set up
+     * hashing constants for new array size.
+     */
+
+    tablePtr->numBuckets *= 4;
+    tablePtr->buckets = (Tcl_HashEntry **) ckalloc((unsigned)
+	    (tablePtr->numBuckets * sizeof(Tcl_HashEntry *)));
+    for (count = tablePtr->numBuckets, newChainPtr = tablePtr->buckets;
+	    count > 0; count--, newChainPtr++) {
+	*newChainPtr = NULL;
+    }
+    tablePtr->rebuildSize *= 4;
+    tablePtr->downShift -= 2;
+    tablePtr->mask = (tablePtr->mask << 2) + 3;
+
+    /*
+     * Rehash all of the existing entries into the new bucket array.
+     */
+
+    for (oldChainPtr = oldBuckets; oldSize > 0; oldSize--, oldChainPtr++) {
+	for (hPtr = *oldChainPtr; hPtr != NULL; hPtr = *oldChainPtr) {
+	    *oldChainPtr = hPtr->nextPtr;
+	    if (tablePtr->keyType == TCL_STRING_KEYS) {
+		index = HashString(hPtr->key.string) & tablePtr->mask;
+	    } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {
+		index = RANDOM_INDEX(tablePtr, hPtr->key.oneWordValue);
+	    } else {
+		register int *iPtr;
+		int count;
+
+		for (index = 0, count = tablePtr->keyType,
+			iPtr = hPtr->key.words; count > 0; count--, iPtr++) {
+		    index += *iPtr;
+		}
+		index = RANDOM_INDEX(tablePtr, index);
+	    }
+	    hPtr->bucketPtr = &(tablePtr->buckets[index]);
+	    hPtr->nextPtr = *hPtr->bucketPtr;
+	    *hPtr->bucketPtr = hPtr;
+	}
+    }
+
+    /*
+     * Free up the old bucket array, if it was dynamically allocated.
+     */
+
+    if (oldBuckets != tablePtr->staticBuckets) {
+	ckfree((char *) oldBuckets);
+    }
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclHistory.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclHistory.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclHistory.c	(revision 5)
@@ -0,0 +1,157 @@
+/* 
+ * tclHistory.c --
+ *
+ *	This module and the Tcl library file history.tcl together implement
+ *	Tcl command history. Tcl_RecordAndEval(Obj) can be called to record
+ *	commands ("events") before they are executed. Commands defined in
+ *	history.tcl may be used to perform history substitutions.
+ *
+ * Copyright (c) 1990-1993 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclHistory.c,v 1.1 2008-06-04 13:58:06 demin Exp $
+ */
+
+#include "tclInt.h"
+#include "tclPort.h"
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_RecordAndEval --
+ *
+ *	This procedure adds its command argument to the current list of
+ *	recorded events and then executes the command by calling
+ *	Tcl_Eval.
+ *
+ * Results:
+ *	The return value is a standard Tcl return value, the result of
+ *	executing cmd.
+ *
+ * Side effects:
+ *	The command is recorded and executed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_RecordAndEval(interp, cmd, flags)
+    Tcl_Interp *interp;		/* Token for interpreter in which command
+				 * will be executed. */
+    char *cmd;			/* Command to record. */
+    int flags;			/* Additional flags.  TCL_NO_EVAL means
+				 * only record: don't execute command.
+				 * TCL_EVAL_GLOBAL means use Tcl_GlobalEval
+				 * instead of Tcl_Eval. */
+{
+    register Tcl_Obj *cmdPtr;
+    int length = strlen(cmd);
+    int result;
+
+    if (length > 0) {
+	/*
+	 * Call Tcl_RecordAndEvalObj to do the actual work.
+	 */
+
+	TclNewObj(cmdPtr);
+	TclInitStringRep(cmdPtr, cmd, length);
+	Tcl_IncrRefCount(cmdPtr);
+
+	result = Tcl_RecordAndEvalObj(interp, cmdPtr, flags);
+
+	/*
+	 * Move the interpreter's object result to the string result, 
+	 * then reset the object result.
+	 * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS.
+	 */
+
+	Tcl_SetResult(interp,
+	        TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL),
+	        TCL_VOLATILE);
+
+	/*
+	 * Discard the Tcl object created to hold the command.
+	 */
+	
+	Tcl_DecrRefCount(cmdPtr);	
+    } else {
+	/*
+	 * An empty string. Just reset the interpreter's result.
+	 */
+
+	Tcl_ResetResult(interp);
+	result = TCL_OK;
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_RecordAndEvalObj --
+ *
+ *	This procedure adds the command held in its argument object to the
+ *	current list of recorded events and then executes the command by
+ *	calling Tcl_EvalObj.
+ *
+ * Results:
+ *	The return value is a standard Tcl return value, the result of
+ *	executing the command.
+ *
+ * Side effects:
+ *	The command is recorded and executed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_RecordAndEvalObj(interp, cmdPtr, flags)
+    Tcl_Interp *interp;		/* Token for interpreter in which command
+				 * will be executed. */
+    Tcl_Obj *cmdPtr;		/* Points to object holding the command to
+				 * record and execute. */
+    int flags;			/* Additional flags. TCL_NO_EVAL means
+				 * record only: don't execute the command.
+				 * TCL_EVAL_GLOBAL means use
+				 * Tcl_GlobalEvalObj instead of
+				 * Tcl_EvalObj. */
+{
+    Interp *iPtr = (Interp *) interp;
+    int result;
+    Tcl_Obj *list[3];
+    register Tcl_Obj *objPtr;
+
+    /*
+     * Do recording by eval'ing a tcl history command: history add $cmd.
+     */
+
+    list[0] = Tcl_NewStringObj("history", -1);
+    list[1] = Tcl_NewStringObj("add", -1);
+    list[2] = cmdPtr;
+    
+    objPtr = Tcl_NewListObj(3, list);
+    Tcl_IncrRefCount(objPtr);
+    (void) Tcl_GlobalEvalObj(interp, objPtr);
+    Tcl_DecrRefCount(objPtr);
+
+    /*
+     * Execute the command.
+     */
+
+    result = TCL_OK;
+    if (!(flags & TCL_NO_EVAL)) {
+	iPtr->evalFlags = (flags & ~TCL_EVAL_GLOBAL);
+	if (flags & TCL_EVAL_GLOBAL) {
+	    result = Tcl_GlobalEvalObj(interp, cmdPtr);
+	} else {
+	    result = Tcl_EvalObj(interp, cmdPtr);
+	}
+    }
+    return result;
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclIndexObj.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclIndexObj.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclIndexObj.c	(revision 5)
@@ -0,0 +1,313 @@
+/* 
+ * tclIndexObj.c --
+ *
+ *	This file implements objects of type "index".  This object type
+ *	is used to lookup a keyword in a table of valid values and cache
+ *	the index of the matching entry.
+ *
+ * Copyright (c) 1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclIndexObj.c,v 1.1 2008-06-04 13:58:07 demin Exp $
+ */
+
+#include "tclInt.h"
+
+/*
+ * Prototypes for procedures defined later in this file:
+ */
+
+static void		DupIndexInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
+			    Tcl_Obj *copyPtr));
+static int		SetIndexFromAny _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr));
+static void		UpdateStringOfIndex _ANSI_ARGS_((Tcl_Obj *listPtr));
+
+/*
+ * The structure below defines the index Tcl object type by means of
+ * procedures that can be invoked by generic object code.
+ */
+
+Tcl_ObjType tclIndexType = {
+    "index",				/* name */
+    (Tcl_FreeInternalRepProc *) NULL,	/* freeIntRepProc */
+    DupIndexInternalRep,	        /* dupIntRepProc */
+    UpdateStringOfIndex,		/* updateStringProc */
+    SetIndexFromAny			/* setFromAnyProc */
+};
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetIndexFromObj --
+ *
+ *	This procedure looks up an object's value in a table of strings
+ *	and returns the index of the matching string, if any.
+ *
+ * Results:
+
+ *	If the value of objPtr is identical to or a unique abbreviation
+ *	for one of the entries in objPtr, then the return value is
+ *	TCL_OK and the index of the matching entry is stored at
+ *	*indexPtr.  If there isn't a proper match, then TCL_ERROR is
+ *	returned and an error message is left in interp's result (unless
+ *	interp is NULL).  The msg argument is used in the error
+ *	message; for example, if msg has the value "option" then the
+ *	error message will say something flag 'bad option "foo": must be
+ *	...'
+ *
+ * Side effects:
+ *	The result of the lookup is cached as the internal rep of
+ *	objPtr, so that repeated lookups can be done quickly.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetIndexFromObj(interp, objPtr, tablePtr, msg, flags, indexPtr)
+    Tcl_Interp *interp; 	/* Used for error reporting if not NULL. */
+    Tcl_Obj *objPtr;		/* Object containing the string to lookup. */
+    char **tablePtr;		/* Array of strings to compare against the
+				 * value of objPtr; last entry must be NULL
+				 * and there must not be duplicate entries. */
+    char *msg;			/* Identifying word to use in error messages. */
+    int flags;			/* 0 or TCL_EXACT */
+    int *indexPtr;		/* Place to store resulting integer index. */
+{
+    int index, length, i, numAbbrev;
+    char *key, *p1, *p2, **entryPtr;
+    Tcl_Obj *resultPtr;
+
+    /*
+     * See if there is a valid cached result from a previous lookup.
+     */
+
+    if ((objPtr->typePtr == &tclIndexType)
+	    && (objPtr->internalRep.twoPtrValue.ptr1 == (VOID *) tablePtr)) {
+	*indexPtr = (int) objPtr->internalRep.twoPtrValue.ptr2;
+	return TCL_OK;
+    }
+
+    /*
+     * Lookup the value of the object in the table.  Accept unique
+     * abbreviations unless TCL_EXACT is set in flags.
+     */
+
+    key = Tcl_GetStringFromObj(objPtr, &length);
+    index = -1;
+    numAbbrev = 0;
+    for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) {
+	for (p1 = key, p2 = *entryPtr; *p1 == *p2; p1++, p2++) {
+	    if (*p1 == 0) {
+		index = i;
+		goto done;
+	    }
+	}
+	if (*p1 == 0) {
+	    /*
+	     * The value is an abbreviation for this entry.  Continue
+	     * checking other entries to make sure it's unique.  If we
+	     * get more than one unique abbreviation, keep searching to
+	     * see if there is an exact match, but remember the number
+	     * of unique abbreviations and don't allow either.
+	     */
+
+	    numAbbrev++;
+	    index = i;
+	}
+    }
+    if ((flags & TCL_EXACT) || (numAbbrev != 1)) {
+	goto error;
+    }
+
+    done:
+    if ((objPtr->typePtr != NULL)
+	    && (objPtr->typePtr->freeIntRepProc != NULL)) {
+	objPtr->typePtr->freeIntRepProc(objPtr);
+    }
+    objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) tablePtr;
+    objPtr->internalRep.twoPtrValue.ptr2 = (VOID *) index;
+    objPtr->typePtr = &tclIndexType;
+    *indexPtr = index;
+    return TCL_OK;
+
+    error:
+    if (interp != NULL) {
+	resultPtr = Tcl_GetObjResult(interp);
+	Tcl_AppendStringsToObj(resultPtr,
+		(numAbbrev > 1) ? "ambiguous " : "bad ", msg, " \"",
+		key, "\": must be ", *tablePtr, (char *) NULL);
+	for (entryPtr = tablePtr+1; *entryPtr != NULL; entryPtr++) {
+	    if (entryPtr[1] == NULL) {
+		Tcl_AppendStringsToObj(resultPtr, ", or ", *entryPtr,
+			(char *) NULL);
+	    } else {
+		Tcl_AppendStringsToObj(resultPtr, ", ", *entryPtr,
+			(char *) NULL);
+	    }
+	}
+    }
+    return TCL_ERROR;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupIndexInternalRep --
+ *
+ *	Copy the internal representation of an index Tcl_Obj from one
+ *	object to another.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	"copyPtr"s internal rep is set to same value as "srcPtr"s
+ *	internal rep.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DupIndexInternalRep(srcPtr, copyPtr)
+    register Tcl_Obj *srcPtr;	/* Object with internal rep to copy. */
+    register Tcl_Obj *copyPtr;	/* Object with internal rep to set. */
+{
+    copyPtr->internalRep.twoPtrValue.ptr1
+	    = srcPtr->internalRep.twoPtrValue.ptr1;
+    copyPtr->internalRep.twoPtrValue.ptr2
+	    = srcPtr->internalRep.twoPtrValue.ptr2;
+    copyPtr->typePtr = &tclIndexType;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetIndexFromAny --
+ *
+ *	This procedure is called to convert a Tcl object to index
+ *	internal form. However, this doesn't make sense (need to have a
+ *	table of keywords in order to do the conversion) so the
+ *	procedure always generates an error.
+ *
+ * Results:
+ *	The return value is always TCL_ERROR, and an error message is
+ *	left in interp's result if interp isn't NULL. 
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetIndexFromAny(interp, objPtr)
+    Tcl_Interp *interp;		/* Used for error reporting if not NULL. */
+    register Tcl_Obj *objPtr;	/* The object to convert. */
+{
+    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	    "can't convert value to index except via Tcl_GetIndexFromObj API",
+	    -1);
+    return TCL_ERROR;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateStringOfIndex --
+ *
+ *	This procedure is called to update the string representation for
+ *	an index object.  It should never be called, because we never
+ *	invalidate the string representation for an index object.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	A panic is added
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateStringOfIndex(objPtr)
+    register Tcl_Obj *objPtr;	/* Int object whose string rep to update. */
+{
+    panic("UpdateStringOfIndex should never be invoked");
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_WrongNumArgs --
+ *
+ *	This procedure generates a "wrong # args" error message in an
+ *	interpreter.  It is used as a utility function by many command
+ *	procedures.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	An error message is generated in interp's result object to
+ *	indicate that a command was invoked with the wrong number of
+ *	arguments.  The message has the form
+ *		wrong # args: should be "foo bar additional stuff"
+ *	where "foo" and "bar" are the initial objects in objv (objc
+ *	determines how many of these are printed) and "additional stuff"
+ *	is the contents of the message argument.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_WrongNumArgs(interp, objc, objv, message)
+    Tcl_Interp *interp;			/* Current interpreter. */
+    int objc;				/* Number of arguments to print
+					 * from objv. */
+    Tcl_Obj *CONST objv[];		/* Initial argument objects, which
+					 * should be included in the error
+					 * message. */
+    char *message;			/* Error message to print after the
+					 * leading objects in objv. The
+					 * message may be NULL. */
+{
+    Tcl_Obj *objPtr;
+    char **tablePtr;
+    int i;
+
+    objPtr = Tcl_GetObjResult(interp);
+    Tcl_AppendToObj(objPtr, "wrong # args: should be \"", -1);
+    for (i = 0; i < objc; i++) {
+	/*
+	 * If the object is an index type use the index table which allows
+	 * for the correct error message even if the subcommand was
+	 * abbreviated.  Otherwise, just use the string rep.
+	 */
+	
+	if (objv[i]->typePtr == &tclIndexType) {
+	    tablePtr = ((char **) objv[i]->internalRep.twoPtrValue.ptr1);
+	    Tcl_AppendStringsToObj(objPtr,
+		    tablePtr[(int) objv[i]->internalRep.twoPtrValue.ptr2],
+		    (char *) NULL);
+	} else {
+	    Tcl_AppendStringsToObj(objPtr,
+		    Tcl_GetStringFromObj(objv[i], (int *) NULL),
+		    (char *) NULL);
+	}
+	if (i < (objc - 1)) {
+	    Tcl_AppendStringsToObj(objPtr, " ", (char *) NULL);
+	}
+    }
+    if (message) {
+      Tcl_AppendStringsToObj(objPtr, " ", message, (char *) NULL);
+    }
+    Tcl_AppendStringsToObj(objPtr, "\"", (char *) NULL);
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclInt.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclInt.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclInt.h	(revision 5)
@@ -0,0 +1,1915 @@
+/*
+ * tclInt.h --
+ *
+ *	Declarations of things used internally by the Tcl interpreter.
+ *
+ * Copyright (c) 1987-1993 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1993-1997 Lucent Technologies.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclInt.h,v 1.1 2008-06-04 13:58:07 demin Exp $
+ */
+
+#ifndef _TCLINT
+#define _TCLINT
+
+/*
+ * Common include files needed by most of the Tcl source files are
+ * included here, so that system-dependent personalizations for the
+ * include files only have to be made in once place.  This results
+ * in a few extra includes, but greater modularity.  The order of
+ * the three groups of #includes is important.	For example, stdio.h
+ * is needed by tcl.h, and the _ANSI_ARGS_ declaration in tcl.h is
+ * needed by stdlib.h in some configurations.
+ */
+
+#include <stdio.h>
+
+#ifndef _TCL
+#include "tcl.h"
+#endif
+
+#include <ctype.h>
+#ifdef NO_LIMITS_H
+#   include "../compat/limits.h"
+#else
+#   include <limits.h>
+#endif
+#ifdef NO_STDLIB_H
+#   include "../compat/stdlib.h"
+#else
+#   include <stdlib.h>
+#endif
+#ifdef NO_STRING_H
+#include "../compat/string.h"
+#else
+#include <string.h>
+#endif
+#if defined(__STDC__) || defined(HAS_STDARG)
+#   include <stdarg.h>
+#else
+#   include <varargs.h>
+#endif
+
+#ifdef BUILD_tcl
+# undef TCL_STORAGE_CLASS
+# define TCL_STORAGE_CLASS DLLEXPORT
+#endif
+
+/*
+ * The following procedures allow namespaces to be customized to
+ * support special name resolution rules for commands/variables.
+ * 
+ */
+
+struct Tcl_ResolvedVarInfo;
+
+typedef Tcl_Var (Tcl_ResolveRuntimeVarProc) _ANSI_ARGS_((
+    Tcl_Interp* interp, struct Tcl_ResolvedVarInfo *vinfoPtr));
+
+typedef void (Tcl_ResolveVarDeleteProc) _ANSI_ARGS_((
+    struct Tcl_ResolvedVarInfo *vinfoPtr));
+
+/*
+ * The following structure encapsulates the routines needed to resolve a
+ * variable reference at runtime.  Any variable specific state will typically
+ * be appended to this structure.
+ */
+
+
+typedef struct Tcl_ResolvedVarInfo {
+    Tcl_ResolveRuntimeVarProc *fetchProc;
+    Tcl_ResolveVarDeleteProc *deleteProc;
+} Tcl_ResolvedVarInfo;
+
+
+
+typedef int (Tcl_ResolveCompiledVarProc) _ANSI_ARGS_((
+    Tcl_Interp* interp, char* name, int length,
+    Tcl_Namespace *context, Tcl_ResolvedVarInfo **rPtr));
+
+typedef int (Tcl_ResolveVarProc) _ANSI_ARGS_((
+    Tcl_Interp* interp, char* name, Tcl_Namespace *context,
+    int flags, Tcl_Var *rPtr));
+
+typedef int (Tcl_ResolveCmdProc) _ANSI_ARGS_((Tcl_Interp* interp,
+	char* name, Tcl_Namespace *context, int flags,
+	Tcl_Command *rPtr));
+ 
+typedef struct Tcl_ResolverInfo {
+    Tcl_ResolveCmdProc *cmdResProc;	/* Procedure handling command name
+					 * resolution. */
+    Tcl_ResolveVarProc *varResProc;	/* Procedure handling variable name
+					 * resolution for variables that
+					 * can only be handled at runtime. */
+    Tcl_ResolveCompiledVarProc *compiledVarResProc;
+					/* Procedure handling variable name
+					 * resolution at compile time. */
+} Tcl_ResolverInfo;
+
+/*
+ *----------------------------------------------------------------
+ * Data structures related to namespaces.
+ *----------------------------------------------------------------
+ */
+
+/*
+ * The structure below defines a namespace.
+ * Note: the first five fields must match exactly the fields in a
+ * Tcl_Namespace structure (see tcl.h). If you change one, be sure to
+ * change the other.
+ */
+
+typedef struct Namespace {
+    char *name;			 /* The namespace's simple (unqualified)
+				  * name. This contains no ::'s. The name of
+				  * the global namespace is "" although "::"
+				  * is an synonym. */
+    char *fullName;		 /* The namespace's fully qualified name.
+				  * This starts with ::. */
+    ClientData clientData;	 /* An arbitrary value associated with this
+				  * namespace. */
+    Tcl_NamespaceDeleteProc *deleteProc;
+				 /* Procedure invoked when deleting the
+				  * namespace to, e.g., free clientData. */
+    struct Namespace *parentPtr; /* Points to the namespace that contains
+				  * this one. NULL if this is the global
+				  * namespace. */
+    Tcl_HashTable childTable;	 /* Contains any child namespaces. Indexed
+				  * by strings; values have type
+				  * (Namespace *). */
+    long nsId;			 /* Unique id for the namespace. */
+    Tcl_Interp *interp;		 /* The interpreter containing this
+				  * namespace. */
+    int flags;			 /* OR-ed combination of the namespace
+				  * status flags NS_DYING and NS_DEAD
+				  * listed below. */
+    int activationCount;	 /* Number of "activations" or active call
+				  * frames for this namespace that are on
+				  * the Tcl call stack. The namespace won't
+				  * be freed until activationCount becomes
+				  * zero. */
+    int refCount;		 /* Count of references by namespaceName *
+				  * objects. The namespace can't be freed
+				  * until refCount becomes zero. */
+    Tcl_HashTable cmdTable;	 /* Contains all the commands currently
+				  * registered in the namespace. Indexed by
+				  * strings; values have type (Command *).
+				  * Commands imported by Tcl_Import have
+				  * Command structures that point (via an
+				  * ImportedCmdRef structure) to the
+				  * Command structure in the source
+				  * namespace's command table. */
+    Tcl_HashTable varTable;	 /* Contains all the (global) variables
+				  * currently in this namespace. Indexed
+				  * by strings; values have type (Var *). */
+    char **exportArrayPtr;	 /* Points to an array of string patterns
+				  * specifying which commands are exported.
+				  * A pattern may include "string match"
+				  * style wildcard characters to specify
+				  * multiple commands; however, no namespace
+				  * qualifiers are allowed. NULL if no
+				  * export patterns are registered. */
+    int numExportPatterns;	 /* Number of export patterns currently
+				  * registered using "namespace export". */
+    int maxExportPatterns;	 /* Mumber of export patterns for which
+				  * space is currently allocated. */
+    int cmdRefEpoch;		 /* Incremented if a newly added command
+				  * shadows a command for which this
+				  * namespace has already cached a Command *
+				  * pointer; this causes all its cached
+				  * Command* pointers to be invalidated. */
+    int resolverEpoch;		 /* Incremented whenever the name resolution
+				  * rules change for this namespace; this
+				  * invalidates all byte codes compiled in
+				  * the namespace, causing the code to be
+				  * recompiled under the new rules. */
+    Tcl_ResolveCmdProc *cmdResProc;
+				 /* If non-null, this procedure overrides
+				  * the usual command resolution mechanism
+				  * in Tcl.  This procedure is invoked
+				  * within Tcl_FindCommand to resolve all
+				  * command references within the namespace. */
+    Tcl_ResolveVarProc *varResProc;
+				 /* If non-null, this procedure overrides
+				  * the usual variable resolution mechanism
+				  * in Tcl.  This procedure is invoked
+				  * within Tcl_FindNamespaceVar to resolve all
+				  * variable references within the namespace
+				  * at runtime. */
+    Tcl_ResolveCompiledVarProc *compiledVarResProc;
+				 /* If non-null, this procedure overrides
+				  * the usual variable resolution mechanism
+				  * in Tcl.  This procedure is invoked
+				  * within LookupCompiledLocal to resolve
+				  * variable references within the namespace
+				  * at compile time. */
+} Namespace;
+
+/*
+ * Flags used to represent the status of a namespace:
+ *
+ * NS_DYING -	1 means Tcl_DeleteNamespace has been called to delete the
+ *		namespace but there are still active call frames on the Tcl
+ *		stack that refer to the namespace. When the last call frame
+ *		referring to it has been popped, it's variables and command
+ *		will be destroyed and it will be marked "dead" (NS_DEAD).
+ *		The namespace can no longer be looked up by name.
+ * NS_DEAD -	1 means Tcl_DeleteNamespace has been called to delete the
+ *		namespace and no call frames still refer to it. Its
+ *		variables and command have already been destroyed. This bit
+ *		allows the namespace resolution code to recognize that the
+ *		namespace is "deleted". When the last namespaceName object
+ *		in any byte code code unit that refers to the namespace has
+ *		been freed (i.e., when the namespace's refCount is 0), the
+ *		namespace's storage will be freed.
+ */
+
+#define NS_DYING	0x01
+#define NS_DEAD		0x02
+
+/*
+ * Flag passed to TclGetNamespaceForQualName to have it create all namespace
+ * components of a namespace-qualified name that cannot be found. The new
+ * namespaces are created within their specified parent. Note that this
+ * flag's value must not conflict with the values of the flags
+ * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, and FIND_ONLY_NS (defined in
+ * tclNamesp.c).
+ */
+
+#define CREATE_NS_IF_UNKNOWN 0x800
+
+/*
+ *----------------------------------------------------------------
+ * Data structures related to variables.   These are used primarily
+ * in tclVar.c
+ *----------------------------------------------------------------
+ */
+
+/*
+ * The following structure defines a variable trace, which is used to
+ * invoke a specific C procedure whenever certain operations are performed
+ * on a variable.
+ */
+
+typedef struct VarTrace {
+    Tcl_VarTraceProc *traceProc;/* Procedure to call when operations given
+				 * by flags are performed on variable. */
+    ClientData clientData;	/* Argument to pass to proc. */
+    int flags;			/* What events the trace procedure is
+				 * interested in:  OR-ed combination of
+				 * TCL_TRACE_READS, TCL_TRACE_WRITES, and
+				 * TCL_TRACE_UNSETS. */
+    struct VarTrace *nextPtr;	/* Next in list of traces associated with
+				 * a particular variable. */
+} VarTrace;
+
+/*
+ * When a variable trace is active (i.e. its associated procedure is
+ * executing), one of the following structures is linked into a list
+ * associated with the variable's interpreter.	The information in
+ * the structure is needed in order for Tcl to behave reasonably
+ * if traces are deleted while traces are active.
+ */
+
+typedef struct ActiveVarTrace {
+    struct Var *varPtr;		/* Variable that's being traced. */
+    struct ActiveVarTrace *nextPtr;
+				/* Next in list of all active variable
+				 * traces for the interpreter, or NULL
+				 * if no more. */
+    VarTrace *nextTracePtr;	/* Next trace to check after current
+				 * trace procedure returns;  if this
+				 * trace gets deleted, must update pointer
+				 * to avoid using free'd memory. */
+} ActiveVarTrace;
+
+/*
+ * The following structure describes an enumerative search in progress on
+ * an array variable;  this are invoked with options to the "array"
+ * command.
+ */
+
+typedef struct ArraySearch {
+    int id;			/* Integer id used to distinguish among
+				 * multiple concurrent searches for the
+				 * same array. */
+    struct Var *varPtr;		/* Pointer to array variable that's being
+				 * searched. */
+    Tcl_HashSearch search;	/* Info kept by the hash module about
+				 * progress through the array. */
+    Tcl_HashEntry *nextEntry;	/* Non-null means this is the next element
+				 * to be enumerated (it's leftover from
+				 * the Tcl_FirstHashEntry call or from
+				 * an "array anymore" command).	 NULL
+				 * means must call Tcl_NextHashEntry
+				 * to get value to return. */
+    struct ArraySearch *nextPtr;/* Next in list of all active searches
+				 * for this variable, or NULL if this is
+				 * the last one. */
+} ArraySearch;
+
+/*
+ * The structure below defines a variable, which associates a string name
+ * with a Tcl_Obj value. These structures are kept in procedure call frames
+ * (for local variables recognized by the compiler) or in the heap (for
+ * global variables and any variable not known to the compiler). For each
+ * Var structure in the heap, a hash table entry holds the variable name and
+ * a pointer to the Var structure.
+ */
+
+typedef struct Var {
+    union {
+	Tcl_Obj *objPtr;	/* The variable's object value. Used for 
+				 * scalar variables and array elements. */
+	Tcl_HashTable *tablePtr;/* For array variables, this points to
+				 * information about the hash table used
+				 * to implement the associative array. 
+				 * Points to malloc-ed data. */
+	struct Var *linkPtr;	/* If this is a global variable being
+				 * referred to in a procedure, or a variable
+				 * created by "upvar", this field points to
+				 * the referenced variable's Var struct. */
+    } value;
+    char *name;			/* NULL if the variable is in a hashtable,
+				 * otherwise points to the variable's
+				 * name. It is used, e.g., by TclLookupVar
+				 * and "info locals". The storage for the
+				 * characters of the name is not owned by
+				 * the Var and must not be freed when
+				 * freeing the Var. */
+    Namespace *nsPtr;		/* Points to the namespace that contains
+				 * this variable or NULL if the variable is
+				 * a local variable in a Tcl procedure. */
+    Tcl_HashEntry *hPtr;	/* If variable is in a hashtable, either the
+				 * hash table entry that refers to this
+				 * variable or NULL if the variable has been
+				 * detached from its hash table (e.g. an
+				 * array is deleted, but some of its
+				 * elements are still referred to in
+				 * upvars). NULL if the variable is not in a
+				 * hashtable. This is used to delete an
+				 * variable from its hashtable if it is no
+				 * longer needed. */
+    int refCount;		/* Counts number of active uses of this
+				 * variable, not including its entry in the
+				 * call frame or the hash table: 1 for each
+				 * additional variable whose linkPtr points
+				 * here, 1 for each nested trace active on
+				 * variable, and 1 if the variable is a 
+				 * namespace variable. This record can't be
+				 * deleted until refCount becomes 0. */
+    VarTrace *tracePtr;		/* First in list of all traces set for this
+				 * variable. */
+    ArraySearch *searchPtr;	/* First in list of all searches active
+				 * for this variable, or NULL if none. */
+    int flags;			/* Miscellaneous bits of information about
+				 * variable. See below for definitions. */
+} Var;
+
+/*
+ * Flag bits for variables. The first three (VAR_SCALAR, VAR_ARRAY, and
+ * VAR_LINK) are mutually exclusive and give the "type" of the variable.
+ * VAR_UNDEFINED is independent of the variable's type. 
+ *
+ * VAR_SCALAR -			1 means this is a scalar variable and not
+ *				an array or link. The "objPtr" field points
+ *				to the variable's value, a Tcl object.
+ * VAR_ARRAY -			1 means this is an array variable rather
+ *				than a scalar variable or link. The
+ *				"tablePtr" field points to the array's
+ *				hashtable for its elements.
+ * VAR_LINK -			1 means this Var structure contains a
+ *				pointer to another Var structure that
+ *				either has the real value or is itself
+ *				another VAR_LINK pointer. Variables like
+ *				this come about through "upvar" and "global"
+ *				commands, or through references to variables
+ *				in enclosing namespaces.
+ * VAR_UNDEFINED -		1 means that the variable is in the process
+ *				of being deleted. An undefined variable
+ *				logically does not exist and survives only
+ *				while it has a trace, or if it is a global
+ *				variable currently being used by some
+ *				procedure.
+ * VAR_IN_HASHTABLE -		1 means this variable is in a hashtable and
+ *				the Var structure is malloced. 0 if it is
+ *				a local variable that was assigned a slot
+ *				in a procedure frame by	the compiler so the
+ *				Var storage is part of the call frame.
+ * VAR_TRACE_ACTIVE -		1 means that trace processing is currently
+ *				underway for a read or write access, so
+ *				new read or write accesses should not cause
+ *				trace procedures to be called and the
+ *				variable can't be deleted.
+ * VAR_ARRAY_ELEMENT -		1 means that this variable is an array
+ *				element, so it is not legal for it to be
+ *				an array itself (the VAR_ARRAY flag had
+ *				better not be set).
+ * VAR_NAMESPACE_VAR -		1 means that this variable was declared
+ *				as a namespace variable. This flag ensures
+ *				it persists until its namespace is
+ *				destroyed or until the variable is unset;
+ *				it will persist even if it has not been
+ *				initialized and is marked undefined.
+ *				The variable's refCount is incremented to
+ *				reflect the "reference" from its namespace.
+ *
+ * The following additional flags are used with the CompiledLocal type
+ * defined below:
+ *
+ * VAR_ARGUMENT -		1 means that this variable holds a procedure
+ *				argument. 
+ * VAR_TEMPORARY -		1 if the local variable is an anonymous
+ *				temporary variable. Temporaries have a NULL
+ *				name.
+ * VAR_RESOLVED -		1 if name resolution has been done for this
+ *				variable.
+ */
+
+#define VAR_SCALAR		0x1
+#define VAR_ARRAY		0x2
+#define VAR_LINK		0x4
+#define VAR_UNDEFINED		0x8
+#define VAR_IN_HASHTABLE	0x10
+#define VAR_TRACE_ACTIVE	0x20
+#define VAR_ARRAY_ELEMENT	0x40
+#define VAR_NAMESPACE_VAR	0x80
+
+#define VAR_ARGUMENT		0x100
+#define VAR_TEMPORARY		0x200
+#define VAR_RESOLVED		0x400	
+
+/*
+ * Macros to ensure that various flag bits are set properly for variables.
+ * The ANSI C "prototypes" for these macros are:
+ *
+ * EXTERN void	TclSetVarScalar _ANSI_ARGS_((Var *varPtr));
+ * EXTERN void	TclSetVarArray _ANSI_ARGS_((Var *varPtr));
+ * EXTERN void	TclSetVarLink _ANSI_ARGS_((Var *varPtr));
+ * EXTERN void	TclSetVarArrayElement _ANSI_ARGS_((Var *varPtr));
+ * EXTERN void	TclSetVarUndefined _ANSI_ARGS_((Var *varPtr));
+ * EXTERN void	TclClearVarUndefined _ANSI_ARGS_((Var *varPtr));
+ */
+
+#define TclSetVarScalar(varPtr) \
+    (varPtr)->flags = ((varPtr)->flags & ~(VAR_ARRAY|VAR_LINK)) | VAR_SCALAR
+
+#define TclSetVarArray(varPtr) \
+    (varPtr)->flags = ((varPtr)->flags & ~(VAR_SCALAR|VAR_LINK)) | VAR_ARRAY
+
+#define TclSetVarLink(varPtr) \
+    (varPtr)->flags = ((varPtr)->flags & ~(VAR_SCALAR|VAR_ARRAY)) | VAR_LINK
+
+#define TclSetVarArrayElement(varPtr) \
+    (varPtr)->flags = ((varPtr)->flags & ~VAR_ARRAY) | VAR_ARRAY_ELEMENT
+
+#define TclSetVarUndefined(varPtr) \
+    (varPtr)->flags |= VAR_UNDEFINED
+
+#define TclClearVarUndefined(varPtr) \
+    (varPtr)->flags &= ~VAR_UNDEFINED
+
+/*
+ * Macros to read various flag bits of variables.
+ * The ANSI C "prototypes" for these macros are:
+ *
+ * EXTERN int	TclIsVarScalar _ANSI_ARGS_((Var *varPtr));
+ * EXTERN int	TclIsVarLink _ANSI_ARGS_((Var *varPtr));
+ * EXTERN int	TclIsVarArray _ANSI_ARGS_((Var *varPtr));
+ * EXTERN int	TclIsVarUndefined _ANSI_ARGS_((Var *varPtr));
+ * EXTERN int	TclIsVarArrayElement _ANSI_ARGS_((Var *varPtr));
+ * EXTERN int	TclIsVarTemporary _ANSI_ARGS_((Var *varPtr));
+ * EXTERN int	TclIsVarArgument _ANSI_ARGS_((Var *varPtr));
+ * EXTERN int	TclIsVarResolved _ANSI_ARGS_((Var *varPtr));
+ */
+    
+#define TclIsVarScalar(varPtr) \
+    ((varPtr)->flags & VAR_SCALAR)
+
+#define TclIsVarLink(varPtr) \
+    ((varPtr)->flags & VAR_LINK)
+
+#define TclIsVarArray(varPtr) \
+    ((varPtr)->flags & VAR_ARRAY)
+
+#define TclIsVarUndefined(varPtr) \
+    ((varPtr)->flags & VAR_UNDEFINED)
+
+#define TclIsVarArrayElement(varPtr) \
+    ((varPtr)->flags & VAR_ARRAY_ELEMENT)
+
+#define TclIsVarTemporary(varPtr) \
+    ((varPtr)->flags & VAR_TEMPORARY)
+    
+#define TclIsVarArgument(varPtr) \
+    ((varPtr)->flags & VAR_ARGUMENT)
+    
+#define TclIsVarResolved(varPtr) \
+    ((varPtr)->flags & VAR_RESOLVED)
+
+/*
+ *----------------------------------------------------------------
+ * Data structures related to procedures.  These are used primarily
+ * in tclProc.c, tclCompile.c, and tclExecute.c.
+ *----------------------------------------------------------------
+ */
+
+/*
+ * Forward declaration to prevent an error when the forward reference to
+ * Command is encountered in the Proc and ImportRef types declared below.
+ */
+
+struct Command;
+
+/*
+ * The variable-length structure below describes a local variable of a
+ * procedure that was recognized by the compiler. These variables have a
+ * name, an element in the array of compiler-assigned local variables in the
+ * procedure's call frame, and various other items of information. If the
+ * local variable is a formal argument, it may also have a default value.
+ * The compiler can't recognize local variables whose names are
+ * expressions (these names are only known at runtime when the expressions
+ * are evaluated) or local variables that are created as a result of an
+ * "upvar" or "uplevel" command. These other local variables are kept
+ * separately in a hash table in the call frame.
+ */
+
+typedef struct CompiledLocal {
+    struct CompiledLocal *nextPtr;
+				/* Next compiler-recognized local variable
+				 * for this procedure, or NULL if this is
+				 * the last local. */
+    int nameLength;		/* The number of characters in local
+				 * variable's name. Used to speed up
+				 * variable lookups. */
+    int frameIndex;		/* Index in the array of compiler-assigned
+				 * variables in the procedure call frame. */
+    int flags;			/* Flag bits for the local variable. Same as
+				 * the flags for the Var structure above,
+				 * although only VAR_SCALAR, VAR_ARRAY, 
+				 * VAR_LINK, VAR_ARGUMENT, VAR_TEMPORARY, and
+				 * VAR_RESOLVED make sense. */
+    Tcl_Obj *defValuePtr;	/* Pointer to the default value of an
+				 * argument, if any. NULL if not an argument
+				 * or, if an argument, no default value. */
+    Tcl_ResolvedVarInfo *resolveInfo;
+				/* Customized variable resolution info
+				 * supplied by the Tcl_ResolveCompiledVarProc
+				 * associated with a namespace. Each variable
+				 * is marked by a unique ClientData tag
+				 * during compilation, and that same tag
+				 * is used to find the variable at runtime. */
+    char name[4];		/* Name of the local variable starts here.
+				 * If the name is NULL, this will just be
+				 * '\0'. The actual size of this field will
+				 * be large enough to hold the name. MUST
+				 * BE THE LAST FIELD IN THE STRUCTURE! */
+} CompiledLocal;
+
+/*
+ * The structure below defines a command procedure, which consists of a
+ * collection of Tcl commands plus information about arguments and other
+ * local variables recognized at compile time.
+ */
+
+typedef struct Proc {
+    struct Interp *iPtr;	  /* Interpreter for which this command
+				   * is defined. */
+    int refCount;		  /* Reference count: 1 if still present
+				   * in command table plus 1 for each call
+				   * to the procedure that is currently
+				   * active. This structure can be freed
+				   * when refCount becomes zero. */
+    struct Command *cmdPtr;	  /* Points to the Command structure for
+				   * this procedure. This is used to get
+				   * the namespace in which to execute
+				   * the procedure. */
+    Tcl_Obj *bodyPtr;		  /* Points to the ByteCode object for
+				   * procedure's body command. */
+    int numArgs;		  /* Number of formal parameters. */
+    int numCompiledLocals;	  /* Count of local variables recognized by
+				   * the compiler including arguments and
+				   * temporaries. */
+    CompiledLocal *firstLocalPtr; /* Pointer to first of the procedure's
+				   * compiler-allocated local variables, or
+				   * NULL if none. The first numArgs entries
+				   * in this list describe the procedure's
+				   * formal arguments. */
+    CompiledLocal *lastLocalPtr;  /* Pointer to the last allocated local
+				   * variable or NULL if none. This has
+				   * frame index (numCompiledLocals-1). */
+} Proc;
+
+/*
+ * The structure below defines a command trace.	 This is used to allow Tcl
+ * clients to find out whenever a command is about to be executed.
+ */
+
+typedef struct Trace {
+    int level;			/* Only trace commands at nesting level
+				 * less than or equal to this. */
+    Tcl_CmdTraceProc *proc;	/* Procedure to call to trace command. */
+    ClientData clientData;	/* Arbitrary value to pass to proc. */
+    struct Trace *nextPtr;	/* Next in list of traces for this interp. */
+} Trace;
+
+/*
+ * The structure below defines an entry in the assocData hash table which
+ * is associated with an interpreter. The entry contains a pointer to a
+ * function to call when the interpreter is deleted, and a pointer to
+ * a user-defined piece of data.
+ */
+
+typedef struct AssocData {
+    Tcl_InterpDeleteProc *proc;	/* Proc to call when deleting. */
+    ClientData clientData;	/* Value to pass to proc. */
+} AssocData;	
+
+/*
+ * The structure below defines a call frame. A call frame defines a naming
+ * context for a procedure call: its local naming scope (for local
+ * variables) and its global naming scope (a namespace, perhaps the global
+ * :: namespace). A call frame can also define the naming context for a
+ * namespace eval or namespace inscope command: the namespace in which the
+ * command's code should execute. The Tcl_CallFrame structures exist only
+ * while procedures or namespace eval/inscope's are being executed, and
+ * provide a kind of Tcl call stack.
+ * 
+ * WARNING!! The structure definition must be kept consistent with the
+ * Tcl_CallFrame structure in tcl.h. If you change one, change the other.
+ */
+
+typedef struct CallFrame {
+    Namespace *nsPtr;		/* Points to the namespace used to resolve
+				 * commands and global variables. */
+    int isProcCallFrame;	/* If nonzero, the frame was pushed to
+				 * execute a Tcl procedure and may have
+				 * local vars. If 0, the frame was pushed
+				 * to execute a namespace command and var
+				 * references are treated as references to
+				 * namespace vars; varTablePtr and
+				 * compiledLocals are ignored. */
+    int objc;			/* This and objv below describe the
+				 * arguments for this procedure call. */
+    Tcl_Obj *CONST *objv;	/* Array of argument objects. */
+    struct CallFrame *callerPtr;
+				/* Value of interp->framePtr when this
+				 * procedure was invoked (i.e. next higher
+				 * in stack of all active procedures). */
+    struct CallFrame *callerVarPtr;
+				/* Value of interp->varFramePtr when this
+				 * procedure was invoked (i.e. determines
+				 * variable scoping within caller). Same
+				 * as callerPtr unless an "uplevel" command
+				 * or something equivalent was active in
+				 * the caller). */
+    int level;			/* Level of this procedure, for "uplevel"
+				 * purposes (i.e. corresponds to nesting of
+				 * callerVarPtr's, not callerPtr's). 1 for
+				 * outermost procedure, 0 for top-level. */
+    Proc *procPtr;		/* Points to the structure defining the
+				 * called procedure. Used to get information
+				 * such as the number of compiled local
+				 * variables (local variables assigned
+				 * entries ["slots"] in the compiledLocals
+				 * array below). */
+    Tcl_HashTable *varTablePtr;	/* Hash table containing local variables not
+				 * recognized by the compiler, or created at
+				 * execution time through, e.g., upvar.
+				 * Initially NULL and created if needed. */
+    int numCompiledLocals;	/* Count of local variables recognized by
+				 * the compiler including arguments. */
+    Var* compiledLocals;	/* Points to the array of local variables
+				 * recognized by the compiler. The compiler
+				 * emits code that refers to these variables
+				 * using an index into this array. */
+} CallFrame;
+
+/*
+ *----------------------------------------------------------------
+ * Data structures related to history.	 These are used primarily
+ * in tclHistory.c
+ *----------------------------------------------------------------
+ */
+
+/*
+ * The structure below defines one history event (a previously-executed
+ * command that can be re-executed in whole or in part).
+ */
+
+typedef struct {
+    char *command;		/* String containing previously-executed
+				 * command. */
+    int bytesAvl;		/* Total # of bytes available at *event (not
+				 * all are necessarily in use now). */
+} HistoryEvent;
+
+/*
+ * The structure below defines a pending revision to the most recent
+ * history event.  Changes are linked together into a list and applied
+ * during the next call to Tcl_RecordHistory.  See the comments at the
+ * beginning of tclHistory.c for information on revisions.
+ */
+
+typedef struct HistoryRev {
+    int firstIndex;		/* Index of the first byte to replace in
+				 * current history event. */
+    int lastIndex;		/* Index of last byte to replace in
+				 * current history event. */
+    int newSize;		/* Number of bytes in newBytes. */
+    char *newBytes;		/* Replacement for the range given by
+				 * firstIndex and lastIndex (malloced). */
+    struct HistoryRev *nextPtr;	/* Next in chain of revisions to apply, or
+				 * NULL for end of list. */
+} HistoryRev;
+
+/*
+ *----------------------------------------------------------------
+ * Data structures related to expressions.  These are used only in
+ * tclExpr.c.
+ *----------------------------------------------------------------
+ */
+
+/*
+ * The data structure below defines a math function (e.g. sin or hypot)
+ * for use in Tcl expressions.
+ */
+
+#define MAX_MATH_ARGS 5
+typedef struct MathFunc {
+    int builtinFuncIndex;	/* If this is a builtin math function, its
+				 * index in the array of builtin functions.
+				 * (tclCompilation.h lists these indices.)
+				 * The value is -1 if this is a new function
+				 * defined by Tcl_CreateMathFunc. The value
+				 * is also -1 if a builtin function is
+				 * replaced by a Tcl_CreateMathFunc call. */
+    int numArgs;		/* Number of arguments for function. */
+    Tcl_ValueType argTypes[MAX_MATH_ARGS];
+				/* Acceptable types for each argument. */
+    Tcl_MathProc *proc;		/* Procedure that implements this function.
+				 * NULL if isBuiltinFunc is 1. */
+    ClientData clientData;	/* Additional argument to pass to the
+				 * function when invoking it. NULL if
+				 * isBuiltinFunc is 1. */
+} MathFunc;
+
+/*
+ *----------------------------------------------------------------
+ * Data structures related to bytecode compilation and execution.
+ * These are used primarily in tclCompile.c, tclExecute.c, and
+ * tclBasic.c.
+ *----------------------------------------------------------------
+ */
+
+/*
+ * Forward declaration to prevent an error when the forward reference to
+ * CompileEnv is encountered in the procedure type CompileProc declared
+ * below.
+ */
+
+struct CompileEnv;
+
+/*
+ * The type of procedures called by the Tcl bytecode compiler to compile
+ * commands. Pointers to these procedures are kept in the Command structure
+ * describing each command. When a CompileProc returns, the interpreter's
+ * result is set to error information, if any. In addition, the CompileProc
+ * returns an integer value, which is one of the following:
+ *
+ * TCL_OK		Compilation completed normally.
+ * TCL_ERROR		Compilation failed because of an error;
+ *			the interpreter's result describes what went wrong.
+ * TCL_OUT_LINE_COMPILE	Compilation failed because, e.g., the command is
+ *			too complex for effective inline compilation. The
+ *			CompileProc believes the command is legal but 
+ *			should be compiled "out of line" by emitting code
+ *			to invoke its command procedure at runtime.
+ */
+
+#define TCL_OUT_LINE_COMPILE	(TCL_CONTINUE + 1)
+
+typedef int (CompileProc) _ANSI_ARGS_((Tcl_Interp *interp, char *string,
+	char *lastChar, int compileFlags, struct CompileEnv *compEnvPtr));
+
+/*
+ * The data structure defining the execution environment for ByteCode's.
+ * There is one ExecEnv structure per Tcl interpreter. It holds the
+ * evaluation stack that holds command operands and results. The stack grows
+ * towards increasing addresses. The "stackTop" member is cached by
+ * TclExecuteByteCode in a local variable: it must be set before calling
+ * TclExecuteByteCode and will be restored by TclExecuteByteCode before it
+ * returns.
+ */
+
+typedef union StackItem {
+    Tcl_Obj *o;			/* Stack item as a pointer to a Tcl_Obj. */
+    int	     i;			/* Stack item as an integer. */
+    VOID    *p;			/* Stack item as an arbitrary pointer. */
+} StackItem;
+
+typedef struct ExecEnv {
+    StackItem *stackPtr;	/* Points to the first item in the
+				 * evaluation stack on the heap. */
+    int stackTop;		/* Index of current top of stack; -1 when
+				 * the stack is empty. */
+    int stackEnd;		/* Index of last usable item in stack. */
+} ExecEnv;
+
+/*
+ *----------------------------------------------------------------
+ * Data structures related to commands.
+ *----------------------------------------------------------------
+ */
+
+/*
+ * An imported command is created in an namespace when it imports a "real"
+ * command from another namespace. An imported command has a Command
+ * structure that points (via its ClientData value) to the "real" Command
+ * structure in the source namespace's command table. The real command
+ * records all the imported commands that refer to it in a list of ImportRef
+ * structures so that they can be deleted when the real command is deleted.  */
+
+typedef struct ImportRef {
+    struct Command *importedCmdPtr;
+				/* Points to the imported command created in
+				 * an importing namespace; this command
+				 * redirects its invocations to the "real"
+				 * command. */
+    struct ImportRef *nextPtr;	/* Next element on the linked list of
+				 * imported commands that refer to the
+				 * "real" command. The real command deletes
+				 * these imported commands on this list when
+				 * it is deleted. */
+} ImportRef;
+
+/*
+ * Data structure used as the ClientData of imported commands: commands
+ * created in an namespace when it imports a "real" command from another
+ * namespace.
+ */
+
+typedef struct ImportedCmdData {
+    struct Command *realCmdPtr;	/* "Real" command that this imported command
+				 * refers to. */
+    struct Command *selfPtr;	/* Pointer to this imported command. Needed
+				 * only when deleting it in order to remove
+				 * it from the real command's linked list of
+				 * imported commands that refer to it. */
+} ImportedCmdData;
+
+/*
+ * A Command structure exists for each command in a namespace. The
+ * Tcl_Command opaque type actually refers to these structures.
+ */
+
+typedef struct Command {
+    Tcl_HashEntry *hPtr;	/* Pointer to the hash table entry that
+				 * refers to this command. The hash table is
+				 * either a namespace's command table or an
+				 * interpreter's hidden command table. This
+				 * pointer is used to get a command's name
+				 * from its Tcl_Command handle. NULL means
+				 * that the hash table entry has been
+				 * removed already (this can happen if
+				 * deleteProc causes the command to be
+				 * deleted or recreated). */
+    Namespace *nsPtr;		/* Points to the namespace containing this
+				 * command. */
+    int refCount;		/* 1 if in command hashtable plus 1 for each
+				 * reference from a CmdName Tcl object
+				 * representing a command's name in a
+				 * ByteCode instruction sequence. This
+				 * structure can be freed when refCount
+				 * becomes zero. */
+    int cmdEpoch;		/* Incremented to invalidate any references
+				 * that point to this command when it is
+				 * renamed, deleted, hidden, or exposed. */
+    CompileProc *compileProc;	/* Procedure called to compile command. NULL
+				 * if no compile proc exists for command. */
+    Tcl_ObjCmdProc *objProc;	/* Object-based command procedure. */
+    ClientData objClientData;	/* Arbitrary value passed to object proc. */
+    Tcl_CmdProc *proc;		/* String-based command procedure. */
+    ClientData clientData;	/* Arbitrary value passed to string proc. */
+    Tcl_CmdDeleteProc *deleteProc;
+				/* Procedure invoked when deleting command
+				 * to, e.g., free all client data. */
+    ClientData deleteData;	/* Arbitrary value passed to deleteProc. */
+    int deleted;		/* Means that the command is in the process
+				 * of being deleted (its deleteProc is
+				 * currently executing). Other attempts to
+				 * delete the command should be ignored. */
+    ImportRef *importRefPtr;	/* List of each imported Command created in
+				 * another namespace when this command is
+				 * imported. These imported commands
+				 * redirect invocations back to this
+				 * command. The list is used to remove all
+				 * those imported commands when deleting
+				 * this "real" command. */
+} Command;
+
+/*
+ *----------------------------------------------------------------
+ * Data structures related to name resolution procedures.
+ *----------------------------------------------------------------
+ */
+
+/*
+ * The interpreter keeps a linked list of name resolution schemes.
+ * The scheme for a namespace is consulted first, followed by the
+ * list of schemes in an interpreter, followed by the default
+ * name resolution in Tcl.  Schemes are added/removed from the
+ * interpreter's list by calling Tcl_AddInterpResolver and
+ * Tcl_RemoveInterpResolver.
+ */
+
+typedef struct ResolverScheme {
+    char *name;			/* Name identifying this scheme. */
+    Tcl_ResolveCmdProc *cmdResProc;
+				/* Procedure handling command name
+				 * resolution. */
+    Tcl_ResolveVarProc *varResProc;
+				/* Procedure handling variable name
+				 * resolution for variables that
+				 * can only be handled at runtime. */
+    Tcl_ResolveCompiledVarProc *compiledVarResProc;
+				/* Procedure handling variable name
+				 * resolution at compile time. */
+
+    struct ResolverScheme *nextPtr;
+				/* Pointer to next record in linked list. */
+} ResolverScheme;
+
+/*
+ *----------------------------------------------------------------
+ * This structure defines an interpreter, which is a collection of
+ * commands plus other state information related to interpreting
+ * commands, such as variable storage. Primary responsibility for
+ * this data structure is in tclBasic.c, but almost every Tcl
+ * source file uses something in here.
+ *----------------------------------------------------------------
+ */
+
+typedef struct Interp {
+
+    /*
+     * Note:  the first three fields must match exactly the fields in
+     * a Tcl_Interp struct (see tcl.h).	 If you change one, be sure to
+     * change the other.
+     *
+     * The interpreter's result is held in both the string and the
+     * objResultPtr fields. These fields hold, respectively, the result's
+     * string or object value. The interpreter's result is always in the
+     * result field if that is non-empty, otherwise it is in objResultPtr.
+     * The two fields are kept consistent unless some C code sets
+     * interp->result directly. Programs should not access result and
+     * objResultPtr directly; instead, they should always get and set the
+     * result using procedures such as Tcl_SetObjResult, Tcl_GetObjResult,
+     * and Tcl_GetStringResult. See the SetResult man page for details.
+     */
+
+    char *result;		/* If the last command returned a string
+				 * result, this points to it. Should not be
+				 * accessed directly; see comment above. */
+    Tcl_FreeProc *freeProc;	/* Zero means a string result is statically
+				 * allocated. TCL_DYNAMIC means string
+				 * result was allocated with ckalloc and
+				 * should be freed with ckfree. Other values
+				 * give address of procedure to invoke to
+				 * free the string result. Tcl_Eval must
+				 * free it before executing next command. */
+    int errorLine;		/* When TCL_ERROR is returned, this gives
+				 * the line number in the command where the
+				 * error occurred (1 means first line). */
+    Tcl_Obj *objResultPtr;	/* If the last command returned an object
+				 * result, this points to it. Should not be
+				 * accessed directly; see comment above. */
+    Namespace *globalNsPtr;	/* The interpreter's global namespace. */
+    Tcl_HashTable mathFuncTable;/* Contains all the math functions currently
+				 * defined for the interpreter.	 Indexed by
+				 * strings (function names); values have
+				 * type (MathFunc *). */
+
+    /*
+     * Information related to procedures and variables. See tclProc.c
+     * and tclvar.c for usage.
+     */
+
+    int numLevels;		/* Keeps track of how many nested calls to
+				 * Tcl_Eval are in progress for this
+				 * interpreter.	 It's used to delay deletion
+				 * of the table until all Tcl_Eval
+				 * invocations are completed. */
+    int maxNestingDepth;	/* If numLevels exceeds this value then Tcl
+				 * assumes that infinite recursion has
+				 * occurred and it generates an error. */
+    CallFrame *framePtr;	/* Points to top-most in stack of all nested
+				 * procedure invocations.  NULL means there
+				 * are no active procedures. */
+    CallFrame *varFramePtr;	/* Points to the call frame whose variables
+				 * are currently in use (same as framePtr
+				 * unless an "uplevel" command is
+				 * executing). NULL means no procedure is
+				 * active or "uplevel 0" is executing. */
+    ActiveVarTrace *activeTracePtr;
+				/* First in list of active traces for
+				 * interp, or NULL if no active traces. */
+    int returnCode;		/* Completion code to return if current
+				 * procedure exits with TCL_RETURN code. */
+    char *errorInfo;		/* Value to store in errorInfo if returnCode
+				 * is TCL_ERROR.  Malloc'ed, may be NULL */
+    char *errorCode;		/* Value to store in errorCode if returnCode
+				 * is TCL_ERROR.  Malloc'ed, may be NULL */
+
+    /*
+     * Information used by Tcl_AppendResult to keep track of partial
+     * results.	 See Tcl_AppendResult code for details.
+     */
+
+    char *appendResult;		/* Storage space for results generated
+				 * by Tcl_AppendResult.	 Malloc-ed.  NULL
+				 * means not yet allocated. */
+    int appendAvl;		/* Total amount of space available at
+				 * partialResult. */
+    int appendUsed;		/* Number of non-null bytes currently
+				 * stored at partialResult. */
+
+    /*
+     * Miscellaneous information:
+     */
+
+    int cmdCount;		/* Total number of times a command procedure
+				 * has been called for this interpreter. */
+    int evalFlags;		/* Flags to control next call to Tcl_Eval.
+				 * Normally zero, but may be set before
+				 * calling Tcl_Eval.  See below for valid
+				 * values. */
+    int termOffset;		/* Offset of character just after last one
+				 * compiled or executed by Tcl_EvalObj. */
+    int compileEpoch;		/* Holds the current "compilation epoch"
+				 * for this interpreter. This is
+				 * incremented to invalidate existing
+				 * ByteCodes when, e.g., a command with a
+				 * compile procedure is redefined. */
+    Proc *compiledProcPtr;	/* If a procedure is being compiled, a
+				 * pointer to its Proc structure; otherwise,
+				 * this is NULL. Set by ObjInterpProc in
+				 * tclProc.c and used by tclCompile.c to
+				 * process local variables appropriately. */
+    ResolverScheme *resolverPtr;
+				/* Linked list of name resolution schemes
+				 * added to this interpreter.  Schemes
+				 * are added/removed by calling
+				 * Tcl_AddInterpResolver and
+				 * Tcl_RemoveInterpResolver. */
+    char *scriptFile;		/* NULL means there is no nested source
+				 * command active;  otherwise this points to
+				 * the name of the file being sourced (it's
+				 * not malloc-ed:  it points to an argument
+				 * to Tcl_EvalFile. */
+    int flags;			/* Various flag bits.  See below. */
+    long randSeed;		/* Seed used for rand() function. */
+    Trace *tracePtr;		/* List of traces for this interpreter. */
+    Tcl_HashTable *assocData;	/* Hash table for associating data with
+				 * this interpreter. Cleaned up when
+				 * this interpreter is deleted. */
+    struct ExecEnv *execEnvPtr;	/* Execution environment for Tcl bytecode
+				 * execution. Contains a pointer to the
+				 * Tcl evaluation stack. */
+    Tcl_Obj *emptyObjPtr;	/* Points to an object holding an empty
+				 * string. Returned by Tcl_ObjSetVar2 when
+				 * variable traces change a variable in a
+				 * gross way. */
+    char resultSpace[TCL_RESULT_SIZE+1];
+				/* Static space holding small results. */
+} Interp;
+
+/*
+ * EvalFlag bits for Interp structures:
+ *
+ * TCL_BRACKET_TERM	1 means that the current script is terminated by
+ *			a close bracket rather than the end of the string.
+ * TCL_ALLOW_EXCEPTIONS	1 means it's OK for the script to terminate with
+ *			a code other than TCL_OK or TCL_ERROR;	0 means
+ *			codes other than these should be turned into errors.
+ */
+
+#define TCL_BRACKET_TERM	  1
+#define TCL_ALLOW_EXCEPTIONS	  4
+
+/*
+ * Flag bits for Interp structures:
+ *
+ * DELETED:		Non-zero means the interpreter has been deleted:
+ *			don't process any more commands for it, and destroy
+ *			the structure as soon as all nested invocations of
+ *			Tcl_Eval are done.
+ * ERR_IN_PROGRESS:	Non-zero means an error unwind is already in
+ *			progress. Zero means a command proc has been
+ *			invoked since last error occured.
+ * ERR_ALREADY_LOGGED:	Non-zero means information has already been logged
+ *			in $errorInfo for the current Tcl_Eval instance,
+ *			so Tcl_Eval needn't log it (used to implement the
+ *			"error message log" command).
+ * ERROR_CODE_SET:	Non-zero means that Tcl_SetErrorCode has been
+ *			called to record information for the current
+ *			error.	Zero means Tcl_Eval must clear the
+ *			errorCode variable if an error is returned.
+ * EXPR_INITIALIZED:	Non-zero means initialization specific to
+ *			expressions has	been carried out.
+ * DONT_COMPILE_CMDS_INLINE: Non-zero means that the bytecode compiler
+ *			should not compile any commands into an inline
+ *			sequence of instructions. This is set 1, for
+ *			example, when command traces are requested.
+ * RAND_SEED_INITIALIZED: Non-zero means that the randSeed value of the
+ *			interp has not be initialized.	This is set 1
+ *			when we first use the rand() or srand() functions.
+ * SAFE_INTERP:		Non zero means that the current interp is a
+ *			safe interp (ie it has only the safe commands
+ *			installed, less priviledge than a regular interp).
+ */
+
+#define DELETED			 1
+#define ERR_IN_PROGRESS		 2
+#define ERR_ALREADY_LOGGED	 4
+#define ERROR_CODE_SET		 8
+#define EXPR_INITIALIZED	 0x10
+#define DONT_COMPILE_CMDS_INLINE 0x20
+#define RAND_SEED_INITIALIZED	 0x40
+#define SAFE_INTERP		 0x80
+
+/*
+ *----------------------------------------------------------------
+ * Data structures related to command parsing. These are used in
+ * tclParse.c and its clients.
+ *----------------------------------------------------------------
+ */
+
+/*
+ * The following data structure is used by various parsing procedures
+ * to hold information about where to store the results of parsing
+ * (e.g. the substituted contents of a quoted argument, or the result
+ * of a nested command).  At any given time, the space available
+ * for output is fixed, but a procedure may be called to expand the
+ * space available if the current space runs out.
+ */
+
+typedef struct ParseValue {
+    char *buffer;		/* Address of first character in
+				 * output buffer. */
+    char *next;			/* Place to store next character in
+				 * output buffer. */
+    char *end;			/* Address of the last usable character
+				 * in the buffer. */
+    void (*expandProc) _ANSI_ARGS_((struct ParseValue *pvPtr, int needed));
+				/* Procedure to call when space runs out;
+				 * it will make more space. */
+    ClientData clientData;	/* Arbitrary information for use of
+				 * expandProc. */
+} ParseValue;
+
+/*
+ * A table used to classify input characters to assist in parsing
+ * Tcl commands.  The table should be indexed with a signed character
+ * using the CHAR_TYPE macro.  The character may have a negative
+ * value.  The CHAR_TYPE macro takes a pointer to a signed character
+ * and a pointer to the last character in the source string.  If the
+ * src pointer is pointing at the terminating null of the string,
+ * CHAR_TYPE returns TCL_COMMAND_END.
+ */
+
+extern unsigned char tclTypeTable[];
+#define CHAR_TYPE(src,last) \
+	(((src)==(last))?TCL_COMMAND_END:(tclTypeTable)[(int)(*(src) + 128)])
+
+/*
+ * Possible values returned by CHAR_TYPE. Note that except for TCL_DOLLAR,
+ * these are all one byte values with a single bit set 1. This means these
+ * values may be bit-or'ed together (except for TCL_DOLLAR) to quickly test
+ * whether a character is one of several different kinds of characters.
+ *
+ * TCL_NORMAL -		All characters that don't have special significance
+ *			to the Tcl language.
+ * TCL_SPACE -		Character is space, tab, or return.
+ * TCL_COMMAND_END -	Character is newline or semicolon or close-bracket
+ *			or terminating null.
+ * TCL_QUOTE -		Character is a double-quote.
+ * TCL_OPEN_BRACKET -	Character is a "[".
+ * TCL_OPEN_BRACE -	Character is a "{".
+ * TCL_CLOSE_BRACE -	Character is a "}".
+ * TCL_BACKSLASH -	Character is a "\".
+ * TCL_DOLLAR -		Character is a "$".
+ */
+
+#define TCL_NORMAL		0x01
+#define TCL_SPACE		0x02
+#define TCL_COMMAND_END		0x04
+#define TCL_QUOTE		0x08
+#define TCL_OPEN_BRACKET	0x10
+#define TCL_OPEN_BRACE		0x20
+#define TCL_CLOSE_BRACE		0x40
+#define TCL_BACKSLASH		0x80
+#define TCL_DOLLAR		0x00
+
+/*
+ * Maximum number of levels of nesting permitted in Tcl commands (used
+ * to catch infinite recursion).
+ */
+
+#define MAX_NESTING_DEPTH	1000
+
+/*
+ * The macro below is used to modify a "char" value (e.g. by casting
+ * it to an unsigned character) so that it can be used safely with
+ * macros such as isspace.
+ */
+
+#define UCHAR(c) ((unsigned char) (c))
+
+/*
+ * This macro is used to determine the offset needed to safely allocate any
+ * data structure in memory. Given a starting offset or size, it "rounds up"
+ * or "aligns" the offset to the next 8-byte boundary so that any data
+ * structure can be placed at the resulting offset without fear of an
+ * alignment error.
+ *
+ * WARNING!! DO NOT USE THIS MACRO TO ALIGN POINTERS: it will produce
+ * the wrong result on platforms that allocate addresses that are divisible
+ * by 4 or 2. Only use it for offsets or sizes.
+ */
+
+#define TCL_ALIGN(x) (((int)(x) + 7) & ~7)
+
+/*
+ * The following macros are used to specify the runtime platform
+ * setting of the tclPlatform variable.
+ */
+
+typedef enum {
+    TCL_PLATFORM_UNIX,		/* Any Unix-like OS. */
+    TCL_PLATFORM_MAC,		/* MacOS. */
+    TCL_PLATFORM_WINDOWS	/* Any Microsoft Windows OS. */
+} TclPlatformType;
+
+/*
+ * Flags for TclInvoke:
+ *
+ * TCL_INVOKE_HIDDEN		Invoke a hidden command; if not set,
+ *				invokes an exposed command.
+ * TCL_INVOKE_NO_UNKNOWN	If set, "unknown" is not invoked if
+ *				the command to be invoked is not found.
+ *				Only has an effect if invoking an exposed
+ *				command, i.e. if TCL_INVOKE_HIDDEN is not
+ *				also set.
+ */
+
+#define	TCL_INVOKE_HIDDEN	(1<<0)
+#define TCL_INVOKE_NO_UNKNOWN	(1<<1)
+
+/*
+ * The structure used as the internal representation of Tcl list
+ * objects. This is an array of pointers to the element objects. This array
+ * is grown (reallocated and copied) as necessary to hold all the list's
+ * element pointers. The array might contain more slots than currently used
+ * to hold all element pointers. This is done to make append operations
+ * faster.
+ */
+
+typedef struct List {
+    int maxElemCount;		/* Total number of element array slots. */
+    int elemCount;		/* Current number of list elements. */
+    Tcl_Obj **elements;		/* Array of pointers to element objects. */
+} List;
+    
+/*
+ *----------------------------------------------------------------
+ * Data structures related to hooking 'TclStat(...)' and
+ * 'TclAccess(...)'.
+ *----------------------------------------------------------------
+ */
+
+typedef int (*TclCmdProcType) _ANSI_ARGS_((ClientData clientData,
+	Tcl_Interp *interp, int argc, char *argv[]));
+typedef int (*TclObjCmdProcType) _ANSI_ARGS_((ClientData clientData,
+	Tcl_Interp *interp, int objc, struct Tcl_Obj * CONST objv[]));
+
+/*
+ *----------------------------------------------------------------
+ * Variables shared among Tcl modules but not used by the outside world.
+ *----------------------------------------------------------------
+ */
+
+extern char *			tclExecutableName;
+extern TclPlatformType		tclPlatform;
+
+/*
+ * Variables denoting the Tcl object types defined in the core.
+ */
+
+extern Tcl_ObjType	tclBooleanType;
+extern Tcl_ObjType	tclByteCodeType;
+extern Tcl_ObjType	tclDoubleType;
+extern Tcl_ObjType	tclIntType;
+extern Tcl_ObjType	tclListType;
+extern Tcl_ObjType	tclProcBodyType;
+extern Tcl_ObjType	tclStringType;
+
+/*
+ * The head of the list of free Tcl objects, and the total number of Tcl
+ * objects ever allocated and freed.
+ */
+
+extern Tcl_Obj *	tclFreeObjList;
+
+#ifdef TCL_COMPILE_STATS
+extern long		tclObjsAlloced;
+extern long		tclObjsFreed;
+#endif /* TCL_COMPILE_STATS */
+
+/*
+ * Pointer to a heap-allocated string of length zero that the Tcl core uses
+ * as the value of an empty string representation for an object. This value
+ * is shared by all new objects allocated by Tcl_NewObj.
+ */
+
+extern char *		tclEmptyStringRep;
+
+/*
+ *----------------------------------------------------------------
+ * Procedures shared among Tcl modules but not used by the outside
+ * world:
+ *----------------------------------------------------------------
+ */
+
+EXTERN void		panic _ANSI_ARGS_(TCL_VARARGS(char *,format));
+EXTERN void		TclAllocateFreeObjects _ANSI_ARGS_((void));
+EXTERN void		TclCleanupCommand _ANSI_ARGS_((Command *cmdPtr));
+EXTERN int		TclCopyAndCollapse _ANSI_ARGS_((int count,
+			    char *src, char *dst));
+EXTERN int		TclCreateProc _ANSI_ARGS_((Tcl_Interp *interp,
+			    Namespace *nsPtr, char *procName,
+			    Tcl_Obj *argsPtr, Tcl_Obj *bodyPtr,
+			    Proc **procPtrPtr));
+EXTERN void		TclDeleteCompiledLocalVars _ANSI_ARGS_((
+			    Interp *iPtr, CallFrame *framePtr));
+EXTERN void		TclDeleteVars _ANSI_ARGS_((Interp *iPtr,
+			    Tcl_HashTable *tablePtr));
+EXTERN void		TclDumpMemoryInfo _ANSI_ARGS_((FILE *outFile));
+EXTERN void		TclExpandParseValue _ANSI_ARGS_((ParseValue *pvPtr,
+			    int needed));
+EXTERN void		TclExprFloatError _ANSI_ARGS_((Tcl_Interp *interp,
+			    double value));
+EXTERN void		TclFinalizeCompExecEnv _ANSI_ARGS_((void));
+EXTERN void		TclFinalizeEnvironment _ANSI_ARGS_((void));
+EXTERN void		TclFinalizeExecEnv _ANSI_ARGS_((void));
+EXTERN int		TclFindElement _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *list, int listLength, char **elementPtr,
+			    char **nextPtr, int *sizePtr, int *bracePtr));
+EXTERN Proc *		TclFindProc _ANSI_ARGS_((Interp *iPtr,
+			    char *procName));
+EXTERN int		TclFormatInt _ANSI_ARGS_((char *buffer, long n));
+EXTERN int		TclGetDate _ANSI_ARGS_((char *p,
+			    unsigned long now, long zone,
+			    unsigned long *timePtr));
+EXTERN Tcl_Obj *	TclGetElementOfIndexedArray _ANSI_ARGS_((
+			    Tcl_Interp *interp, int localIndex,
+			    Tcl_Obj *elemPtr, int leaveErrorMsg));
+EXTERN char *		TclGetEnv _ANSI_ARGS_((CONST char *name));
+EXTERN int		TclGetFrame _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, CallFrame **framePtrPtr));
+EXTERN TclCmdProcType	TclGetInterpProc _ANSI_ARGS_((void));
+EXTERN int		TclGetIntForIndex _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr, int endValue, int *indexPtr));
+EXTERN Tcl_Obj *	TclGetIndexedScalar _ANSI_ARGS_((Tcl_Interp *interp,
+			    int localIndex, int leaveErrorMsg));
+EXTERN int		TclGetLong _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, long *longPtr));
+EXTERN int		TclGetNamespaceForQualName _ANSI_ARGS_((
+			    Tcl_Interp *interp, char *qualName,
+			    Namespace *cxtNsPtr, int flags,
+			    Namespace **nsPtrPtr, Namespace **altNsPtrPtr,
+			    Namespace **actualCxtPtrPtr,
+			    char **simpleNamePtr));
+EXTERN TclObjCmdProcType TclGetObjInterpProc _ANSI_ARGS_((void));
+EXTERN int		TclGetOpenMode _ANSI_ARGS_((Tcl_Interp *interp,
+        		    char *string, int *seekFlagPtr));
+EXTERN Tcl_Command	TclGetOriginalCommand _ANSI_ARGS_((
+			    Tcl_Command command));
+EXTERN char *		TclGetUserHome _ANSI_ARGS_((char *name,
+			    Tcl_DString *bufferPtr));
+EXTERN int		TclGlobalInvoke _ANSI_ARGS_((Tcl_Interp *interp,
+		            int argc, char **argv, int flags));
+EXTERN int		TclInExit _ANSI_ARGS_((void));
+EXTERN Tcl_Obj *	TclIncrElementOfIndexedArray _ANSI_ARGS_((
+                            Tcl_Interp *interp, int localIndex,
+			    Tcl_Obj *elemPtr, long incrAmount));
+EXTERN Tcl_Obj *	TclIncrIndexedScalar _ANSI_ARGS_((
+                            Tcl_Interp *interp, int localIndex,
+			    long incrAmount));
+EXTERN Tcl_Obj *	TclIncrVar2 _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
+			    long incrAmount, int part1NotParsed));
+EXTERN void		TclInitCompiledLocals _ANSI_ARGS_((
+			    Tcl_Interp *interp, CallFrame *framePtr,
+			    Namespace *nsPtr));
+EXTERN void		TclInitNamespaces _ANSI_ARGS_((void));
+EXTERN int		TclInterpInit _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN int		TclInvoke _ANSI_ARGS_((Tcl_Interp *interp,
+		            int argc, char **argv, int flags));
+EXTERN int		TclInvokeObjectCommand _ANSI_ARGS_((
+                            ClientData clientData, Tcl_Interp *interp,
+                            int argc, char **argv));
+EXTERN int		TclInvokeStringCommand _ANSI_ARGS_((
+                            ClientData clientData, Tcl_Interp *interp,
+                            int objc, Tcl_Obj *CONST objv[]));
+EXTERN Proc *		TclIsProc _ANSI_ARGS_((Command *cmdPtr));
+EXTERN int		TclLooksLikeInt _ANSI_ARGS_((char *p));
+EXTERN Var *		TclLookupVar _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *part1, char *part2, int flags, char *msg,
+			    int createPart1, int createPart2,
+			    Var **arrayPtrPtr));
+EXTERN int		TclNeedSpace _ANSI_ARGS_((char *start, char *end));
+EXTERN Tcl_Obj *	TclNewProcBodyObj _ANSI_ARGS_((Proc *procPtr));
+EXTERN int		TclObjCommandComplete _ANSI_ARGS_((Tcl_Obj *cmdPtr));
+EXTERN int		TclObjInterpProc _ANSI_ARGS_((ClientData clientData,
+		    	    Tcl_Interp *interp, int objc,
+			    Tcl_Obj *CONST objv[]));
+EXTERN int		TclObjInvoke _ANSI_ARGS_((Tcl_Interp *interp,
+		            int objc, Tcl_Obj *CONST objv[], int flags));
+EXTERN int		TclObjInvokeGlobal _ANSI_ARGS_((Tcl_Interp *interp,
+		            int objc, Tcl_Obj *CONST objv[], int flags));
+EXTERN char *		TclpAlloc _ANSI_ARGS_((unsigned int size));
+
+EXTERN char *		TclpRealloc _ANSI_ARGS_((char *ptr,
+			    unsigned int size));
+#ifndef TclpSysAlloc
+EXTERN VOID * 		TclpSysAlloc _ANSI_ARGS_((long size, int isBin));
+#endif
+#ifndef TclpSysFree
+EXTERN void 		TclpSysFree _ANSI_ARGS_((VOID *ptr));
+#endif
+#ifndef TclpSysRealloc
+EXTERN VOID * 		TclpSysRealloc _ANSI_ARGS_((VOID *cp,
+			    unsigned int size));
+#endif
+EXTERN int		TclParseBraces _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, char **termPtr, ParseValue *pvPtr));
+EXTERN int		TclParseNestedCmd _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, int flags, char **termPtr,
+			    ParseValue *pvPtr));
+EXTERN int		TclParseQuotes _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *string, int termChar, int flags,
+			    char **termPtr, ParseValue *pvPtr));
+EXTERN void		TclPlatformExit _ANSI_ARGS_((int status));
+EXTERN char *		TclPrecTraceProc _ANSI_ARGS_((ClientData clientData,
+			    Tcl_Interp *interp, char *name1, char *name2,
+			    int flags));
+EXTERN int		TclPreventAliasLoop _ANSI_ARGS_((Tcl_Interp *interp,
+		            Tcl_Interp *cmdInterp, Tcl_Command cmd));
+EXTERN void		TclPrintByteCodeObj _ANSI_ARGS_((Tcl_Interp *interp,
+		            Tcl_Obj *objPtr));
+EXTERN void		TclProcCleanupProc _ANSI_ARGS_((Proc *procPtr));
+EXTERN int		TclProcCompileProc _ANSI_ARGS_((Tcl_Interp *interp,
+ 			    Proc *procPtr, Tcl_Obj *bodyPtr, Namespace *nsPtr,
+ 			    CONST char *description, CONST char *procName));
+EXTERN void		TclProcDeleteProc _ANSI_ARGS_((ClientData clientData));
+EXTERN int		TclProcInterpProc _ANSI_ARGS_((ClientData clientData,
+		    	    Tcl_Interp *interp, int argc, char **argv));
+EXTERN int		TclRenameCommand _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *oldName, char *newName)) ;
+EXTERN void		TclResetShadowedCmdRefs _ANSI_ARGS_((
+			    Tcl_Interp *interp, Command *newCmdPtr));
+EXTERN int		TclServiceIdle _ANSI_ARGS_((void));
+EXTERN Tcl_Obj *	TclSetElementOfIndexedArray _ANSI_ARGS_((
+                            Tcl_Interp *interp, int localIndex,
+			    Tcl_Obj *elemPtr, Tcl_Obj *objPtr,
+			    int leaveErrorMsg));
+EXTERN Tcl_Obj *	TclSetIndexedScalar _ANSI_ARGS_((Tcl_Interp *interp,
+			    int localIndex, Tcl_Obj *objPtr,
+			    int leaveErrorMsg));
+EXTERN char *		TclSetPreInitScript _ANSI_ARGS_((char *string));
+EXTERN int		TclSockGetPort _ANSI_ARGS_((Tcl_Interp *interp,
+		            char *string, char *proto, int *portPtr));
+EXTERN int		TclSockMinimumBuffers _ANSI_ARGS_((int sock,
+        		    int size));
+EXTERN void		TclTeardownNamespace _ANSI_ARGS_((Namespace *nsPtr));
+EXTERN int		TclUpdateReturnInfo _ANSI_ARGS_((Interp *iPtr));
+EXTERN char *		TclWordEnd _ANSI_ARGS_((char *start, char *lastChar,
+			    int nested, int *semiPtr));
+
+/*
+ *----------------------------------------------------------------
+ * Command procedures in the generic core:
+ *----------------------------------------------------------------
+ */
+
+EXTERN int	Tcl_AfterObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_AppendObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_ArrayObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_BreakCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int argc, char **argv));
+EXTERN int	Tcl_CaseObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_CatchObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_CdObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_ConcatObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_ContinueCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int argc, char **argv));
+EXTERN int	Tcl_ErrorObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_EvalObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_ExitObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_ExprObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_ForCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int argc, char **argv));
+EXTERN int	Tcl_ForeachObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_FormatObjCmd _ANSI_ARGS_((ClientData dummy,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_GlobalObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_IfCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int argc, char **argv));
+EXTERN int	Tcl_IncrCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int argc, char **argv));
+EXTERN int	Tcl_InfoObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_InterpObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_JoinObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_LappendObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_LindexObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_LinsertObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_LlengthObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_ListObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_LrangeObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_LreplaceObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_LsortObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_NamespaceObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_ProcObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_PutsObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_PwdCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int argc, char **argv));
+EXTERN int	Tcl_RegexpCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int argc, char **argv));
+EXTERN int	Tcl_RegsubCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int argc, char **argv));
+EXTERN int	Tcl_RenameObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_ReturnObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_ScanCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int argc, char **argv));
+EXTERN int	Tcl_SetCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int argc, char **argv));
+EXTERN int	Tcl_SplitObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_SourceObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_StringObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_SubstCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int argc, char **argv));
+EXTERN int	Tcl_SwitchObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_TimeObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_TraceCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int argc, char **argv));
+EXTERN int	Tcl_UnsetObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_UplevelObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_UpvarObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_VariableObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_WhileCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int argc, char **argv));
+
+/*
+ *----------------------------------------------------------------
+ * Command procedures found only in the Mac version of the core:
+ *----------------------------------------------------------------
+ */
+
+#ifdef MAC_TCL
+EXTERN int 	Tcl_EchoCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int argc, char **argv));
+EXTERN int 	Tcl_LsCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int argc, char **argv));
+EXTERN int 	Tcl_BeepObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int 	Tcl_MacSourceObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int	Tcl_ResourceObjCmd _ANSI_ARGS_((ClientData clientData,
+		    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+#endif
+
+/*
+ *----------------------------------------------------------------
+ * Compilation procedures for commands in the generic core:
+ *----------------------------------------------------------------
+ */
+
+EXTERN int	TclCompileBreakCmd _ANSI_ARGS_((Tcl_Interp *interp,
+		    char *string, char *lastChar, int compileFlags,
+		    struct CompileEnv *compileEnvPtr));
+EXTERN int	TclCompileCatchCmd _ANSI_ARGS_((Tcl_Interp *interp,
+		    char *string, char *lastChar, int compileFlags,
+		    struct CompileEnv *compileEnvPtr));
+EXTERN int	TclCompileContinueCmd _ANSI_ARGS_((Tcl_Interp *interp,
+		    char *string, char *lastChar, int compileFlags,
+		    struct CompileEnv *compileEnvPtr));
+EXTERN int	TclCompileExprCmd _ANSI_ARGS_((Tcl_Interp *interp,
+		    char *string, char *lastChar, int compileFlags,
+		    struct CompileEnv *compileEnvPtr));
+EXTERN int	TclCompileForCmd _ANSI_ARGS_((Tcl_Interp *interp,
+		    char *string, char *lastChar, int compileFlags,
+		    struct CompileEnv *compileEnvPtr));
+EXTERN int	TclCompileForeachCmd _ANSI_ARGS_((Tcl_Interp *interp,
+		    char *string, char *lastChar, int compileFlags,
+		    struct CompileEnv *compileEnvPtr));
+EXTERN int	TclCompileIfCmd _ANSI_ARGS_((Tcl_Interp *interp,
+		    char *string, char *lastChar, int compileFlags,
+		    struct CompileEnv *compileEnvPtr));
+EXTERN int	TclCompileIncrCmd _ANSI_ARGS_((Tcl_Interp *interp,
+		    char *string, char *lastChar, int compileFlags,
+		    struct CompileEnv *compileEnvPtr));
+EXTERN int	TclCompileSetCmd _ANSI_ARGS_((Tcl_Interp *interp,
+		    char *string, char *lastChar, int compileFlags,
+		    struct CompileEnv *compileEnvPtr));
+EXTERN int	TclCompileWhileCmd _ANSI_ARGS_((Tcl_Interp *interp,
+		    char *string, char *lastChar, int compileFlags,
+		    struct CompileEnv *compileEnvPtr));
+
+/*
+ *----------------------------------------------------------------
+ * Macros used by the Tcl core to create and release Tcl objects.
+ * TclNewObj(objPtr) creates a new object denoting an empty string.
+ * TclDecrRefCount(objPtr) decrements the object's reference count,
+ * and frees the object if its reference count is zero.
+ * These macros are inline versions of Tcl_NewObj() and
+ * Tcl_DecrRefCount(). Notice that the names differ in not having
+ * a "_" after the "Tcl". Notice also that these macros reference
+ * their argument more than once, so you should avoid calling them
+ * with an expression that is expensive to compute or has
+ * side effects. The ANSI C "prototypes" for these macros are:
+ *
+ * EXTERN void	TclNewObj _ANSI_ARGS_((Tcl_Obj *objPtr));
+ * EXTERN void	TclDecrRefCount _ANSI_ARGS_((Tcl_Obj *objPtr));
+ *----------------------------------------------------------------
+ */
+
+#ifdef TCL_COMPILE_STATS
+#  define TclIncrObjsAllocated() \
+    tclObjsAlloced++
+#  define TclIncrObjsFreed() \
+    tclObjsFreed++
+#else
+#  define TclIncrObjsAllocated()
+#  define TclIncrObjsFreed()
+#endif /* TCL_COMPILE_STATS */
+
+#ifdef TCL_MEM_DEBUG
+#  define TclNewObj(objPtr) \
+    (objPtr) = (Tcl_Obj *) Tcl_DbCkalloc(sizeof(Tcl_Obj), __FILE__, __LINE__); \
+    (objPtr)->refCount = 0; \
+    (objPtr)->bytes    = tclEmptyStringRep; \
+    (objPtr)->length   = 0; \
+    (objPtr)->typePtr  = NULL; \
+    TclIncrObjsAllocated()
+#  define TclDbNewObj(objPtr, file, line) \
+    (objPtr) = (Tcl_Obj *) Tcl_DbCkalloc(sizeof(Tcl_Obj), (file), (line)); \
+    (objPtr)->refCount = 0; \
+    (objPtr)->bytes    = tclEmptyStringRep; \
+    (objPtr)->length   = 0; \
+    (objPtr)->typePtr  = NULL; \
+    TclIncrObjsAllocated()
+#  define TclDecrRefCount(objPtr) \
+    if (--(objPtr)->refCount <= 0) { \
+ 	if ((objPtr)->refCount < -1) \
+            panic("Reference count for %lx was negative: %s line %d", \
+		  (objPtr), __FILE__, __LINE__); \
+        if (((objPtr)->bytes != NULL) \
+	        && ((objPtr)->bytes != tclEmptyStringRep)) { \
+	    ckfree((char *) (objPtr)->bytes); \
+        } \
+        if (((objPtr)->typePtr != NULL) \
+	        && ((objPtr)->typePtr->freeIntRepProc != NULL)) { \
+	    (objPtr)->typePtr->freeIntRepProc(objPtr); \
+        } \
+        ckfree((char *) (objPtr)); \
+        TclIncrObjsFreed(); \
+    }
+#else /* not TCL_MEM_DEBUG */
+#  define TclNewObj(objPtr) \
+    if (tclFreeObjList == NULL) { \
+	TclAllocateFreeObjects(); \
+    } \
+    (objPtr) = tclFreeObjList; \
+    tclFreeObjList = (Tcl_Obj *) \
+	tclFreeObjList->internalRep.otherValuePtr; \
+    (objPtr)->refCount = 0; \
+    (objPtr)->bytes    = tclEmptyStringRep; \
+    (objPtr)->length   = 0; \
+    (objPtr)->typePtr  = NULL; \
+    TclIncrObjsAllocated()
+#  define TclDecrRefCount(objPtr) \
+    if (--(objPtr)->refCount <= 0) { \
+        if (((objPtr)->bytes != NULL) \
+	        && ((objPtr)->bytes != tclEmptyStringRep)) { \
+	    ckfree((char *) (objPtr)->bytes); \
+        } \
+        if (((objPtr)->typePtr != NULL) \
+	        && ((objPtr)->typePtr->freeIntRepProc != NULL)) { \
+	    (objPtr)->typePtr->freeIntRepProc(objPtr); \
+        } \
+        (objPtr)->internalRep.otherValuePtr = (VOID *) tclFreeObjList; \
+        tclFreeObjList = (objPtr); \
+        TclIncrObjsFreed(); \
+    }
+#endif /* TCL_MEM_DEBUG */
+
+/*
+ *----------------------------------------------------------------
+ * Macro used by the Tcl core to set a Tcl_Obj's string representation
+ * to a copy of the "len" bytes starting at "bytePtr". This code
+ * works even if the byte array contains NULLs as long as the length
+ * is correct. Because "len" is referenced multiple times, it should
+ * be as simple an expression as possible. The ANSI C "prototype" for
+ * this macro is:
+ *
+ * EXTERN void	TclInitStringRep _ANSI_ARGS_((Tcl_Obj *objPtr,
+ *		    char *bytePtr, int len));
+ *----------------------------------------------------------------
+ */
+
+#define TclInitStringRep(objPtr, bytePtr, len) \
+    if ((len) == 0) { \
+        (objPtr)->bytes  = tclEmptyStringRep; \
+	(objPtr)->length = 0; \
+    } else { \
+	(objPtr)->bytes = (char *) ckalloc((unsigned) ((len) + 1)); \
+	memcpy((VOID *) (objPtr)->bytes, (VOID *) (bytePtr), \
+	        (unsigned) (len)); \
+	(objPtr)->bytes[len] = '\0'; \
+	(objPtr)->length = (len); \
+    }
+
+/*
+ *----------------------------------------------------------------
+ * Macro used by the Tcl core to get the string representation's
+ * byte array pointer and length from a Tcl_Obj. This is an inline
+ * version of Tcl_GetStringFromObj(). "lengthPtr" must be the
+ * address of an integer variable or NULL; If non-NULL, that variable
+ * will be set to the string rep's length. The macro's expression
+ * result is the string rep's byte pointer which might be NULL.
+ * Note that the bytes referenced by this pointer must not be modified
+ * by the caller. The ANSI C "prototype" for this macro is:
+ *
+ * EXTERN char *  TclGetStringFromObj _ANSI_ARGS_((Tcl_Obj *objPtr,
+ *		       int *lengthPtr));
+ *----------------------------------------------------------------
+ */
+
+#define TclGetStringFromObj(objPtr, lengthPtr) \
+    ((objPtr)->bytes? \
+        ((lengthPtr)? \
+	    ((*(lengthPtr) = (objPtr)->length), (objPtr)->bytes) : \
+	    (objPtr)->bytes) : \
+        Tcl_GetStringFromObj((objPtr), (lengthPtr)))
+
+/*
+ *----------------------------------------------------------------
+ * Macro used by the Tcl core to reset an interpreter's Tcl object
+ * result to an unshared empty string object with ref count one.
+ * This does not clear any error information for the interpreter.
+ * The ANSI C "prototype" for this macro is:
+ *
+ * EXTERN void	TclResetObjResult _ANSI_ARGS_((Tcl_Interp *interp));
+ *---------------------------------------------------------------
+ */
+
+#define TclResetObjResult(interp) \
+    { \
+        register Tcl_Obj *objResultPtr = ((Interp *) interp)->objResultPtr; \
+        if (Tcl_IsShared(objResultPtr)) { \
+	    TclDecrRefCount(objResultPtr); \
+	    TclNewObj(objResultPtr); \
+	    Tcl_IncrRefCount(objResultPtr); \
+	    ((Interp *) interp)->objResultPtr = objResultPtr; \
+        } else { \
+	    if ((objResultPtr->bytes != NULL) \
+		    && (objResultPtr->bytes != tclEmptyStringRep)) { \
+	        ckfree((char *) objResultPtr->bytes); \
+	    } \
+	    objResultPtr->bytes  = tclEmptyStringRep; \
+	    objResultPtr->length = 0; \
+	    if ((objResultPtr->typePtr != NULL) \
+	            && (objResultPtr->typePtr->freeIntRepProc != NULL)) { \
+	        objResultPtr->typePtr->freeIntRepProc(objResultPtr); \
+	    } \
+	    objResultPtr->typePtr = (Tcl_ObjType *) NULL; \
+        } \
+    }
+
+/*
+ *----------------------------------------------------------------
+ * Procedures used in conjunction with Tcl namespaces. They are
+ * defined here instead of in tcl.h since they are not stable yet.
+ *----------------------------------------------------------------
+ */
+
+EXTERN void		Tcl_AddInterpResolvers _ANSI_ARGS_((Tcl_Interp *interp,
+ 			    char *name, Tcl_ResolveCmdProc *cmdProc,
+ 			    Tcl_ResolveVarProc *varProc,
+ 			    Tcl_ResolveCompiledVarProc *compiledVarProc));
+EXTERN int		Tcl_AppendExportList _ANSI_ARGS_((
+			    Tcl_Interp *interp, Tcl_Namespace *nsPtr,
+			    Tcl_Obj *objPtr));
+EXTERN Tcl_Namespace *	Tcl_CreateNamespace _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *name, ClientData clientData,
+			    Tcl_NamespaceDeleteProc *deleteProc));
+EXTERN void		Tcl_DeleteNamespace _ANSI_ARGS_((
+			    Tcl_Namespace *nsPtr));
+EXTERN int		Tcl_Export _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Namespace *nsPtr, char *pattern,
+			    int resetListFirst));
+EXTERN Tcl_Command	Tcl_FindCommand _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *name, Tcl_Namespace *contextNsPtr,
+			    int flags));
+EXTERN Tcl_Namespace *	Tcl_FindNamespace _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *name, Tcl_Namespace *contextNsPtr,
+			    int flags));
+EXTERN int              Tcl_GetInterpResolvers _ANSI_ARGS_((Tcl_Interp *interp,
+                            char *name, Tcl_ResolverInfo *resInfo));
+EXTERN int              Tcl_GetNamespaceResolvers _ANSI_ARGS_((
+			    Tcl_Namespace *namespacePtr,
+			    Tcl_ResolverInfo *resInfo));
+EXTERN void		Tcl_GetVariableFullName _ANSI_ARGS_((
+			    Tcl_Interp *interp, Tcl_Var variable,
+  			    Tcl_Obj *objPtr));
+EXTERN Tcl_Var		Tcl_FindNamespaceVar _ANSI_ARGS_((
+			    Tcl_Interp *interp, char *name,
+			    Tcl_Namespace *contextNsPtr, int flags));
+EXTERN int		Tcl_ForgetImport _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Namespace *nsPtr, char *pattern));
+EXTERN Tcl_Command	Tcl_GetCommandFromObj _ANSI_ARGS_((
+			    Tcl_Interp *interp, Tcl_Obj *objPtr));
+EXTERN void		Tcl_GetCommandFullName _ANSI_ARGS_((
+			    Tcl_Interp *interp, Tcl_Command command,
+			    Tcl_Obj *objPtr));
+EXTERN Tcl_Namespace *	Tcl_GetCurrentNamespace _ANSI_ARGS_((
+			    Tcl_Interp *interp));
+EXTERN Tcl_Namespace *	Tcl_GetGlobalNamespace _ANSI_ARGS_((
+			    Tcl_Interp *interp));
+EXTERN void		Tcl_GetVariableFullName _ANSI_ARGS_((
+			    Tcl_Interp *interp, Tcl_Var variable,
+			    Tcl_Obj *objPtr));
+EXTERN int		Tcl_Import _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Namespace *nsPtr, char *pattern,
+			    int allowOverwrite));
+EXTERN void		Tcl_PopCallFrame _ANSI_ARGS_((Tcl_Interp* interp));
+EXTERN int		Tcl_PushCallFrame _ANSI_ARGS_((Tcl_Interp* interp,
+			    Tcl_CallFrame *framePtr, Tcl_Namespace *nsPtr,
+			    int isProcCallFrame)); 
+EXTERN int		Tcl_RemoveInterpResolvers _ANSI_ARGS_((
+			    Tcl_Interp *interp, char *name));
+EXTERN void		Tcl_SetNamespaceResolvers _ANSI_ARGS_((
+			    Tcl_Namespace *namespacePtr,
+			    Tcl_ResolveCmdProc *cmdProc,
+			    Tcl_ResolveVarProc *varProc,
+			    Tcl_ResolveCompiledVarProc *compiledVarProc));
+
+# undef TCL_STORAGE_CLASS
+# define TCL_STORAGE_CLASS DLLIMPORT
+
+#endif /* _TCLINT */
+
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclLink.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclLink.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclLink.c	(revision 5)
@@ -0,0 +1,428 @@
+/* 
+ * tclLink.c --
+ *
+ *	This file implements linked variables (a C variable that is
+ *	tied to a Tcl variable).  The idea of linked variables was
+ *	first suggested by Andreas Stolcke and this implementation is
+ *	based heavily on a prototype implementation provided by
+ *	him.
+ *
+ * Copyright (c) 1993 The Regents of the University of California.
+ * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclLink.c,v 1.1 2008-06-04 13:58:07 demin Exp $
+ */
+
+#include "tclInt.h"
+
+/*
+ * For each linked variable there is a data structure of the following
+ * type, which describes the link and is the clientData for the trace
+ * set on the Tcl variable.
+ */
+
+typedef struct Link {
+    Tcl_Interp *interp;		/* Interpreter containing Tcl variable. */
+    char *varName;		/* Name of variable (must be global).  This
+				 * is needed during trace callbacks, since
+				 * the actual variable may be aliased at
+				 * that time via upvar. */
+    char *addr;			/* Location of C variable. */
+    int type;			/* Type of link (TCL_LINK_INT, etc.). */
+    union {
+	int i;
+	double d;
+    } lastValue;		/* Last known value of C variable;  used to
+				 * avoid string conversions. */
+    int flags;			/* Miscellaneous one-bit values;  see below
+				 * for definitions. */
+} Link;
+
+/*
+ * Definitions for flag bits:
+ * LINK_READ_ONLY -		1 means errors should be generated if Tcl
+ *				script attempts to write variable.
+ * LINK_BEING_UPDATED -		1 means that a call to Tcl_UpdateLinkedVar
+ *				is in progress for this variable, so
+ *				trace callbacks on the variable should
+ *				be ignored.
+ */
+
+#define LINK_READ_ONLY		1
+#define LINK_BEING_UPDATED	2
+
+/*
+ * Forward references to procedures defined later in this file:
+ */
+
+static char *		LinkTraceProc _ANSI_ARGS_((ClientData clientData,
+			    Tcl_Interp *interp, char *name1, char *name2,
+			    int flags));
+static char *		StringValue _ANSI_ARGS_((Link *linkPtr,
+			    char *buffer));
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LinkVar --
+ *
+ *	Link a C variable to a Tcl variable so that changes to either
+ *	one causes the other to change.
+ *
+ * Results:
+ *	The return value is TCL_OK if everything went well or TCL_ERROR
+ *	if an error occurred (interp->result is also set after errors).
+ *
+ * Side effects:
+ *	The value at *addr is linked to the Tcl variable "varName",
+ *	using "type" to convert between string values for Tcl and
+ *	binary values for *addr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_LinkVar(interp, varName, addr, type)
+    Tcl_Interp *interp;		/* Interpreter in which varName exists. */
+    char *varName;		/* Name of a global variable in interp. */
+    char *addr;			/* Address of a C variable to be linked
+				 * to varName. */
+    int type;			/* Type of C variable: TCL_LINK_INT, etc. 
+				 * Also may have TCL_LINK_READ_ONLY
+				 * OR'ed in. */
+{
+    Link *linkPtr;
+    char buffer[TCL_DOUBLE_SPACE];
+    int code;
+
+    linkPtr = (Link *) ckalloc(sizeof(Link));
+    linkPtr->interp = interp;
+    linkPtr->varName = (char *) ckalloc((unsigned) (strlen(varName) + 1));
+    strcpy(linkPtr->varName, varName);
+    linkPtr->addr = addr;
+    linkPtr->type = type & ~TCL_LINK_READ_ONLY;
+    if (type & TCL_LINK_READ_ONLY) {
+	linkPtr->flags = LINK_READ_ONLY;
+    } else {
+	linkPtr->flags = 0;
+    }
+    if (Tcl_SetVar(interp, varName, StringValue(linkPtr, buffer),
+	    TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
+	ckfree(linkPtr->varName);
+	ckfree((char *) linkPtr);
+	return TCL_ERROR;
+    }
+    code = Tcl_TraceVar(interp, varName, TCL_GLOBAL_ONLY|TCL_TRACE_READS
+	    |TCL_TRACE_WRITES|TCL_TRACE_UNSETS, LinkTraceProc,
+	    (ClientData) linkPtr);
+    if (code != TCL_OK) {
+	ckfree(linkPtr->varName);
+	ckfree((char *) linkPtr);
+    }
+    return code;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_UnlinkVar --
+ *
+ *	Destroy the link between a Tcl variable and a C variable.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	If "varName" was previously linked to a C variable, the link
+ *	is broken to make the variable independent.  If there was no
+ *	previous link for "varName" then nothing happens.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_UnlinkVar(interp, varName)
+    Tcl_Interp *interp;		/* Interpreter containing variable to unlink. */
+    char *varName;		/* Global variable in interp to unlink. */
+{
+    Link *linkPtr;
+
+    linkPtr = (Link *) Tcl_VarTraceInfo(interp, varName, TCL_GLOBAL_ONLY,
+	    LinkTraceProc, (ClientData) NULL);
+    if (linkPtr == NULL) {
+	return;
+    }
+    Tcl_UntraceVar(interp, varName,
+	    TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+	    LinkTraceProc, (ClientData) linkPtr);
+    ckfree(linkPtr->varName);
+    ckfree((char *) linkPtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_UpdateLinkedVar --
+ *
+ *	This procedure is invoked after a linked variable has been
+ *	changed by C code.  It updates the Tcl variable so that
+ *	traces on the variable will trigger.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The Tcl variable "varName" is updated from its C value,
+ *	causing traces on the variable to trigger.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_UpdateLinkedVar(interp, varName)
+    Tcl_Interp *interp;		/* Interpreter containing variable. */
+    char *varName;		/* Name of global variable that is linked. */
+{
+    Link *linkPtr;
+    char buffer[TCL_DOUBLE_SPACE];
+    int savedFlag;
+
+    linkPtr = (Link *) Tcl_VarTraceInfo(interp, varName, TCL_GLOBAL_ONLY,
+	    LinkTraceProc, (ClientData) NULL);
+    if (linkPtr == NULL) {
+	return;
+    }
+    savedFlag = linkPtr->flags & LINK_BEING_UPDATED;
+    linkPtr->flags |= LINK_BEING_UPDATED;
+    Tcl_SetVar(interp, linkPtr->varName, StringValue(linkPtr, buffer),
+	    TCL_GLOBAL_ONLY);
+    linkPtr->flags = (linkPtr->flags & ~LINK_BEING_UPDATED) | savedFlag;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * LinkTraceProc --
+ *
+ *	This procedure is invoked when a linked Tcl variable is read,
+ *	written, or unset from Tcl.  It's responsible for keeping the
+ *	C variable in sync with the Tcl variable.
+ *
+ * Results:
+ *	If all goes well, NULL is returned; otherwise an error message
+ *	is returned.
+ *
+ * Side effects:
+ *	The C variable may be updated to make it consistent with the
+ *	Tcl variable, or the Tcl variable may be overwritten to reject
+ *	a modification.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+LinkTraceProc(clientData, interp, name1, name2, flags)
+    ClientData clientData;	/* Contains information about the link. */
+    Tcl_Interp *interp;		/* Interpreter containing Tcl variable. */
+    char *name1;		/* First part of variable name. */
+    char *name2;		/* Second part of variable name. */
+    int flags;			/* Miscellaneous additional information. */
+{
+    Link *linkPtr = (Link *) clientData;
+    int changed;
+    char buffer[TCL_DOUBLE_SPACE];
+    char *value, **pp;
+    Tcl_DString savedResult;
+
+    /*
+     * If the variable is being unset, then just re-create it (with a
+     * trace) unless the whole interpreter is going away.
+     */
+
+    if (flags & TCL_TRACE_UNSETS) {
+	if (flags & TCL_INTERP_DESTROYED) {
+	    ckfree(linkPtr->varName);
+	    ckfree((char *) linkPtr);
+	} else if (flags & TCL_TRACE_DESTROYED) {
+	    Tcl_SetVar(interp, linkPtr->varName, StringValue(linkPtr, buffer),
+		    TCL_GLOBAL_ONLY);
+	    Tcl_TraceVar(interp, linkPtr->varName, TCL_GLOBAL_ONLY
+		    |TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		    LinkTraceProc, (ClientData) linkPtr);
+	}
+	return NULL;
+    }
+
+    /*
+     * If we were invoked because of a call to Tcl_UpdateLinkedVar, then
+     * don't do anything at all.  In particular, we don't want to get
+     * upset that the variable is being modified, even if it is
+     * supposed to be read-only.
+     */
+
+    if (linkPtr->flags & LINK_BEING_UPDATED) {
+	return NULL;
+    }
+
+    /*
+     * For read accesses, update the Tcl variable if the C variable
+     * has changed since the last time we updated the Tcl variable.
+     */
+
+    if (flags & TCL_TRACE_READS) {
+	switch (linkPtr->type) {
+	    case TCL_LINK_INT:
+	    case TCL_LINK_BOOLEAN:
+		changed = *(int *)(linkPtr->addr) != linkPtr->lastValue.i;
+		break;
+	    case TCL_LINK_DOUBLE:
+		changed = *(double *)(linkPtr->addr) != linkPtr->lastValue.d;
+		break;
+	    case TCL_LINK_STRING:
+		changed = 1;
+		break;
+	    default:
+		return "internal error: bad linked variable type";
+	}
+	if (changed) {
+	    Tcl_SetVar(interp, linkPtr->varName, StringValue(linkPtr, buffer),
+		    TCL_GLOBAL_ONLY);
+	}
+	return NULL;
+    }
+
+    /*
+     * For writes, first make sure that the variable is writable.  Then
+     * convert the Tcl value to C if possible.  If the variable isn't
+     * writable or can't be converted, then restore the varaible's old
+     * value and return an error.  Another tricky thing: we have to save
+     * and restore the interpreter's result, since the variable access
+     * could occur when the result has been partially set.
+     */
+
+    if (linkPtr->flags & LINK_READ_ONLY) {
+	Tcl_SetVar(interp, linkPtr->varName, StringValue(linkPtr, buffer),
+		TCL_GLOBAL_ONLY);
+	return "linked variable is read-only";
+    }
+    value = Tcl_GetVar(interp, linkPtr->varName, TCL_GLOBAL_ONLY);
+    if (value == NULL) {
+	/*
+	 * This shouldn't ever happen.
+	 */
+	return "internal error: linked variable couldn't be read";
+    }
+    Tcl_DStringInit(&savedResult);
+    Tcl_DStringAppend(&savedResult, interp->result, -1);
+    Tcl_ResetResult(interp);
+    switch (linkPtr->type) {
+	case TCL_LINK_INT:
+	    if (Tcl_GetInt(interp, value, &linkPtr->lastValue.i) != TCL_OK) {
+		Tcl_DStringResult(interp, &savedResult);
+		Tcl_SetVar(interp, linkPtr->varName,
+			StringValue(linkPtr, buffer), TCL_GLOBAL_ONLY);
+		return "variable must have integer value";
+	    }
+	    *(int *)(linkPtr->addr) = linkPtr->lastValue.i;
+	    break;
+	case TCL_LINK_DOUBLE:
+	    if (Tcl_GetDouble(interp, value, &linkPtr->lastValue.d)
+		    != TCL_OK) {
+		Tcl_DStringResult(interp, &savedResult);
+		Tcl_SetVar(interp, linkPtr->varName,
+			StringValue(linkPtr, buffer), TCL_GLOBAL_ONLY);
+		return "variable must have real value";
+	    }
+	    *(double *)(linkPtr->addr) = linkPtr->lastValue.d;
+	    break;
+	case TCL_LINK_BOOLEAN:
+	    if (Tcl_GetBoolean(interp, value, &linkPtr->lastValue.i)
+		    != TCL_OK) {
+		Tcl_DStringResult(interp, &savedResult);
+		Tcl_SetVar(interp, linkPtr->varName,
+			StringValue(linkPtr, buffer), TCL_GLOBAL_ONLY);
+		return "variable must have boolean value";
+	    }
+	    *(int *)(linkPtr->addr) = linkPtr->lastValue.i;
+	    break;
+	case TCL_LINK_STRING:
+	    pp = (char **)(linkPtr->addr);
+	    if (*pp != NULL) {
+		ckfree(*pp);
+	    }
+	    *pp = (char *) ckalloc((unsigned) (strlen(value) + 1));
+	    strcpy(*pp, value);
+	    break;
+	default:
+	    return "internal error: bad linked variable type";
+    }
+    Tcl_DStringResult(interp, &savedResult);
+    return NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringValue --
+ *
+ *	Converts the value of a C variable to a string for use in a
+ *	Tcl variable to which it is linked.
+ *
+ * Results:
+ *	The return value is a pointer
+ to a string that represents
+ *	the value of the C variable given by linkPtr.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+StringValue(linkPtr, buffer)
+    Link *linkPtr;		/* Structure describing linked variable. */
+    char *buffer;		/* Small buffer to use for converting
+				 * values.  Must have TCL_DOUBLE_SPACE
+				 * bytes or more. */
+{
+    char *p;
+
+    switch (linkPtr->type) {
+	case TCL_LINK_INT:
+	    linkPtr->lastValue.i = *(int *)(linkPtr->addr);
+	    TclFormatInt(buffer, linkPtr->lastValue.i);
+	    return buffer;
+	case TCL_LINK_DOUBLE:
+	    linkPtr->lastValue.d = *(double *)(linkPtr->addr);
+	    Tcl_PrintDouble((Tcl_Interp *) NULL, linkPtr->lastValue.d, buffer);
+	    return buffer;
+	case TCL_LINK_BOOLEAN:
+	    linkPtr->lastValue.i = *(int *)(linkPtr->addr);
+	    if (linkPtr->lastValue.i != 0) {
+		return "1";
+	    }
+	    return "0";
+	case TCL_LINK_STRING:
+	    p = *(char **)(linkPtr->addr);
+	    if (p == NULL) {
+		return "NULL";
+	    }
+	    return p;
+    }
+
+    /*
+     * This code only gets executed if the link type is unknown
+     * (shouldn't ever happen).
+     */
+
+    return "??";
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclListObj.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclListObj.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclListObj.c	(revision 5)
@@ -0,0 +1,1069 @@
+/* 
+ * tclListObj.c --
+ *
+ *	This file contains procedures that implement the Tcl list object
+ *	type.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclListObj.c,v 1.1 2008-06-04 13:58:07 demin Exp $
+ */
+
+#include "tclInt.h"
+
+/*
+ * Prototypes for procedures defined later in this file:
+ */
+
+static void		DupListInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
+			    Tcl_Obj *copyPtr));
+static void		FreeListInternalRep _ANSI_ARGS_((Tcl_Obj *listPtr));
+static int		SetListFromAny _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr));
+static void		UpdateStringOfList _ANSI_ARGS_((Tcl_Obj *listPtr));
+
+/*
+ * The structure below defines the list Tcl object type by means of
+ * procedures that can be invoked by generic object code.
+ */
+
+Tcl_ObjType tclListType = {
+    "list",				/* name */
+    FreeListInternalRep,		/* freeIntRepProc */
+    DupListInternalRep,		        /* dupIntRepProc */
+    UpdateStringOfList,			/* updateStringProc */
+    SetListFromAny			/* setFromAnyProc */
+};
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_NewListObj --
+ *
+ *	This procedure is normally called when not debugging: i.e., when
+ *	TCL_MEM_DEBUG is not defined. It creates a new list object from an
+ *	(objc,objv) array: that is, each of the objc elements of the array
+ *	referenced by objv is inserted as an element into a new Tcl object.
+ *
+ *	When TCL_MEM_DEBUG is defined, this procedure just returns the
+ *	result of calling the debugging version Tcl_DbNewListObj.
+ *
+ * Results:
+ *	A new list object is returned that is initialized from the object
+ *	pointers in objv. If objc is less than or equal to zero, an empty
+ *	object is returned. The new object's string representation
+ *	is left NULL. The resulting new list object has ref count 0.
+ *
+ * Side effects:
+ *	The ref counts of the elements in objv are incremented since the
+ *	resulting list now refers to them.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_MEM_DEBUG
+#undef Tcl_NewListObj
+
+Tcl_Obj *
+Tcl_NewListObj(objc, objv)
+    int objc;			/* Count of objects referenced by objv. */
+    Tcl_Obj *CONST objv[];	/* An array of pointers to Tcl objects. */
+{
+    return Tcl_DbNewListObj(objc, objv, "unknown", 0);
+}
+
+#else /* if not TCL_MEM_DEBUG */
+
+Tcl_Obj *
+Tcl_NewListObj(objc, objv)
+    int objc;			/* Count of objects referenced by objv. */
+    Tcl_Obj *CONST objv[];	/* An array of pointers to Tcl objects. */
+{
+    register Tcl_Obj *listPtr;
+    register Tcl_Obj **elemPtrs;
+    register List *listRepPtr;
+    int i;
+    
+    TclNewObj(listPtr);
+    
+    if (objc > 0) {
+	Tcl_InvalidateStringRep(listPtr);
+	
+	elemPtrs = (Tcl_Obj **)
+	    ckalloc((unsigned) (objc * sizeof(Tcl_Obj *)));
+	for (i = 0;  i < objc;  i++) {
+	    elemPtrs[i] = objv[i];
+	    Tcl_IncrRefCount(elemPtrs[i]);
+	}
+	
+	listRepPtr = (List *) ckalloc(sizeof(List));
+	listRepPtr->maxElemCount = objc;
+	listRepPtr->elemCount    = objc;
+	listRepPtr->elements     = elemPtrs;
+	
+	listPtr->internalRep.otherValuePtr = (VOID *) listRepPtr;
+	listPtr->typePtr = &tclListType;
+    }
+    return listPtr;
+}
+#endif /* if TCL_MEM_DEBUG */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DbNewListObj --
+ *
+ *	This procedure is normally called when debugging: i.e., when
+ *	TCL_MEM_DEBUG is defined. It creates new list objects. It is the
+ *	same as the Tcl_NewListObj procedure above except that it calls
+ *	Tcl_DbCkalloc directly with the file name and line number from its
+ *	caller. This simplifies debugging since then the checkmem command
+ *	will report the correct file name and line number when reporting
+ *	objects that haven't been freed.
+ *
+ *	When TCL_MEM_DEBUG is not defined, this procedure just returns the
+ *	result of calling Tcl_NewListObj.
+ *
+ * Results:
+ *	A new list object is returned that is initialized from the object
+ *	pointers in objv. If objc is less than or equal to zero, an empty
+ *	object is returned. The new object's string representation
+ *	is left NULL. The new list object has ref count 0.
+ *
+ * Side effects:
+ *	The ref counts of the elements in objv are incremented since the
+ *	resulting list now refers to them.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_MEM_DEBUG
+
+Tcl_Obj *
+Tcl_DbNewListObj(objc, objv, file, line)
+    int objc;			/* Count of objects referenced by objv. */
+    Tcl_Obj *CONST objv[];	/* An array of pointers to Tcl objects. */
+    char *file;			/* The name of the source file calling this
+				 * procedure; used for debugging. */
+    int line;			/* Line number in the source file; used
+				 * for debugging. */
+{
+    register Tcl_Obj *listPtr;
+    register Tcl_Obj **elemPtrs;
+    register List *listRepPtr;
+    int i;
+    
+    TclDbNewObj(listPtr, file, line);
+    
+    if (objc > 0) {
+	Tcl_InvalidateStringRep(listPtr);
+	
+	elemPtrs = (Tcl_Obj **)
+	    ckalloc((unsigned) (objc * sizeof(Tcl_Obj *)));
+	for (i = 0;  i < objc;  i++) {
+	    elemPtrs[i] = objv[i];
+	    Tcl_IncrRefCount(elemPtrs[i]);
+	}
+	
+	listRepPtr = (List *) ckalloc(sizeof(List));
+	listRepPtr->maxElemCount = objc;
+	listRepPtr->elemCount    = objc;
+	listRepPtr->elements     = elemPtrs;
+	
+	listPtr->internalRep.otherValuePtr = (VOID *) listRepPtr;
+	listPtr->typePtr = &tclListType;
+    }
+    return listPtr;
+}
+
+#else /* if not TCL_MEM_DEBUG */
+
+Tcl_Obj *
+Tcl_DbNewListObj(objc, objv, file, line)
+    int objc;			/* Count of objects referenced by objv. */
+    Tcl_Obj *CONST objv[];	/* An array of pointers to Tcl objects. */
+    char *file;			/* The name of the source file calling this
+				 * procedure; used for debugging. */
+    int line;			/* Line number in the source file; used
+				 * for debugging. */
+{
+    return Tcl_NewListObj(objc, objv);
+}
+#endif /* TCL_MEM_DEBUG */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetListObj --
+ *
+ *	Modify an object to be a list containing each of the objc elements
+ *	of the object array referenced by objv.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The object is made a list object and is initialized from the object
+ *	pointers in objv. If objc is less than or equal to zero, an empty
+ *	object is returned. The new object's string representation
+ *	is left NULL. The ref counts of the elements in objv are incremented
+ *	since the list now refers to them. The object's old string and
+ *	internal representations are freed and its type is set NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetListObj(objPtr, objc, objv)
+    Tcl_Obj *objPtr;		/* Object whose internal rep to init. */
+    int objc;			/* Count of objects referenced by objv. */
+    Tcl_Obj *CONST objv[];	/* An array of pointers to Tcl objects. */
+{
+    register Tcl_Obj **elemPtrs;
+    register List *listRepPtr;
+    Tcl_ObjType *oldTypePtr = objPtr->typePtr;
+    int i;
+
+    if (Tcl_IsShared(objPtr)) {
+	panic("Tcl_SetListObj called with shared object");
+    }
+    
+    /*
+     * Free any old string rep and any internal rep for the old type.
+     */
+
+    Tcl_InvalidateStringRep(objPtr);
+    if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
+	oldTypePtr->freeIntRepProc(objPtr);
+	objPtr->typePtr = NULL;
+    }
+        
+    /*
+     * Set the object's type to "list" and initialize the internal rep.
+     */
+
+    if (objc > 0) {
+	elemPtrs = (Tcl_Obj **)
+	    ckalloc((unsigned) (objc * sizeof(Tcl_Obj *)));
+	for (i = 0;  i < objc;  i++) {
+	    elemPtrs[i] = objv[i];
+	    Tcl_IncrRefCount(elemPtrs[i]);
+	}
+	
+	listRepPtr = (List *) ckalloc(sizeof(List));
+	listRepPtr->maxElemCount = objc;
+	listRepPtr->elemCount    = objc;
+	listRepPtr->elements     = elemPtrs;
+	
+	objPtr->internalRep.otherValuePtr = (VOID *) listRepPtr;
+	objPtr->typePtr = &tclListType;
+    } else {
+	objPtr->bytes = tclEmptyStringRep;
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ListObjGetElements --
+ *
+ *	This procedure returns an (objc,objv) array of the elements in a
+ *	list object.
+ *
+ * Results:
+ *	The return value is normally TCL_OK; in this case *objcPtr is set to
+ *	the count of list elements and *objvPtr is set to a pointer to an
+ *	array of (*objcPtr) pointers to each list element. If listPtr does
+ *	not refer to a list object and the object can not be converted to
+ *	one, TCL_ERROR is returned and an error message will be left in
+ *	the interpreter's result if interp is not NULL.
+ *
+ *	The objects referenced by the returned array should be treated as
+ *	readonly and their ref counts are _not_ incremented; the caller must
+ *	do that if it holds on to a reference. Furthermore, the pointer
+ *	and length returned by this procedure may change as soon as any
+ *	procedure is called on the list object; be careful about retaining
+ *	the pointer in a local data structure.
+ *
+ * Side effects:
+ *	The possible conversion of the object referenced by listPtr
+ *	to a list object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_ListObjGetElements(interp, listPtr, objcPtr, objvPtr)
+    Tcl_Interp *interp;		/* Used to report errors if not NULL. */
+    register Tcl_Obj *listPtr;	/* List object for which an element array
+				 * is to be returned. */
+    int *objcPtr;		/* Where to store the count of objects
+				 * referenced by objv. */
+    Tcl_Obj ***objvPtr;		/* Where to store the pointer to an array
+				 * of pointers to the list's objects. */
+{
+    register List *listRepPtr;
+
+    if (listPtr->typePtr != &tclListType) {
+	int result = SetListFromAny(interp, listPtr);
+	if (result != TCL_OK) {
+	    return result;
+	}
+    }
+    listRepPtr = (List *) listPtr->internalRep.otherValuePtr;
+    *objcPtr = listRepPtr->elemCount;
+    *objvPtr = listRepPtr->elements;
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ListObjAppendList --
+ *
+ *	This procedure appends the objects in the list referenced by
+ *	elemListPtr to the list object referenced by listPtr. If listPtr is
+ *	not already a list object, an attempt will be made to convert it to
+ *	one.
+ *
+ * Results:
+ *	The return value is normally TCL_OK. If listPtr or elemListPtr do
+ *	not refer to list objects and they can not be converted to one,
+ *	TCL_ERROR is returned and an error message is left in
+ *	the interpreter's result if interp is not NULL.
+ *
+ * Side effects:
+ *	The reference counts of the elements in elemListPtr are incremented
+ *	since the list now refers to them. listPtr and elemListPtr are
+ *	converted, if necessary, to list objects. Also, appending the
+ *	new elements may cause listObj's array of element pointers to grow.
+ *	listPtr's old string representation, if any, is invalidated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_ListObjAppendList(interp, listPtr, elemListPtr)
+    Tcl_Interp *interp;		/* Used to report errors if not NULL. */
+    register Tcl_Obj *listPtr;	/* List object to append elements to. */
+    Tcl_Obj *elemListPtr;	/* List obj with elements to append. */
+{
+    register List *listRepPtr;
+    int listLen, objc, result;
+    Tcl_Obj **objv;
+
+    if (Tcl_IsShared(listPtr)) {
+	panic("Tcl_ListObjAppendList called with shared object");
+    }
+    if (listPtr->typePtr != &tclListType) {
+	result = SetListFromAny(interp, listPtr);
+	if (result != TCL_OK) {
+	    return result;
+	}
+    }
+    listRepPtr = (List *) listPtr->internalRep.otherValuePtr;
+    listLen = listRepPtr->elemCount;
+
+    result = Tcl_ListObjGetElements(interp, elemListPtr, &objc, &objv);
+    if (result != TCL_OK) {
+	return result;
+    }
+
+    /*
+     * Insert objc new elements starting after the lists's last element.
+     * Delete zero existing elements.
+     */
+    
+    return Tcl_ListObjReplace(interp, listPtr, listLen, 0, objc, objv);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ListObjAppendElement --
+ *
+ *	This procedure is a special purpose version of
+ *	Tcl_ListObjAppendList: it appends a single object referenced by
+ *	objPtr to the list object referenced by listPtr. If listPtr is not
+ *	already a list object, an attempt will be made to convert it to one.
+ *
+ * Results:
+ *	The return value is normally TCL_OK; in this case objPtr is added
+ *	to the end of listPtr's list. If listPtr does not refer to a list
+ *	object and the object can not be converted to one, TCL_ERROR is
+ *	returned and an error message will be left in the interpreter's
+ *	result if interp is not NULL.
+ *
+ * Side effects:
+ *	The ref count of objPtr is incremented since the list now refers 
+ *	to it. listPtr will be converted, if necessary, to a list object.
+ *	Also, appending the new element may cause listObj's array of element
+ *	pointers to grow. listPtr's old string representation, if any,
+ *	is invalidated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_ListObjAppendElement(interp, listPtr, objPtr)
+    Tcl_Interp *interp;		/* Used to report errors if not NULL. */
+    Tcl_Obj *listPtr;		/* List object to append objPtr to. */
+    Tcl_Obj *objPtr;		/* Object to append to listPtr's list. */
+{
+    register List *listRepPtr;
+    register Tcl_Obj **elemPtrs;
+    int numElems, numRequired;
+    
+    if (Tcl_IsShared(listPtr)) {
+	panic("Tcl_ListObjAppendElement called with shared object");
+    }
+    if (listPtr->typePtr != &tclListType) {
+	int result = SetListFromAny(interp, listPtr);
+	if (result != TCL_OK) {
+	    return result;
+	}
+    }
+
+    listRepPtr = (List *) listPtr->internalRep.otherValuePtr;
+    elemPtrs = listRepPtr->elements;
+    numElems = listRepPtr->elemCount;
+    numRequired = numElems + 1 ;
+    
+    /*
+     * If there is no room in the current array of element pointers,
+     * allocate a new, larger array and copy the pointers to it.
+     */
+
+    if (numRequired > listRepPtr->maxElemCount) {
+	int newMax = (2 * numRequired);
+	Tcl_Obj **newElemPtrs = (Tcl_Obj **)
+	    ckalloc((unsigned) (newMax * sizeof(Tcl_Obj *)));
+	
+	memcpy((VOID *) newElemPtrs, (VOID *) elemPtrs,
+	       (size_t) (numElems * sizeof(Tcl_Obj *)));
+
+	listRepPtr->maxElemCount = newMax;
+	listRepPtr->elements = newElemPtrs;
+	ckfree((char *) elemPtrs);
+	elemPtrs = newElemPtrs;
+    }
+
+    /*
+     * Add objPtr to the end of listPtr's array of element
+     * pointers. Increment the ref count for the (now shared) objPtr.
+     */
+
+    elemPtrs[numElems] = objPtr;
+    Tcl_IncrRefCount(objPtr);
+    listRepPtr->elemCount++;
+
+    /*
+     * Invalidate any old string representation since the list's internal
+     * representation has changed.
+     */
+
+    Tcl_InvalidateStringRep(listPtr);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ListObjIndex --
+ *
+ *	This procedure returns a pointer to the index'th object from the
+ *	list referenced by listPtr. The first element has index 0. If index
+ *	is negative or greater than or equal to the number of elements in
+ *	the list, a NULL is returned. If listPtr is not a list object, an
+ *	attempt will be made to convert it to a list.
+ *
+ * Results:
+ *	The return value is normally TCL_OK; in this case objPtrPtr is set
+ *	to the Tcl_Obj pointer for the index'th list element or NULL if
+ *	index is out of range. This object should be treated as readonly and
+ *	its ref count is _not_ incremented; the caller must do that if it
+ *	holds on to the reference. If listPtr does not refer to a list and
+ *	can't be converted to one, TCL_ERROR is returned and an error
+ *	message is left in the interpreter's result if interp is not NULL.
+ *
+ * Side effects:
+ *	listPtr will be converted, if necessary, to a list object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_ListObjIndex(interp, listPtr, index, objPtrPtr)
+    Tcl_Interp *interp;		/* Used to report errors if not NULL. */
+    register Tcl_Obj *listPtr;	/* List object to index into. */
+    register int index;		/* Index of element to return. */
+    Tcl_Obj **objPtrPtr;	/* The resulting Tcl_Obj* is stored here. */
+{
+    register List *listRepPtr;
+    
+    if (listPtr->typePtr != &tclListType) {
+	int result = SetListFromAny(interp, listPtr);
+	if (result != TCL_OK) {
+	    return result;
+	}
+    }
+
+    listRepPtr = (List *) listPtr->internalRep.otherValuePtr;
+    if ((index < 0) || (index >= listRepPtr->elemCount)) {
+	*objPtrPtr = NULL;
+    } else {
+	*objPtrPtr = listRepPtr->elements[index];
+    }
+    
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ListObjLength --
+ *
+ *	This procedure returns the number of elements in a list object. If
+ *	the object is not already a list object, an attempt will be made to
+ *	convert it to one.
+ *
+ * Results:
+ *	The return value is normally TCL_OK; in this case *intPtr will be
+ *	set to the integer count of list elements. If listPtr does not refer
+ *	to a list object and the object can not be converted to one,
+ *	TCL_ERROR is returned and an error message will be left in
+ *	the interpreter's result if interp is not NULL.
+ *
+ * Side effects:
+ *	The possible conversion of the argument object to a list object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_ListObjLength(interp, listPtr, intPtr)
+    Tcl_Interp *interp;		/* Used to report errors if not NULL. */
+    register Tcl_Obj *listPtr;	/* List object whose #elements to return. */
+    register int *intPtr;	/* The resulting int is stored here. */
+{
+    register List *listRepPtr;
+    
+    if (listPtr->typePtr != &tclListType) {
+	int result = SetListFromAny(interp, listPtr);
+	if (result != TCL_OK) {
+	    return result;
+	}
+    }
+
+    listRepPtr = (List *) listPtr->internalRep.otherValuePtr;
+    *intPtr = listRepPtr->elemCount;
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ListObjReplace --
+ * 
+ *	This procedure replaces zero or more elements of the list referenced
+ *	by listPtr with the objects from an (objc,objv) array. 
+ *	The objc elements of the array referenced by objv replace the
+ *	count elements in listPtr starting at first.
+ *
+ *	If the argument first is zero or negative, it refers to the first
+ *	element. If first is greater than or equal to the number of elements
+ *	in the list, then no elements are deleted; the new elements are
+ *	appended to the list. Count gives the number of elements to
+ *	replace. If count is zero or negative then no elements are deleted;
+ *	the new elements are simply inserted before first.
+ *
+ *	The argument objv refers to an array of objc pointers to the new
+ *	elements to be added to listPtr in place of those that were
+ *	deleted. If objv is NULL, no new elements are added. If listPtr is
+ *	not a list object, an attempt will be made to convert it to one.
+ *
+ * Results:
+ *	The return value is normally TCL_OK. If listPtr does
+ *	not refer to a list object and can not be converted to one,
+ *	TCL_ERROR is returned and an error message will be left in
+ *	the interpreter's result if interp is not NULL.
+ *
+ * Side effects:
+ *	The ref counts of the objc elements in objv are incremented since
+ *	the resulting list now refers to them. Similarly, the ref counts for
+ *	replaced objects are decremented. listPtr is converted, if
+ *	necessary, to a list object. listPtr's old string representation, if
+ *	any, is freed. 
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_ListObjReplace(interp, listPtr, first, count, objc, objv)
+    Tcl_Interp *interp;		/* Used for error reporting if not NULL. */
+    Tcl_Obj *listPtr;		/* List object whose elements to replace. */
+    int first;			/* Index of first element to replace. */
+    int count;			/* Number of elements to replace. */
+    int objc;			/* Number of objects to insert. */
+    Tcl_Obj *CONST objv[];	/* An array of objc pointers to Tcl objects
+				 * to insert. */
+{
+    List *listRepPtr;
+    register Tcl_Obj **elemPtrs, **newPtrs;
+    Tcl_Obj *victimPtr;
+    int numElems, numRequired, numAfterLast;
+    int start, shift, newMax, i, j, result;
+     
+    if (Tcl_IsShared(listPtr)) {
+	panic("Tcl_ListObjReplace called with shared object");
+    }
+    if (listPtr->typePtr != &tclListType) {
+	result = SetListFromAny(interp, listPtr);
+	if (result != TCL_OK) {
+	    return result;
+	}
+    }
+    listRepPtr = (List *) listPtr->internalRep.otherValuePtr;
+    elemPtrs = listRepPtr->elements;
+    numElems = listRepPtr->elemCount;
+
+    if (first < 0)  {
+    	first = 0;
+    }
+    if (first >= numElems) {
+	first = numElems;	/* so we'll insert after last element */
+    }
+    if (count < 0) {
+	count = 0;
+    }
+    
+    numRequired = (numElems - count + objc);
+    if (numRequired <= listRepPtr->maxElemCount) {
+	/*
+	 * Enough room in the current array. First "delete" count
+	 * elements starting at first.
+	 */
+
+	for (i = 0, j = first;  i < count;  i++, j++) {
+	    victimPtr = elemPtrs[j];
+	    TclDecrRefCount(victimPtr);
+	}
+
+	/*
+	 * Shift the elements after the last one removed to their
+	 * new locations.
+	 */
+
+	start = (first + count);
+	numAfterLast = (numElems - start);
+	shift = (objc - count);	/* numNewElems - numDeleted */
+	if ((numAfterLast > 0) && (shift != 0)) {
+	    Tcl_Obj **src, **dst;
+
+	    if (shift < 0) {
+		for (src = elemPtrs + start, dst = src + shift;
+			numAfterLast > 0; numAfterLast--, src++, dst++) {
+		    *dst = *src;
+		}
+	    } else {
+		for (src = elemPtrs + numElems - 1, dst = src + shift;
+			numAfterLast > 0; numAfterLast--, src--, dst--) {
+		    *dst = *src;
+		}
+	    }
+	}
+
+	/*
+	 * Insert the new elements into elemPtrs before "first".
+	 */
+
+	for (i = 0, j = first;  i < objc;  i++, j++) {
+            elemPtrs[j] = objv[i];
+            Tcl_IncrRefCount(objv[i]);
+        }
+
+	/*
+	 * Update the count of elements.
+	 */
+
+	listRepPtr->elemCount = numRequired;
+    } else {
+	/*
+	 * Not enough room in the current array. Allocate a larger array and
+	 * insert elements into it. 
+	 */
+
+	newMax = (2 * numRequired);
+	newPtrs = (Tcl_Obj **)
+	    ckalloc((unsigned) (newMax * sizeof(Tcl_Obj *)));
+
+	/*
+	 * Copy over the elements before "first".
+	 */
+
+	if (first > 0) {
+	    memcpy((VOID *) newPtrs, (VOID *) elemPtrs,
+		    (size_t) (first * sizeof(Tcl_Obj *)));
+	}
+
+	/*
+	 * "Delete" count elements starting at first.
+	 */
+
+	for (i = 0, j = first;  i < count;  i++, j++) {
+	    victimPtr = elemPtrs[j];
+	    TclDecrRefCount(victimPtr);
+	}
+
+	/*
+	 * Copy the elements after the last one removed, shifted to
+	 * their new locations.
+	 */
+
+	start = (first + count);
+	numAfterLast = (numElems - start);
+	if (numAfterLast > 0) {
+	    memcpy((VOID *) &(newPtrs[first + objc]),
+		    (VOID *) &(elemPtrs[start]),
+		    (size_t) (numAfterLast * sizeof(Tcl_Obj *)));
+	}
+	
+	/*
+	 * Insert the new elements before "first" and update the
+	 * count of elements.
+	 */
+
+	for (i = 0, j = first;  i < objc;  i++, j++) {
+	    newPtrs[j] = objv[i];
+	    Tcl_IncrRefCount(objv[i]);
+	}
+
+	listRepPtr->elemCount = numRequired;
+	listRepPtr->maxElemCount = newMax;
+	listRepPtr->elements = newPtrs;
+	ckfree((char *) elemPtrs);
+    }
+    
+    /*
+     * Invalidate and free any old string representation since it no longer
+     * reflects the list's internal representation.
+     */
+
+    Tcl_InvalidateStringRep(listPtr);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeListInternalRep --
+ *
+ *	Deallocate the storage associated with a list object's internal
+ *	representation.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Frees listPtr's List* internal representation and sets listPtr's
+ *	internalRep.otherValuePtr to NULL. Decrements the ref counts
+ *	of all element objects, which may free them.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeListInternalRep(listPtr)
+    Tcl_Obj *listPtr;		/* List object with internal rep to free. */
+{
+    register List *listRepPtr = (List *) listPtr->internalRep.otherValuePtr;
+    register Tcl_Obj **elemPtrs = listRepPtr->elements;
+    register Tcl_Obj *objPtr;
+    int numElems = listRepPtr->elemCount;
+    int i;
+    
+    for (i = 0;  i < numElems;  i++) {
+	objPtr = elemPtrs[i];
+	Tcl_DecrRefCount(objPtr);
+    }
+    ckfree((char *) elemPtrs);
+    ckfree((char *) listRepPtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupListInternalRep --
+ *
+ *	Initialize the internal representation of a list Tcl_Obj to a
+ *	copy of the internal representation of an existing list object. 
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	"srcPtr"s list internal rep pointer should not be NULL and we assume
+ *	it is not NULL. We set "copyPtr"s internal rep to a pointer to a
+ *	newly allocated List structure that, in turn, points to "srcPtr"s
+ *	element objects. Those element objects are not actually copied but
+ *	are shared between "srcPtr" and "copyPtr". The ref count of each
+ *	element object is incremented.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DupListInternalRep(srcPtr, copyPtr)
+    Tcl_Obj *srcPtr;		/* Object with internal rep to copy. */
+    Tcl_Obj *copyPtr;		/* Object with internal rep to set. */
+{
+    List *srcListRepPtr = (List *) srcPtr->internalRep.otherValuePtr;
+    int numElems = srcListRepPtr->elemCount;
+    int maxElems = srcListRepPtr->maxElemCount;
+    register Tcl_Obj **srcElemPtrs = srcListRepPtr->elements;
+    register Tcl_Obj **copyElemPtrs;
+    register List *copyListRepPtr;
+    int i;
+
+    /*
+     * Allocate a new List structure that points to "srcPtr"s element
+     * objects. Increment the ref counts for those (now shared) element
+     * objects.
+     */
+    
+    copyElemPtrs = (Tcl_Obj **)
+	ckalloc((unsigned) maxElems * sizeof(Tcl_Obj *));
+    for (i = 0;  i < numElems;  i++) {
+	copyElemPtrs[i] = srcElemPtrs[i];
+	Tcl_IncrRefCount(copyElemPtrs[i]);
+    }
+    
+    copyListRepPtr = (List *) ckalloc(sizeof(List));
+    copyListRepPtr->maxElemCount = maxElems;
+    copyListRepPtr->elemCount    = numElems;
+    copyListRepPtr->elements     = copyElemPtrs;
+    
+    copyPtr->internalRep.otherValuePtr = (VOID *) copyListRepPtr;
+    copyPtr->typePtr = &tclListType;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetListFromAny --
+ *
+ *	Attempt to generate a list internal form for the Tcl object
+ *	"objPtr".
+ *
+ * Results:
+ *	The return value is TCL_OK or TCL_ERROR. If an error occurs during
+ *	conversion, an error message is left in the interpreter's result
+ *	unless "interp" is NULL.
+ *
+ * Side effects:
+ *	If no error occurs, a list is stored as "objPtr"s internal
+ *	representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetListFromAny(interp, objPtr)
+    Tcl_Interp *interp;		/* Used for error reporting if not NULL. */
+    Tcl_Obj *objPtr;		/* The object to convert. */
+{
+    Tcl_ObjType *oldTypePtr = objPtr->typePtr;
+    char *string, *elemStart, *nextElem, *s;
+    int lenRemain, length, estCount, elemSize, hasBrace, i, j, result;
+    char *limit;		/* Points just after string's last byte. */
+    register char *p;
+    register Tcl_Obj **elemPtrs;
+    register Tcl_Obj *elemPtr;
+    List *listRepPtr;
+
+    /*
+     * Get the string representation. Make it up-to-date if necessary.
+     */
+
+    string = TclGetStringFromObj(objPtr, &length);
+
+    /*
+     * Parse the string into separate string objects, and create a List
+     * structure that points to the element string objects. We use a
+     * modified version of Tcl_SplitList's implementation to avoid one
+     * malloc and a string copy for each list element. First, estimate the
+     * number of elements by counting the number of space characters in the
+     * list.
+     */
+
+    limit = (string + length);
+    estCount = 1;
+    for (p = string;  p < limit;  p++) {
+	if (isspace(UCHAR(*p))) {
+	    estCount++;
+	}
+    }
+
+    /*
+     * Allocate a new List structure with enough room for "estCount"
+     * elements. Each element is a pointer to a Tcl_Obj with the appropriate
+     * string rep. The initial "estCount" elements are set using the
+     * corresponding "argv" strings.
+     */
+
+    elemPtrs = (Tcl_Obj **)
+	    ckalloc((unsigned) (estCount * sizeof(Tcl_Obj *)));
+    for (p = string, lenRemain = length, i = 0;
+	    lenRemain > 0;
+	    p = nextElem, lenRemain = (limit - nextElem), i++) {
+	result = TclFindElement(interp, p, lenRemain, &elemStart, &nextElem,
+				&elemSize, &hasBrace);
+	if (result != TCL_OK) {
+	    for (j = 0;  j < i;  j++) {
+		elemPtr = elemPtrs[j];
+		Tcl_DecrRefCount(elemPtr);
+	    }
+	    ckfree((char *) elemPtrs);
+	    return result;
+	}
+	if (elemStart >= limit) {
+	    break;
+	}
+	if (i > estCount) {
+	    panic("SetListFromAny: bad size estimate for list");
+	}
+
+	/*
+	 * Allocate a Tcl object for the element and initialize it from the
+	 * "elemSize" bytes starting at "elemStart".
+	 */
+
+	s = ckalloc((unsigned) elemSize + 1);
+	if (hasBrace) {
+	    memcpy((VOID *) s, (VOID *) elemStart,  (size_t) elemSize);
+	    s[elemSize] = 0;
+	} else {
+	    elemSize = TclCopyAndCollapse(elemSize, elemStart, s);
+	}
+	
+	TclNewObj(elemPtr);
+        elemPtr->bytes  = s;
+        elemPtr->length = elemSize;
+        elemPtrs[i] = elemPtr;
+	Tcl_IncrRefCount(elemPtr); /* since list now holds ref to it */
+    }
+
+    listRepPtr = (List *) ckalloc(sizeof(List));
+    listRepPtr->maxElemCount = estCount;
+    listRepPtr->elemCount    = i;
+    listRepPtr->elements     = elemPtrs;
+
+    /*
+     * Free the old internalRep before setting the new one. We do this as
+     * late as possible to allow the conversion code, in particular
+     * Tcl_GetStringFromObj, to use that old internalRep.
+     */
+
+    if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
+	oldTypePtr->freeIntRepProc(objPtr);
+    }
+
+    objPtr->internalRep.otherValuePtr = (VOID *) listRepPtr;
+    objPtr->typePtr = &tclListType;
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateStringOfList --
+ *
+ *	Update the string representation for a list object.
+ *	Note: This procedure does not invalidate an existing old string rep
+ *	so storage will be lost if this has not already been done. 
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The object's string is set to a valid string that results from
+ *	the list-to-string conversion. This string will be empty if the
+ *	list has no elements. The list internal representation
+ *	should not be NULL and we assume it is not NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateStringOfList(listPtr)
+    Tcl_Obj *listPtr;		/* List object with string rep to update. */
+{
+#   define LOCAL_SIZE 20
+    int localFlags[LOCAL_SIZE], *flagPtr;
+    List *listRepPtr = (List *) listPtr->internalRep.otherValuePtr;
+    int numElems = listRepPtr->elemCount;
+    register int i;
+    char *elem, *dst;
+    int length;
+
+    /*
+     * Convert each element of the list to string form and then convert it
+     * to proper list element form, adding it to the result buffer.
+     */
+
+    /*
+     * Pass 1: estimate space, gather flags.
+     */
+
+    if (numElems <= LOCAL_SIZE) {
+	flagPtr = localFlags;
+    } else {
+	flagPtr = (int *) ckalloc((unsigned) numElems*sizeof(int));
+    }
+    listPtr->length = 1;
+    for (i = 0; i < numElems; i++) {
+	elem = Tcl_GetStringFromObj(listRepPtr->elements[i], &length);
+	listPtr->length += Tcl_ScanCountedElement(elem, length,
+		&flagPtr[i]) + 1;
+    }
+
+    /*
+     * Pass 2: copy into string rep buffer.
+     */
+
+    listPtr->bytes = ckalloc((unsigned) listPtr->length);
+    dst = listPtr->bytes;
+    for (i = 0; i < numElems; i++) {
+	elem = Tcl_GetStringFromObj(listRepPtr->elements[i], &length);
+	dst += Tcl_ConvertCountedElement(elem, length, dst, flagPtr[i]);
+	*dst = ' ';
+	dst++;
+    }
+    if (flagPtr != localFlags) {
+	ckfree((char *) flagPtr);
+    }
+    if (dst == listPtr->bytes) {
+	*dst = 0;
+    } else {
+	dst--;
+	*dst = 0;
+    }
+    listPtr->length = dst - listPtr->bytes;
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclMath.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclMath.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclMath.h	(revision 5)
@@ -0,0 +1,27 @@
+/*
+ * tclMath.h --
+ *
+ *	This file is necessary because of Metrowerks CodeWarrior Pro 1
+ *	on the Macintosh. With 8-byte doubles turned on, the definitions of
+ *	sin, cos, acos, etc., are screwed up.  They are fine as long as
+ *	they are used as function calls, but if the function pointers
+ *	are passed around and used, they will crash hard on the 68K.
+ *
+ * Copyright (c) 1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclMath.h,v 1.1 2008-06-04 13:58:08 demin Exp $
+ */
+
+#ifndef _TCLMATH
+#define _TCLMATH
+
+#if defined(MAC_TCL)
+#   include "tclMacMath.h"
+#else
+#   include <math.h>
+#endif
+
+#endif /* _TCLMATH */
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclNamesp.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclNamesp.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclNamesp.c	(revision 5)
@@ -0,0 +1,3890 @@
+/*
+ * tclNamesp.c --
+ *
+ *      Contains support for namespaces, which provide a separate context of
+ *      commands and global variables. The global :: namespace is the
+ *      traditional Tcl "global" scope. Other namespaces are created as
+ *      children of the global namespace. These other namespaces contain
+ *      special-purpose commands and variables for packages.
+ *
+ * Copyright (c) 1993-1997 Lucent Technologies.
+ * Copyright (c) 1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * Originally implemented by
+ *   Michael J. McLennan
+ *   Bell Labs Innovations for Lucent Technologies
+ *   mmclennan@lucent.com
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclNamesp.c,v 1.1 2008-06-04 13:58:08 demin Exp $
+ */
+
+#include "tclInt.h"
+
+/*
+ * Flag passed to TclGetNamespaceForQualName to indicate that it should
+ * search for a namespace rather than a command or variable inside a
+ * namespace. Note that this flag's value must not conflict with the values
+ * of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, or CREATE_NS_IF_UNKNOWN.
+ */
+
+#define FIND_ONLY_NS	0x1000
+
+/*
+ * Initial sise of stack allocated space for tail list - used when resetting
+ * shadowed command references in the functin: TclResetShadowedCmdRefs.
+ */
+
+#define NUM_TRAIL_ELEMS 5
+
+/*
+ * Count of the number of namespaces created. This value is used as a
+ * unique id for each namespace.
+ */
+
+static long numNsCreated = 0; 
+
+/*
+ * This structure contains a cached pointer to a namespace that is the
+ * result of resolving the namespace's name in some other namespace. It is
+ * the internal representation for a nsName object. It contains the
+ * pointer along with some information that is used to check the cached
+ * pointer's validity.
+ */
+
+typedef struct ResolvedNsName {
+    Namespace *nsPtr;		/* A cached namespace pointer. */
+    long nsId;			/* nsPtr's unique namespace id. Used to
+				 * verify that nsPtr is still valid
+				 * (e.g., it's possible that the namespace
+				 * was deleted and a new one created at
+				 * the same address). */
+    Namespace *refNsPtr;	/* Points to the namespace containing the
+				 * reference (not the namespace that
+				 * contains the referenced namespace). */
+    int refCount;		/* Reference count: 1 for each nsName
+				 * object that has a pointer to this
+				 * ResolvedNsName structure as its internal
+				 * rep. This structure can be freed when
+				 * refCount becomes zero. */
+} ResolvedNsName;
+
+/*
+ * Declarations for procedures local to this file:
+ */
+
+static void		DeleteImportedCmd _ANSI_ARGS_((
+			    ClientData clientData));
+static void		DupNsNameInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr,
+			    Tcl_Obj *copyPtr));
+static void		FreeNsNameInternalRep _ANSI_ARGS_((
+			    Tcl_Obj *objPtr));
+static int		GetNamespaceFromObj _ANSI_ARGS_((
+			    Tcl_Interp *interp, Tcl_Obj *objPtr,
+			    Tcl_Namespace **nsPtrPtr));
+static int		InvokeImportedCmd _ANSI_ARGS_((
+			    ClientData clientData, Tcl_Interp *interp,
+			    int objc, Tcl_Obj *CONST objv[]));
+static int		NamespaceChildrenCmd _ANSI_ARGS_((
+			    ClientData dummy, Tcl_Interp *interp,
+			    int objc, Tcl_Obj *CONST objv[]));
+static int		NamespaceCodeCmd _ANSI_ARGS_((
+			    ClientData dummy, Tcl_Interp *interp,
+			    int objc, Tcl_Obj *CONST objv[]));
+static int		NamespaceCurrentCmd _ANSI_ARGS_((
+			    ClientData dummy, Tcl_Interp *interp,
+			    int objc, Tcl_Obj *CONST objv[]));
+static int		NamespaceDeleteCmd _ANSI_ARGS_((
+			    ClientData dummy, Tcl_Interp *interp,
+			    int objc, Tcl_Obj *CONST objv[]));
+static int		NamespaceEvalCmd _ANSI_ARGS_((
+			    ClientData dummy, Tcl_Interp *interp,
+			    int objc, Tcl_Obj *CONST objv[]));
+static int		NamespaceExportCmd _ANSI_ARGS_((
+			    ClientData dummy, Tcl_Interp *interp,
+			    int objc, Tcl_Obj *CONST objv[]));
+static int		NamespaceForgetCmd _ANSI_ARGS_((
+			    ClientData dummy, Tcl_Interp *interp,
+			    int objc, Tcl_Obj *CONST objv[]));
+static void		NamespaceFree _ANSI_ARGS_((Namespace *nsPtr));
+static int		NamespaceImportCmd _ANSI_ARGS_((
+			    ClientData dummy, Tcl_Interp *interp,
+			    int objc, Tcl_Obj *CONST objv[]));
+static int		NamespaceInscopeCmd _ANSI_ARGS_((
+			    ClientData dummy, Tcl_Interp *interp,
+			    int objc, Tcl_Obj *CONST objv[]));
+static int		NamespaceOriginCmd _ANSI_ARGS_((
+			    ClientData dummy, Tcl_Interp *interp,
+			    int objc, Tcl_Obj *CONST objv[]));
+static int		NamespaceParentCmd _ANSI_ARGS_((
+			    ClientData dummy, Tcl_Interp *interp,
+			    int objc, Tcl_Obj *CONST objv[]));
+static int		NamespaceQualifiersCmd _ANSI_ARGS_((
+			    ClientData dummy, Tcl_Interp *interp,
+			    int objc, Tcl_Obj *CONST objv[]));
+static int		NamespaceTailCmd _ANSI_ARGS_((
+			    ClientData dummy, Tcl_Interp *interp,
+			    int objc, Tcl_Obj *CONST objv[]));
+static int		NamespaceWhichCmd _ANSI_ARGS_((
+			    ClientData dummy, Tcl_Interp *interp,
+			    int objc, Tcl_Obj *CONST objv[]));
+static int		SetNsNameFromAny _ANSI_ARGS_((
+			    Tcl_Interp *interp, Tcl_Obj *objPtr));
+static void		UpdateStringOfNsName _ANSI_ARGS_((Tcl_Obj *objPtr));
+
+/*
+ * This structure defines a Tcl object type that contains a
+ * namespace reference.  It is used in commands that take the
+ * name of a namespace as an argument.  The namespace reference
+ * is resolved, and the result in cached in the object.
+ */
+
+Tcl_ObjType tclNsNameType = {
+    "nsName",			/* the type's name */
+    FreeNsNameInternalRep,	/* freeIntRepProc */
+    DupNsNameInternalRep,	/* dupIntRepProc */
+    UpdateStringOfNsName,	/* updateStringProc */
+    SetNsNameFromAny		/* setFromAnyProc */
+};
+
+/*
+ * Boolean flag indicating whether or not the namespName object
+ * type has been registered with the Tcl compiler.
+ */
+
+static int nsInitialized = 0;
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInitNamespaces --
+ *
+ *	Called when any interpreter is created to make sure that
+ *	things are properly set up for namespaces.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	On the first call, the namespName object type is registered
+ *	with the Tcl compiler.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclInitNamespaces()
+{
+    if (!nsInitialized) {
+        Tcl_RegisterObjType(&tclNsNameType);
+        nsInitialized = 1;
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetCurrentNamespace --
+ *
+ *	Returns a pointer to an interpreter's currently active namespace.
+ *
+ * Results:
+ *	Returns a pointer to the interpreter's current namespace.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Namespace *
+Tcl_GetCurrentNamespace(interp)
+    register Tcl_Interp *interp; /* Interpreter whose current namespace is
+				  * being queried. */
+{
+    register Interp *iPtr = (Interp *) interp;
+    register Namespace *nsPtr;
+
+    if (iPtr->varFramePtr != NULL) {
+        nsPtr = iPtr->varFramePtr->nsPtr;
+    } else {
+        nsPtr = iPtr->globalNsPtr;
+    }
+    return (Tcl_Namespace *) nsPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetGlobalNamespace --
+ *
+ *	Returns a pointer to an interpreter's global :: namespace.
+ *
+ * Results:
+ *	Returns a pointer to the specified interpreter's global namespace.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Namespace *
+Tcl_GetGlobalNamespace(interp)
+    register Tcl_Interp *interp; /* Interpreter whose global namespace 
+				  * should be returned. */
+{
+    register Interp *iPtr = (Interp *) interp;
+    
+    return (Tcl_Namespace *) iPtr->globalNsPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_PushCallFrame --
+ *
+ *	Pushes a new call frame onto the interpreter's Tcl call stack.
+ *	Called when executing a Tcl procedure or a "namespace eval" or
+ *	"namespace inscope" command. 
+ *
+ * Results:
+ *	Returns TCL_OK if successful, or TCL_ERROR (along with an error
+ *	message in the interpreter's result object) if something goes wrong.
+ *
+ * Side effects:
+ *	Modifies the interpreter's Tcl call stack.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_PushCallFrame(interp, callFramePtr, namespacePtr, isProcCallFrame)
+    Tcl_Interp *interp;		 /* Interpreter in which the new call frame
+				  * is to be pushed. */
+    Tcl_CallFrame *callFramePtr; /* Points to a call frame structure to
+				  * push. Storage for this have already been
+				  * allocated by the caller; typically this
+				  * is the address of a CallFrame structure
+				  * allocated on the caller's C stack.  The
+				  * call frame will be initialized by this
+				  * procedure. The caller can pop the frame
+				  * later with Tcl_PopCallFrame, and it is
+				  * responsible for freeing the frame's
+				  * storage. */
+    Tcl_Namespace *namespacePtr; /* Points to the namespace in which the
+				  * frame will execute. If NULL, the
+				  * interpreter's current namespace will
+				  * be used. */
+    int isProcCallFrame;	 /* If nonzero, the frame represents a
+				  * called Tcl procedure and may have local
+				  * vars. Vars will ordinarily be looked up
+				  * in the frame. If new variables are
+				  * created, they will be created in the
+				  * frame. If 0, the frame is for a
+				  * "namespace eval" or "namespace inscope"
+				  * command and var references are treated
+				  * as references to namespace variables. */
+{
+    Interp *iPtr = (Interp *) interp;
+    register CallFrame *framePtr = (CallFrame *) callFramePtr;
+    register Namespace *nsPtr;
+
+    if (namespacePtr == NULL) {
+	nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+    } else {
+        nsPtr = (Namespace *) namespacePtr;
+        if (nsPtr->flags & NS_DEAD) {
+           panic("Trying to push call frame for dead namespace");
+            /*NOTREACHED*/
+        }
+    }
+
+    nsPtr->activationCount++;
+    framePtr->nsPtr = nsPtr;
+    framePtr->isProcCallFrame = isProcCallFrame;
+    framePtr->objc = 0;
+    framePtr->objv = NULL;
+    framePtr->callerPtr = iPtr->framePtr;
+    framePtr->callerVarPtr = iPtr->varFramePtr;
+    if (iPtr->varFramePtr != NULL) {
+        framePtr->level = (iPtr->varFramePtr->level + 1);
+    } else {
+        framePtr->level = 1;
+    }
+    framePtr->procPtr = NULL; 	   /* no called procedure */
+    framePtr->varTablePtr = NULL;  /* and no local variables */
+    framePtr->numCompiledLocals = 0;
+    framePtr->compiledLocals = NULL;
+
+    /*
+     * Push the new call frame onto the interpreter's stack of procedure
+     * call frames making it the current frame.
+     */
+
+    iPtr->framePtr = framePtr;
+    iPtr->varFramePtr = framePtr;
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_PopCallFrame --
+ *
+ *	Removes a call frame from the Tcl call stack for the interpreter.
+ *	Called to remove a frame previously pushed by Tcl_PushCallFrame.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Modifies the call stack of the interpreter. Resets various fields of
+ *	the popped call frame. If a namespace has been deleted and
+ *	has no more activations on the call stack, the namespace is
+ *	destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_PopCallFrame(interp)
+    Tcl_Interp* interp;		/* Interpreter with call frame to pop. */
+{
+    register Interp *iPtr = (Interp *) interp;
+    register CallFrame *framePtr = iPtr->framePtr;
+    int saveErrFlag;
+    Namespace *nsPtr;
+
+    /*
+     * It's important to remove the call frame from the interpreter's stack
+     * of call frames before deleting local variables, so that traces
+     * invoked by the variable deletion don't see the partially-deleted
+     * frame.
+     */
+
+    iPtr->framePtr = framePtr->callerPtr;
+    iPtr->varFramePtr = framePtr->callerVarPtr;
+
+    /*
+     * Delete the local variables. As a hack, we save then restore the
+     * ERR_IN_PROGRESS flag in the interpreter. The problem is that there
+     * could be unset traces on the variables, which cause scripts to be
+     * evaluated. This will clear the ERR_IN_PROGRESS flag, losing stack
+     * trace information if the procedure was exiting with an error. The
+     * code below preserves the flag. Unfortunately, that isn't really
+     * enough: we really should preserve the errorInfo variable too
+     * (otherwise a nested error in the trace script will trash errorInfo).
+     * What's really needed is a general-purpose mechanism for saving and
+     * restoring interpreter state.
+     */
+
+    saveErrFlag = (iPtr->flags & ERR_IN_PROGRESS);
+
+    if (framePtr->varTablePtr != NULL) {
+        TclDeleteVars(iPtr, framePtr->varTablePtr);
+        ckfree((char *) framePtr->varTablePtr);
+        framePtr->varTablePtr = NULL;
+    }
+    if (framePtr->numCompiledLocals > 0) {
+        TclDeleteCompiledLocalVars(iPtr, framePtr);
+    }
+
+    iPtr->flags |= saveErrFlag;
+
+    /*
+     * Decrement the namespace's count of active call frames. If the
+     * namespace is "dying" and there are no more active call frames,
+     * call Tcl_DeleteNamespace to destroy it.
+     */
+
+    nsPtr = framePtr->nsPtr;
+    nsPtr->activationCount--;
+    if ((nsPtr->flags & NS_DYING)
+	    && (nsPtr->activationCount == 0)) {
+        Tcl_DeleteNamespace((Tcl_Namespace *) nsPtr);
+    }
+    framePtr->nsPtr = NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CreateNamespace --
+ *
+ *	Creates a new namespace with the given name. If there is no
+ *	active namespace (i.e., the interpreter is being initialized),
+ *	the global :: namespace is created and returned.
+ *
+ * Results:
+ *	Returns a pointer to the new namespace if successful. If the
+ *	namespace already exists or if another error occurs, this routine
+ *	returns NULL, along with an error message in the interpreter's
+ *	result object.
+ *
+ * Side effects:
+ *	If the name contains "::" qualifiers and a parent namespace does
+ *	not already exist, it is automatically created. 
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Namespace *
+Tcl_CreateNamespace(interp, name, clientData, deleteProc)
+    Tcl_Interp *interp;             /* Interpreter in which a new namespace
+				     * is being created. Also used for
+				     * error reporting. */
+    char *name;                     /* Name for the new namespace. May be a
+				     * qualified name with names of ancestor
+				     * namespaces separated by "::"s. */
+    ClientData clientData;	    /* One-word value to store with
+				     * namespace. */
+    Tcl_NamespaceDeleteProc *deleteProc;
+    				    /* Procedure called to delete client
+				     * data when the namespace is deleted.
+				     * NULL if no procedure should be
+				     * called. */
+{
+    Interp *iPtr = (Interp *) interp;
+    register Namespace *nsPtr, *ancestorPtr;
+    Namespace *parentPtr, *dummy1Ptr, *dummy2Ptr;
+    Namespace *globalNsPtr = iPtr->globalNsPtr;
+    char *simpleName;
+    Tcl_HashEntry *entryPtr;
+    Tcl_DString buffer1, buffer2;
+    int newEntry;
+
+    /*
+     * If there is no active namespace, the interpreter is being
+     * initialized. 
+     */
+
+    if ((globalNsPtr == NULL) && (iPtr->varFramePtr == NULL)) {
+	/*
+	 * Treat this namespace as the global namespace, and avoid
+	 * looking for a parent.
+	 */
+	
+        parentPtr = NULL;
+        simpleName = "";
+    } else if (*name == '\0') {
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		"can't create namespace \"\": only global namespace can have empty name", (char *) NULL);
+	return NULL;
+    } else {
+	/*
+	 * Find the parent for the new namespace.
+	 */
+
+       TclGetNamespaceForQualName(interp, name, (Namespace *) NULL,
+           /*flags*/ CREATE_NS_IF_UNKNOWN, &parentPtr, &dummy1Ptr,
+           &dummy2Ptr, &simpleName);
+
+	/*
+	 * If the unqualified name at the end is empty, there were trailing
+	 * "::"s after the namespace's name which we ignore. The new
+	 * namespace was already (recursively) created and is pointed to
+	 * by parentPtr.
+	 */
+
+	if (*simpleName == '\0') {
+	    return (Tcl_Namespace *) parentPtr;
+	}
+
+        /*
+         * Check for a bad namespace name and make sure that the name
+	 * does not already exist in the parent namespace.
+	 */
+
+        if (Tcl_FindHashEntry(&parentPtr->childTable, simpleName) != NULL) {
+	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		    "can't create namespace \"", name,
+    	    	    "\": already exists", (char *) NULL);
+            return NULL;
+        }
+    }
+
+    /*
+     * Create the new namespace and root it in its parent. Increment the
+     * count of namespaces created.
+     */
+
+    numNsCreated++;
+
+    nsPtr = (Namespace *) ckalloc(sizeof(Namespace));
+    nsPtr->name            = (char *) ckalloc((unsigned) (strlen(simpleName)+1));
+    strcpy(nsPtr->name, simpleName);
+    nsPtr->fullName        = NULL;   /* set below */
+    nsPtr->clientData      = clientData;
+    nsPtr->deleteProc      = deleteProc;
+    nsPtr->parentPtr       = parentPtr;
+    Tcl_InitHashTable(&nsPtr->childTable, TCL_STRING_KEYS);
+    nsPtr->nsId            = numNsCreated;
+    nsPtr->interp          = interp;
+    nsPtr->flags           = 0;
+    nsPtr->activationCount = 0;
+    nsPtr->refCount        = 0;
+    Tcl_InitHashTable(&nsPtr->cmdTable, TCL_STRING_KEYS);
+    Tcl_InitHashTable(&nsPtr->varTable, TCL_STRING_KEYS);
+    nsPtr->exportArrayPtr  = NULL;
+    nsPtr->numExportPatterns = 0;
+    nsPtr->maxExportPatterns = 0;
+    nsPtr->cmdRefEpoch       = 0;
+    nsPtr->resolverEpoch     = 0;
+    nsPtr->cmdResProc        = NULL;
+    nsPtr->varResProc        = NULL;
+    nsPtr->compiledVarResProc = NULL;
+
+    if (parentPtr != NULL) {
+        entryPtr = Tcl_CreateHashEntry(&parentPtr->childTable, simpleName,
+	        &newEntry);
+        Tcl_SetHashValue(entryPtr, (ClientData) nsPtr);
+    }
+
+    /*
+     * Build the fully qualified name for this namespace.
+     */
+
+    Tcl_DStringInit(&buffer1);
+    Tcl_DStringInit(&buffer2);
+    for (ancestorPtr = nsPtr;  ancestorPtr != NULL;
+	    ancestorPtr = ancestorPtr->parentPtr) {
+        if (ancestorPtr != globalNsPtr) {
+            Tcl_DStringAppend(&buffer1, "::", 2);
+            Tcl_DStringAppend(&buffer1, ancestorPtr->name, -1);
+        }
+        Tcl_DStringAppend(&buffer1, Tcl_DStringValue(&buffer2), -1);
+
+        Tcl_DStringSetLength(&buffer2, 0);
+        Tcl_DStringAppend(&buffer2, Tcl_DStringValue(&buffer1), -1);
+        Tcl_DStringSetLength(&buffer1, 0);
+    }
+    
+    name = Tcl_DStringValue(&buffer2);
+    nsPtr->fullName = (char *) ckalloc((unsigned) (strlen(name)+1));
+    strcpy(nsPtr->fullName, name);
+
+    Tcl_DStringFree(&buffer1);
+    Tcl_DStringFree(&buffer2);
+
+    /*
+     * Return a pointer to the new namespace.
+     */
+
+    return (Tcl_Namespace *) nsPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DeleteNamespace --
+ *
+ *	Deletes a namespace and all of the commands, variables, and other
+ *	namespaces within it.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	When a namespace is deleted, it is automatically removed as a
+ *	child of its parent namespace. Also, all its commands, variables
+ *	and child namespaces are deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DeleteNamespace(namespacePtr)
+    Tcl_Namespace *namespacePtr;   /* Points to the namespace to delete. */
+{
+    register Namespace *nsPtr = (Namespace *) namespacePtr;
+    Interp *iPtr = (Interp *) nsPtr->interp;
+    Namespace *globalNsPtr =
+	    (Namespace *) Tcl_GetGlobalNamespace((Tcl_Interp *) iPtr);
+    Tcl_HashEntry *entryPtr;
+
+    /*
+     * If the namespace is on the call frame stack, it is marked as "dying"
+     * (NS_DYING is OR'd into its flags): the namespace can't be looked up
+     * by name but its commands and variables are still usable by those
+     * active call frames. When all active call frames referring to the
+     * namespace have been popped from the Tcl stack, Tcl_PopCallFrame will
+     * call this procedure again to delete everything in the namespace.
+     * If no nsName objects refer to the namespace (i.e., if its refCount 
+     * is zero), its commands and variables are deleted and the storage for
+     * its namespace structure is freed. Otherwise, if its refCount is
+     * nonzero, the namespace's commands and variables are deleted but the
+     * structure isn't freed. Instead, NS_DEAD is OR'd into the structure's
+     * flags to allow the namespace resolution code to recognize that the
+     * namespace is "deleted". The structure's storage is freed by
+     * FreeNsNameInternalRep when its refCount reaches 0.
+     */
+
+    if (nsPtr->activationCount > 0) {
+        nsPtr->flags |= NS_DYING;
+        if (nsPtr->parentPtr != NULL) {
+            entryPtr = Tcl_FindHashEntry(&nsPtr->parentPtr->childTable,
+		    nsPtr->name);
+            if (entryPtr != NULL) {
+                Tcl_DeleteHashEntry(entryPtr);
+            }
+        }
+        nsPtr->parentPtr = NULL;
+    } else {
+	/*
+	 * Delete the namespace and everything in it. If this is the global
+	 * namespace, then clear it but don't free its storage unless the
+	 * interpreter is being torn down.
+	 */
+
+        TclTeardownNamespace(nsPtr);
+
+        if ((nsPtr != globalNsPtr) || (iPtr->flags & DELETED)) {
+            /*
+	     * If this is the global namespace, then it may have residual
+             * "errorInfo" and "errorCode" variables for errors that
+             * occurred while it was being torn down.  Try to clear the
+             * variable list one last time.
+	     */
+
+            TclDeleteVars((Interp *) nsPtr->interp, &nsPtr->varTable);
+	    
+            Tcl_DeleteHashTable(&nsPtr->childTable);
+            Tcl_DeleteHashTable(&nsPtr->cmdTable);
+
+            /*
+             * If the reference count is 0, then discard the namespace.
+             * Otherwise, mark it as "dead" so that it can't be used.
+             */
+
+            if (nsPtr->refCount == 0) {
+                NamespaceFree(nsPtr);
+            } else {
+                nsPtr->flags |= NS_DEAD;
+            }
+        }
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclTeardownNamespace --
+ *
+ *	Used internally to dismantle and unlink a namespace when it is
+ *	deleted. Divorces the namespace from its parent, and deletes all
+ *	commands, variables, and child namespaces.
+ *
+ *	This is kept separate from Tcl_DeleteNamespace so that the global
+ *	namespace can be handled specially. Global variables like
+ *	"errorInfo" and "errorCode" need to remain intact while other
+ *	namespaces and commands are torn down, in case any errors occur.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Removes this namespace from its parent's child namespace hashtable.
+ *	Deletes all commands, variables and namespaces in this namespace.
+ *	If this is the global namespace, the "errorInfo" and "errorCode"
+ *	variables are left alone and deleted later.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclTeardownNamespace(nsPtr)
+    register Namespace *nsPtr;	/* Points to the namespace to be dismantled
+				 * and unlinked from its parent. */
+{
+    Interp *iPtr = (Interp *) nsPtr->interp;
+    register Tcl_HashEntry *entryPtr;
+    Tcl_HashSearch search;
+    Tcl_Namespace *childNsPtr;
+    Tcl_Command cmd;
+    Namespace *globalNsPtr =
+	    (Namespace *) Tcl_GetGlobalNamespace((Tcl_Interp *) iPtr);
+    int i;
+
+    /*
+     * Start by destroying the namespace's variable table,
+     * since variables might trigger traces.
+     */
+
+    if (nsPtr == globalNsPtr) {
+	/*
+	 * This is the global namespace, so be careful to preserve the
+	 * "errorInfo" and "errorCode" variables. These might be needed
+	 * later on if errors occur while deleting commands. We are careful
+	 * to destroy and recreate the "errorInfo" and "errorCode"
+	 * variables, in case they had any traces on them.
+	 */
+    
+        char *str, *errorInfoStr, *errorCodeStr;
+
+        str = Tcl_GetVar((Tcl_Interp *) iPtr, "errorInfo", TCL_GLOBAL_ONLY);
+        if (str != NULL) {
+            errorInfoStr = ckalloc((unsigned) (strlen(str)+1));
+            strcpy(errorInfoStr, str);
+        } else {
+            errorInfoStr = NULL;
+        }
+
+        str = Tcl_GetVar((Tcl_Interp *) iPtr, "errorCode", TCL_GLOBAL_ONLY);
+        if (str != NULL) {
+            errorCodeStr = ckalloc((unsigned) (strlen(str)+1));
+            strcpy(errorCodeStr, str);
+        } else {
+            errorCodeStr = NULL;
+        }
+
+        TclDeleteVars(iPtr, &nsPtr->varTable);
+        Tcl_InitHashTable(&nsPtr->varTable, TCL_STRING_KEYS);
+
+        if (errorInfoStr != NULL) {
+            Tcl_SetVar((Tcl_Interp *) iPtr, "errorInfo", errorInfoStr,
+                TCL_GLOBAL_ONLY);
+            ckfree(errorInfoStr);
+        }
+        if (errorCodeStr != NULL) {
+            Tcl_SetVar((Tcl_Interp *) iPtr, "errorCode", errorCodeStr,
+                TCL_GLOBAL_ONLY);
+            ckfree(errorCodeStr);
+        }
+    } else {
+	/*
+	 * Variable table should be cleared but not freed! TclDeleteVars
+	 * frees it, so we reinitialize it afterwards.
+	 */
+    
+        TclDeleteVars(iPtr, &nsPtr->varTable);
+        Tcl_InitHashTable(&nsPtr->varTable, TCL_STRING_KEYS);
+    }
+
+    /*
+     * Remove the namespace from its parent's child hashtable.
+     */
+
+    if (nsPtr->parentPtr != NULL) {
+        entryPtr = Tcl_FindHashEntry(&nsPtr->parentPtr->childTable,
+	        nsPtr->name);
+        if (entryPtr != NULL) {
+            Tcl_DeleteHashEntry(entryPtr);
+        }
+    }
+    nsPtr->parentPtr = NULL;
+
+    /*
+     * Delete all the child namespaces.
+     *
+     * BE CAREFUL: When each child is deleted, it will divorce
+     *    itself from its parent. You can't traverse a hash table
+     *    properly if its elements are being deleted. We use only
+     *    the Tcl_FirstHashEntry function to be safe.
+     */
+
+    for (entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
+            entryPtr != NULL;
+            entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search)) {
+        childNsPtr = (Tcl_Namespace *) Tcl_GetHashValue(entryPtr);
+        Tcl_DeleteNamespace(childNsPtr);
+    }
+
+    /*
+     * Delete all commands in this namespace. Be careful when traversing the
+     * hash table: when each command is deleted, it removes itself from the
+     * command table.
+     */
+
+    for (entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
+            entryPtr != NULL;
+            entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search)) {
+        cmd = (Tcl_Command) Tcl_GetHashValue(entryPtr);
+        Tcl_DeleteCommandFromToken((Tcl_Interp *) iPtr, cmd);
+    }
+    Tcl_DeleteHashTable(&nsPtr->cmdTable);
+    Tcl_InitHashTable(&nsPtr->cmdTable, TCL_STRING_KEYS);
+
+    /*
+     * Free the namespace's export pattern array.
+     */
+
+    if (nsPtr->exportArrayPtr != NULL) {
+	for (i = 0;  i < nsPtr->numExportPatterns;  i++) {
+	    ckfree(nsPtr->exportArrayPtr[i]);
+	}
+        ckfree((char *) nsPtr->exportArrayPtr);
+	nsPtr->exportArrayPtr = NULL;
+	nsPtr->numExportPatterns = 0;
+	nsPtr->maxExportPatterns = 0;
+    }
+
+    /*
+     * Free any client data associated with the namespace.
+     */
+
+    if (nsPtr->deleteProc != NULL) {
+        (*nsPtr->deleteProc)(nsPtr->clientData);
+    }
+    nsPtr->deleteProc = NULL;
+    nsPtr->clientData = NULL;
+
+    /*
+     * Reset the namespace's id field to ensure that this namespace won't
+     * be interpreted as valid by, e.g., the cache validation code for
+     * cached command references in Tcl_GetCommandFromObj.
+     */
+
+    nsPtr->nsId = 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NamespaceFree --
+ *
+ *	Called after a namespace has been deleted, when its
+ *	reference count reaches 0.  Frees the data structure
+ *	representing the namespace.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+NamespaceFree(nsPtr)
+    register Namespace *nsPtr;	/* Points to the namespace to free. */
+{
+    /*
+     * Most of the namespace's contents are freed when the namespace is
+     * deleted by Tcl_DeleteNamespace. All that remains is to free its names
+     * (for error messages), and the structure itself.
+     */
+
+    ckfree(nsPtr->name);
+    ckfree(nsPtr->fullName);
+
+    ckfree((char *) nsPtr);
+}
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_Export --
+ *
+ *	Makes all the commands matching a pattern available to later be
+ *	imported from the namespace specified by contextNsPtr (or the
+ *	current namespace if contextNsPtr is NULL). The specified pattern is
+ *	appended onto the namespace's export pattern list, which is
+ *	optionally cleared beforehand.
+ *
+ * Results:
+ *	Returns TCL_OK if successful, or TCL_ERROR (along with an error
+ *	message in the interpreter's result) if something goes wrong.
+ *
+ * Side effects:
+ *	Appends the export pattern onto the namespace's export list.
+ *	Optionally reset the namespace's export pattern list.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_Export(interp, namespacePtr, pattern, resetListFirst)
+    Tcl_Interp *interp;		 /* Current interpreter. */
+    Tcl_Namespace *namespacePtr; /* Points to the namespace from which 
+				  * commands are to be exported. NULL for
+                                  * the current namespace. */
+    char *pattern;               /* String pattern indicating which commands
+                                  * to export. This pattern may not include
+				  * any namespace qualifiers; only commands
+				  * in the specified namespace may be
+				  * exported. */
+    int resetListFirst;		 /* If nonzero, resets the namespace's
+				  * export list before appending 
+				  * be overwritten by imported commands.
+				  * If 0, return an error if an imported
+				  * cmd conflicts with an existing one. */
+{
+#define INIT_EXPORT_PATTERNS 5    
+    Namespace *nsPtr, *exportNsPtr, *dummyPtr;
+    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+    char *simplePattern, *patternCpy;
+    int neededElems, len, i;
+
+    /*
+     * If the specified namespace is NULL, use the current namespace.
+     */
+
+    if (namespacePtr == NULL) {
+        nsPtr = (Namespace *) currNsPtr;
+    } else {
+        nsPtr = (Namespace *) namespacePtr;
+    }
+
+    /*
+     * If resetListFirst is true (nonzero), clear the namespace's export
+     * pattern list.
+     */
+
+    if (resetListFirst) {
+	if (nsPtr->exportArrayPtr != NULL) {
+	    for (i = 0;  i < nsPtr->numExportPatterns;  i++) {
+		ckfree(nsPtr->exportArrayPtr[i]);
+	    }
+	    ckfree((char *) nsPtr->exportArrayPtr);
+	    nsPtr->exportArrayPtr = NULL;
+	    nsPtr->numExportPatterns = 0;
+	    nsPtr->maxExportPatterns = 0;
+	}
+    }
+
+    /*
+     * Check that the pattern doesn't have namespace qualifiers.
+     */
+
+    TclGetNamespaceForQualName(interp, pattern, nsPtr,
+       /*flags*/ 0, &exportNsPtr, &dummyPtr, &dummyPtr, &simplePattern);
+
+    if ((exportNsPtr != nsPtr) || (strcmp(pattern, simplePattern) != 0)) {
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+	        "invalid export pattern \"", pattern,
+		"\": pattern can't specify a namespace",
+		(char *) NULL);
+	return TCL_ERROR;
+    }
+
+    /*
+     * Make sure there is room in the namespace's pattern array for the
+     * new pattern.
+     */
+
+    neededElems = nsPtr->numExportPatterns + 1;
+    if (nsPtr->exportArrayPtr == NULL) {
+	nsPtr->exportArrayPtr = (char **)
+	        ckalloc((unsigned) (INIT_EXPORT_PATTERNS * sizeof(char *)));
+	nsPtr->numExportPatterns = 0;
+	nsPtr->maxExportPatterns = INIT_EXPORT_PATTERNS;
+    } else if (neededElems > nsPtr->maxExportPatterns) {
+	int numNewElems = 2 * nsPtr->maxExportPatterns;
+	size_t currBytes = nsPtr->numExportPatterns * sizeof(char *);
+	size_t newBytes  = numNewElems * sizeof(char *);
+	char **newPtr = (char **) ckalloc((unsigned) newBytes);
+
+	memcpy((VOID *) newPtr, (VOID *) nsPtr->exportArrayPtr,
+	        currBytes);
+	ckfree((char *) nsPtr->exportArrayPtr);
+	nsPtr->exportArrayPtr = (char **) newPtr;
+	nsPtr->maxExportPatterns = numNewElems;
+    }
+
+    /*
+     * Add the pattern to the namespace's array of export patterns.
+     */
+
+    len = strlen(pattern);
+    patternCpy = (char *) ckalloc((unsigned) (len + 1));
+    strcpy(patternCpy, pattern);
+    
+    nsPtr->exportArrayPtr[nsPtr->numExportPatterns] = patternCpy;
+    nsPtr->numExportPatterns++;
+    return TCL_OK;
+#undef INIT_EXPORT_PATTERNS
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AppendExportList --
+ *
+ *	Appends onto the argument object the list of export patterns for the
+ *	specified namespace.
+ *
+ * Results:
+ *	The return value is normally TCL_OK; in this case the object
+ *	referenced by objPtr has each export pattern appended to it. If an
+ *	error occurs, TCL_ERROR is returned and the interpreter's result
+ *	holds an error message.
+ *
+ * Side effects:
+ *	If necessary, the object referenced by objPtr is converted into
+ *	a list object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_AppendExportList(interp, namespacePtr, objPtr)
+    Tcl_Interp *interp;		 /* Interpreter used for error reporting. */
+    Tcl_Namespace *namespacePtr; /* Points to the namespace whose export
+				  * pattern list is appended onto objPtr.
+				  * NULL for the current namespace. */
+    Tcl_Obj *objPtr;		 /* Points to the Tcl object onto which the
+				  * export pattern list is appended. */
+{
+    Namespace *nsPtr;
+    int i, result;
+
+    /*
+     * If the specified namespace is NULL, use the current namespace.
+     */
+
+    if (namespacePtr == NULL) {
+        nsPtr = (Namespace *) (Namespace *) Tcl_GetCurrentNamespace(interp);
+    } else {
+        nsPtr = (Namespace *) namespacePtr;
+    }
+
+    /*
+     * Append the export pattern list onto objPtr.
+     */
+
+    for (i = 0;  i < nsPtr->numExportPatterns;  i++) {
+	result = Tcl_ListObjAppendElement(interp, objPtr,
+		Tcl_NewStringObj(nsPtr->exportArrayPtr[i], -1));
+	if (result != TCL_OK) {
+	    return result;
+	}
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_Import --
+ *
+ *	Imports all of the commands matching a pattern into the namespace
+ *	specified by contextNsPtr (or the current namespace if contextNsPtr
+ *	is NULL). This is done by creating a new command (the "imported
+ *	command") that points to the real command in its original namespace.
+ *
+ *      If matching commands are on the autoload path but haven't been
+ *	loaded yet, this command forces them to be loaded, then creates
+ *	the links to them.
+ *
+ * Results:
+ *	Returns TCL_OK if successful, or TCL_ERROR (along with an error
+ *	message in the interpreter's result) if something goes wrong.
+ *
+ * Side effects:
+ *	Creates new commands in the importing namespace. These indirect
+ *	calls back to the real command and are deleted if the real commands
+ *	are deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_Import(interp, namespacePtr, pattern, allowOverwrite)
+    Tcl_Interp *interp;		 /* Current interpreter. */
+    Tcl_Namespace *namespacePtr; /* Points to the namespace into which the
+				  * commands are to be imported. NULL for
+                                  * the current namespace. */
+    char *pattern;               /* String pattern indicating which commands
+                                  * to import. This pattern should be
+				  * qualified by the name of the namespace
+				  * from which to import the command(s). */
+    int allowOverwrite;		 /* If nonzero, allow existing commands to
+				  * be overwritten by imported commands.
+				  * If 0, return an error if an imported
+				  * cmd conflicts with an existing one. */
+{
+    Interp *iPtr = (Interp *) interp;
+    Namespace *nsPtr, *importNsPtr, *dummyPtr;
+    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+    char *simplePattern, *cmdName;
+    register Tcl_HashEntry *hPtr;
+    Tcl_HashSearch search;
+    Command *cmdPtr;
+    ImportRef *refPtr;
+    Tcl_Command autoCmd, importedCmd;
+    ImportedCmdData *dataPtr;
+    int wasExported, i, result;
+
+    /*
+     * If the specified namespace is NULL, use the current namespace.
+     */
+
+    if (namespacePtr == NULL) {
+        nsPtr = (Namespace *) currNsPtr;
+    } else {
+        nsPtr = (Namespace *) namespacePtr;
+    }
+ 
+    /*
+     * First, invoke the "auto_import" command with the pattern
+     * being imported.  This command is part of the Tcl library.
+     * It looks for imported commands in autoloaded libraries and
+     * loads them in.  That way, they will be found when we try
+     * to create links below.
+     */
+    
+    autoCmd = Tcl_FindCommand(interp, "auto_import",
+ 	    (Tcl_Namespace *) NULL, /*flags*/ TCL_GLOBAL_ONLY);
+ 
+    if (autoCmd != NULL) {
+	Tcl_Obj *objv[2];
+ 
+	objv[0] = Tcl_NewStringObj("auto_import", -1);
+	Tcl_IncrRefCount(objv[0]);
+	objv[1] = Tcl_NewStringObj(pattern, -1);
+	Tcl_IncrRefCount(objv[1]);
+ 
+	cmdPtr = (Command *) autoCmd;
+	result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp,
+		2, objv);
+ 
+	Tcl_DecrRefCount(objv[0]);
+	Tcl_DecrRefCount(objv[1]);
+ 
+	if (result != TCL_OK) {
+	    return TCL_ERROR;
+	}
+	Tcl_ResetResult(interp);
+    }
+
+    /*
+     * From the pattern, find the namespace from which we are importing
+     * and get the simple pattern (no namespace qualifiers or ::'s) at
+     * the end.
+     */
+
+    if (strlen(pattern) == 0) {
+	Tcl_SetStringObj(Tcl_GetObjResult(interp),
+	        "empty import pattern", -1);
+        return TCL_ERROR;
+    }
+    TclGetNamespaceForQualName(interp, pattern, nsPtr,
+       /*flags*/ 0, &importNsPtr, &dummyPtr, &dummyPtr, &simplePattern);
+
+    if (importNsPtr == NULL) {
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		"unknown namespace in import pattern \"",
+		pattern, "\"", (char *) NULL);
+        return TCL_ERROR;
+    }
+    if (importNsPtr == nsPtr) {
+	if (pattern == simplePattern) {
+	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		    "no namespace specified in import pattern \"", pattern,
+		    "\"", (char *) NULL);
+	} else {
+	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		    "import pattern \"", pattern,
+		    "\" tries to import from namespace \"",
+		    importNsPtr->name, "\" into itself", (char *) NULL);
+	}
+        return TCL_ERROR;
+    }
+
+    /*
+     * Scan through the command table in the source namespace and look for
+     * exported commands that match the string pattern. Create an "imported
+     * command" in the current namespace for each imported command; these
+     * commands redirect their invocations to the "real" command.
+     */
+
+    for (hPtr = Tcl_FirstHashEntry(&importNsPtr->cmdTable, &search);
+	    (hPtr != NULL);
+	    hPtr = Tcl_NextHashEntry(&search)) {
+        cmdName = Tcl_GetHashKey(&importNsPtr->cmdTable, hPtr);
+        if (Tcl_StringMatch(cmdName, simplePattern)) {
+	    /*
+	     * The command cmdName in the source namespace matches the
+	     * pattern. Check whether it was exported. If it wasn't,
+	     * we ignore it.
+	     */
+
+	    wasExported = 0;
+	    for (i = 0;  i < importNsPtr->numExportPatterns;  i++) {
+		if (Tcl_StringMatch(cmdName,
+			importNsPtr->exportArrayPtr[i])) {
+		    wasExported = 1;
+		    break;
+		}
+	    }
+	    if (!wasExported) {
+		continue;
+            }
+
+	    /*
+	     * Unless there is a name clash, create an imported command
+	     * in the current namespace that refers to cmdPtr.
+	     */
+	    
+            if ((Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName) == NULL)
+		    || allowOverwrite) {
+		/*
+		 * Create the imported command and its client data.
+		 * To create the new command in the current namespace, 
+		 * generate a fully qualified name for it.
+		 */
+
+		Tcl_DString ds;
+
+		Tcl_DStringInit(&ds);
+		Tcl_DStringAppend(&ds, nsPtr->fullName, -1);
+		if (nsPtr != iPtr->globalNsPtr) {
+		    Tcl_DStringAppend(&ds, "::", 2);
+		}
+		Tcl_DStringAppend(&ds, cmdName, -1);
+		
+		cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
+		dataPtr = (ImportedCmdData *)
+		        ckalloc(sizeof(ImportedCmdData));
+                importedCmd = Tcl_CreateObjCommand(interp, 
+                        Tcl_DStringValue(&ds), InvokeImportedCmd,
+                        (ClientData) dataPtr, DeleteImportedCmd);
+		dataPtr->realCmdPtr = cmdPtr;
+		dataPtr->selfPtr = (Command *) importedCmd;
+
+		/*
+		 * Create an ImportRef structure describing this new import
+		 * command and add it to the import ref list in the "real"
+		 * command.
+		 */
+
+                refPtr = (ImportRef *) ckalloc(sizeof(ImportRef));
+                refPtr->importedCmdPtr = (Command *) importedCmd;
+                refPtr->nextPtr = cmdPtr->importRefPtr;
+                cmdPtr->importRefPtr = refPtr;
+            } else {
+		Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		        "can't import command \"", cmdName,
+			"\": already exists", (char *) NULL);
+                return TCL_ERROR;
+            }
+        }
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ForgetImport --
+ *
+ *	Deletes previously imported commands. Given a pattern that may
+ *	include the name of an exporting namespace, this procedure first
+ *	finds all matching exported commands. It then looks in the namespace
+ *	specified by namespacePtr for any corresponding previously imported
+ *	commands, which it deletes. If namespacePtr is NULL, commands are
+ *	deleted from the current namespace.
+ *
+ * Results:
+ *	Returns TCL_OK if successful. If there is an error, returns
+ *	TCL_ERROR and puts an error message in the interpreter's result
+ *	object.
+ *
+ * Side effects:
+ *	May delete commands. 
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_ForgetImport(interp, namespacePtr, pattern)
+    Tcl_Interp *interp;		 /* Current interpreter. */
+    Tcl_Namespace *namespacePtr; /* Points to the namespace from which
+				  * previously imported commands should be
+				  * removed. NULL for current namespace. */
+    char *pattern;		 /* String pattern indicating which imported
+				  * commands to remove. This pattern should
+				  * be qualified by the name of the
+				  * namespace from which the command(s) were
+				  * imported. */
+{
+    Namespace *nsPtr, *importNsPtr, *dummyPtr, *actualCtxPtr;
+    char *simplePattern, *cmdName;
+    register Tcl_HashEntry *hPtr;
+    Tcl_HashSearch search;
+    Command *cmdPtr;
+
+    /*
+     * If the specified namespace is NULL, use the current namespace.
+     */
+
+    if (namespacePtr == NULL) {
+        nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+    } else {
+        nsPtr = (Namespace *) namespacePtr;
+    }
+
+    /*
+     * From the pattern, find the namespace from which we are importing
+     * and get the simple pattern (no namespace qualifiers or ::'s) at
+     * the end.
+     */
+
+    TclGetNamespaceForQualName(interp, pattern, nsPtr,
+       /*flags*/ 0, &importNsPtr, &dummyPtr, &actualCtxPtr, &simplePattern);
+
+    if (importNsPtr == NULL) {
+        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		"unknown namespace in namespace forget pattern \"",
+		pattern, "\"", (char *) NULL);
+        return TCL_ERROR;
+    }
+
+    /*
+     * Scan through the command table in the source namespace and look for
+     * exported commands that match the string pattern. If the current
+     * namespace has an imported command that refers to one of those real
+     * commands, delete it.
+     */
+
+    for (hPtr = Tcl_FirstHashEntry(&importNsPtr->cmdTable, &search);
+            (hPtr != NULL);
+            hPtr = Tcl_NextHashEntry(&search)) {
+        cmdName = Tcl_GetHashKey(&importNsPtr->cmdTable, hPtr);
+        if (Tcl_StringMatch(cmdName, simplePattern)) {
+            hPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName);
+            if (hPtr != NULL) {	/* cmd of same name in current namespace */
+                cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
+                if (cmdPtr->deleteProc == DeleteImportedCmd) { 
+                    Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
+                }
+            }
+        }
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetOriginalCommand --
+ *
+ *	An imported command is created in an namespace when it imports a
+ *	"real" command from another namespace. If the specified command is a
+ *	imported command, this procedure returns the original command it
+ *	refers to.  
+ *
+ * Results:
+ *	If the command was imported into a sequence of namespaces a, b,...,n
+ *	where each successive namespace just imports the command from the
+ *	previous namespace, this procedure returns the Tcl_Command token in
+ *	the first namespace, a. Otherwise, if the specified command is not
+ *	an imported command, the procedure returns NULL.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Command
+TclGetOriginalCommand(command)
+    Tcl_Command command;	/* The command for which the original
+				 * command should be returned. */
+{
+    register Command *cmdPtr = (Command *) command;
+    ImportedCmdData *dataPtr;
+
+    if (cmdPtr->deleteProc != DeleteImportedCmd) {
+	return (Tcl_Command) NULL;
+    }
+    
+    while (cmdPtr->deleteProc == DeleteImportedCmd) {
+	dataPtr = (ImportedCmdData *) cmdPtr->objClientData;
+	cmdPtr = dataPtr->realCmdPtr;
+    }
+    return (Tcl_Command) cmdPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InvokeImportedCmd --
+ *
+ *	Invoked by Tcl whenever the user calls an imported command that
+ *	was created by Tcl_Import. Finds the "real" command (in another
+ *	namespace), and passes control to it.
+ *
+ * Results:
+ *	Returns TCL_OK if successful, and  TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ *	Returns a result in the interpreter's result object. If anything
+ *	goes wrong, the result object is set to an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InvokeImportedCmd(clientData, interp, objc, objv)
+    ClientData clientData;	/* Points to the imported command's
+				 * ImportedCmdData structure. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* The argument objects. */
+{
+    register ImportedCmdData *dataPtr = (ImportedCmdData *) clientData;
+    register Command *realCmdPtr = dataPtr->realCmdPtr;
+
+    return (*realCmdPtr->objProc)(realCmdPtr->objClientData, interp,
+            objc, objv);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteImportedCmd --
+ *
+ *	Invoked by Tcl whenever an imported command is deleted. The "real"
+ *	command keeps a list of all the imported commands that refer to it,
+ *	so those imported commands can be deleted when the real command is
+ *	deleted. This procedure removes the imported command reference from
+ *	the real command's list, and frees up the memory associated with
+ *	the imported command.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Removes the imported command from the real command's import list.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DeleteImportedCmd(clientData)
+    ClientData clientData;	/* Points to the imported command's
+				 * ImportedCmdData structure. */
+{
+    ImportedCmdData *dataPtr = (ImportedCmdData *) clientData;
+    Command *realCmdPtr = dataPtr->realCmdPtr;
+    Command *selfPtr = dataPtr->selfPtr;
+    register ImportRef *refPtr, *prevPtr;
+
+    prevPtr = NULL;
+    for (refPtr = realCmdPtr->importRefPtr;  refPtr != NULL;
+            refPtr = refPtr->nextPtr) {
+	if (refPtr->importedCmdPtr == selfPtr) {
+	    /*
+	     * Remove *refPtr from real command's list of imported commands
+	     * that refer to it.
+	     */
+	    
+	    if (prevPtr == NULL) { /* refPtr is first in list */
+		realCmdPtr->importRefPtr = refPtr->nextPtr;
+	    } else {
+		prevPtr->nextPtr = refPtr->nextPtr;
+	    }
+	    ckfree((char *) refPtr);
+	    ckfree((char *) dataPtr);
+	    return;
+	}
+	prevPtr = refPtr;
+    }
+	
+    panic("DeleteImportedCmd: did not find cmd in real cmd's list of import references");
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetNamespaceForQualName --
+ *
+ *	Given a qualified name specifying a command, variable, or namespace,
+ *	and a namespace in which to resolve the name, this procedure returns
+ *	a pointer to the namespace that contains the item. A qualified name
+ *	consists of the "simple" name of an item qualified by the names of
+ *	an arbitrary number of containing namespace separated by "::"s. If
+ *	the qualified name starts with "::", it is interpreted absolutely
+ *	from the global namespace. Otherwise, it is interpreted relative to
+ *	the namespace specified by cxtNsPtr if it is non-NULL. If cxtNsPtr
+ *	is NULL, the name is interpreted relative to the current namespace.
+ *
+ *	A relative name like "foo::bar::x" can be found starting in either
+ *	the current namespace or in the global namespace. So each search
+ *	usually follows two tracks, and two possible namespaces are
+ *	returned. If the procedure sets either *nsPtrPtr or *altNsPtrPtr to
+ *	NULL, then that path failed.
+ *
+ *	If "flags" contains TCL_GLOBAL_ONLY, the relative qualified name is
+ *	sought only in the global :: namespace. The alternate search
+ *	(also) starting from the global namespace is ignored and
+ *	*altNsPtrPtr is set NULL. 
+ *
+ *	If "flags" contains TCL_NAMESPACE_ONLY, the relative qualified
+ *	name is sought only in the namespace specified by cxtNsPtr. The
+ *	alternate search starting from the global namespace is ignored and
+ *	*altNsPtrPtr is set NULL. If both TCL_GLOBAL_ONLY and
+ *	TCL_NAMESPACE_ONLY are specified, TCL_GLOBAL_ONLY is ignored and
+ *	the search starts from the namespace specified by cxtNsPtr.
+ *
+ *	If "flags" contains CREATE_NS_IF_UNKNOWN, all namespace
+ *	components of the qualified name that cannot be found are
+ *	automatically created within their specified parent. This makes sure
+ *	that functions like Tcl_CreateCommand always succeed. There is no
+ *	alternate search path, so *altNsPtrPtr is set NULL.
+ *
+ *	If "flags" contains FIND_ONLY_NS, the qualified name is treated as a
+ *	reference to a namespace, and the entire qualified name is
+ *	followed. If the name is relative, the namespace is looked up only
+ *	in the current namespace. A pointer to the namespace is stored in
+ *	*nsPtrPtr and NULL is stored in *simpleNamePtr. Otherwise, if
+ *	FIND_ONLY_NS is not specified, only the leading components are
+ *	treated as namespace names, and a pointer to the simple name of the
+ *	final component is stored in *simpleNamePtr.
+ *
+ * Results:
+ *     It sets *nsPtrPtr and *altNsPtrPtr to point to the two possible
+ *     namespaces which represent the last (containing) namespace in the
+ *     qualified name. If the procedure sets either *nsPtrPtr or *altNsPtrPtr
+ *     to NULL, then the search along that path failed.  The procedure also
+ *     stores a pointer to the simple name of the final component in
+ *     *simpleNamePtr. If the qualified name is "::" or was treated as a
+ *     namespace reference (FIND_ONLY_NS), the procedure stores a pointer
+ *     to the namespace in *nsPtrPtr, NULL in *altNsPtrPtr, and sets
+ *	*simpleNamePtr to point to an empty string.
+ *
+ *	*actualCxtPtrPtr is set to the actual context namespace. It is
+ *	set to the input context namespace pointer in cxtNsPtr. If cxtNsPtr
+ *	is NULL, it is set to the current namespace context.
+ *
+ *	For backwards compatibility with the TclPro byte code loader,
+ *	this function always returns TCL_OK.
+ *
+ * Side effects:
+ *     If "flags" contains CREATE_NS_IF_UNKNOWN, new namespaces may be
+ *     created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclGetNamespaceForQualName(interp, qualName, cxtNsPtr, flags,
+	nsPtrPtr, altNsPtrPtr, actualCxtPtrPtr, simpleNamePtr)
+    Tcl_Interp *interp;		 /* Interpreter in which to find the
+				  * namespace containing qualName. */
+    register char *qualName;	 /* A namespace-qualified name of an
+				  * command, variable, or namespace. */
+    Namespace *cxtNsPtr;	 /* The namespace in which to start the
+				  * search for qualName's namespace. If NULL
+				  * start from the current namespace.
+				  * Ignored if TCL_GLOBAL_ONLY or
+				  * TCL_NAMESPACE_ONLY are set. */
+    int flags;			 /* Flags controlling the search: an OR'd
+				  * combination of TCL_GLOBAL_ONLY,
+				  * TCL_NAMESPACE_ONLY,
+				  * CREATE_NS_IF_UNKNOWN, and
+				  * FIND_ONLY_NS. */
+    Namespace **nsPtrPtr;	 /* Address where procedure stores a pointer
+				  * to containing namespace if qualName is
+				  * found starting from *cxtNsPtr or, if
+				  * TCL_GLOBAL_ONLY is set, if qualName is
+				  * found in the global :: namespace. NULL
+				  * is stored otherwise. */
+    Namespace **altNsPtrPtr;	 /* Address where procedure stores a pointer
+				  * to containing namespace if qualName is
+				  * found starting from the global ::
+				  * namespace. NULL is stored if qualName
+				  * isn't found starting from :: or if the
+				  * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
+				  * CREATE_NS_IF_UNKNOWN, FIND_ONLY_NS flag
+				  * is set. */
+    Namespace **actualCxtPtrPtr; /* Address where procedure stores a pointer
+				  * to the actual namespace from which the
+				  * search started. This is either cxtNsPtr,
+				  * the :: namespace if TCL_GLOBAL_ONLY was
+				  * specified, or the current namespace if
+				  * cxtNsPtr was NULL. */
+    char **simpleNamePtr;	 /* Address where procedure stores the
+				  * simple name at end of the qualName, or
+				  * NULL if qualName is "::" or the flag
+				  * FIND_ONLY_NS was specified. */
+{
+    Interp *iPtr = (Interp *) interp;
+    Namespace *nsPtr = cxtNsPtr;
+    Namespace *altNsPtr;
+    Namespace *globalNsPtr = iPtr->globalNsPtr;
+    register char *start, *end;
+    char *nsName;
+    Tcl_HashEntry *entryPtr;
+    Tcl_DString buffer;
+    int len;
+
+    /*
+     * Determine the context namespace nsPtr in which to start the primary
+     * search. If TCL_NAMESPACE_ONLY or FIND_ONLY_NS was specified, search
+     * from the current namespace. If the qualName name starts with a "::"
+     * or TCL_GLOBAL_ONLY was specified, search from the global
+     * namespace. Otherwise, use the given namespace given in cxtNsPtr, or
+     * if that is NULL, use the current namespace context. Note that we
+     * always treat two or more adjacent ":"s as a namespace separator.
+     */
+
+    if (flags & (TCL_NAMESPACE_ONLY | FIND_ONLY_NS)) {
+	nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+    } else if (flags & TCL_GLOBAL_ONLY) {
+	nsPtr = globalNsPtr;
+    } else if (nsPtr == NULL) {
+	if (iPtr->varFramePtr != NULL) {
+	    nsPtr = iPtr->varFramePtr->nsPtr;
+	} else {
+	    nsPtr = iPtr->globalNsPtr;
+	}
+    }
+
+    start = qualName;		/* pts to start of qualifying namespace */
+    if ((*qualName == ':') && (*(qualName+1) == ':')) {
+	start = qualName+2;	/* skip over the initial :: */
+	while (*start == ':') {
+            start++;		/* skip over a subsequent : */
+	}
+        nsPtr = globalNsPtr;
+        if (*start == '\0') {	/* qualName is just two or more ":"s */
+            *nsPtrPtr        = globalNsPtr;
+            *altNsPtrPtr     = NULL;
+	    *actualCxtPtrPtr = globalNsPtr;
+            *simpleNamePtr   = start; /* points to empty string */
+            return TCL_OK;
+        }
+    }
+    *actualCxtPtrPtr = nsPtr;
+
+    /*
+     * Start an alternate search path starting with the global namespace.
+     * However, if the starting context is the global namespace, or if the
+     * flag is set to search only the namespace *cxtNsPtr, ignore the
+     * alternate search path.
+     */
+
+    altNsPtr = globalNsPtr;
+    if ((nsPtr == globalNsPtr)
+	    || (flags & (TCL_NAMESPACE_ONLY | FIND_ONLY_NS))) {
+        altNsPtr = NULL;
+    }
+
+    /*
+     * Loop to resolve each namespace qualifier in qualName.
+     */
+
+    Tcl_DStringInit(&buffer);
+    end = start;
+    while (*start != '\0') {
+        /*
+         * Find the next namespace qualifier (i.e., a name ending in "::")
+	 * or the end of the qualified name  (i.e., a name ending in "\0").
+	 * Set len to the number of characters, starting from start,
+	 * in the name; set end to point after the "::"s or at the "\0".
+         */
+
+	len = 0;
+        for (end = start;  *end != '\0';  end++) {
+	    if ((*end == ':') && (*(end+1) == ':')) {
+		end += 2;	/* skip over the initial :: */
+		while (*end == ':') {
+		    end++;	/* skip over the subsequent : */
+		}
+		break;		/* exit for loop; end is after ::'s */
+	    }
+            len++;
+	}
+
+	if ((*end == '\0')
+	        && !((end-start >= 2) && (*(end-1) == ':') && (*(end-2) == ':'))) {
+	    /*
+	     * qualName ended with a simple name at start. If FIND_ONLY_NS
+	     * was specified, look this up as a namespace. Otherwise,
+	     * start is the name of a cmd or var and we are done.
+	     */
+	    
+	    if (flags & FIND_ONLY_NS) {
+		nsName = start;
+	    } else {
+		*nsPtrPtr      = nsPtr;
+		*altNsPtrPtr   = altNsPtr;
+		*simpleNamePtr = start;
+		Tcl_DStringFree(&buffer);
+               return TCL_OK;
+	    }
+	} else {
+	    /*
+	     * start points to the beginning of a namespace qualifier ending
+	     * in "::". end points to the start of a name in that namespace
+	     * that might be empty. Copy the namespace qualifier to a
+	     * buffer so it can be null terminated. We can't modify the
+	     * incoming qualName since it may be a string constant.
+	     */
+
+	    Tcl_DStringSetLength(&buffer, 0);
+            Tcl_DStringAppend(&buffer, start, len);
+            nsName = Tcl_DStringValue(&buffer);
+        }
+
+        /*
+	 * Look up the namespace qualifier nsName in the current namespace
+         * context. If it isn't found but CREATE_NS_IF_UNKNOWN is set,
+         * create that qualifying namespace. This is needed for procedures
+         * like Tcl_CreateCommand that cannot fail.
+	 */
+
+        if (nsPtr != NULL) {
+            entryPtr = Tcl_FindHashEntry(&nsPtr->childTable, nsName);
+            if (entryPtr != NULL) {
+                nsPtr = (Namespace *) Tcl_GetHashValue(entryPtr);
+            } else if (flags & CREATE_NS_IF_UNKNOWN) {
+		Tcl_CallFrame frame;
+		
+               (void) Tcl_PushCallFrame(interp, &frame,
+		        (Tcl_Namespace *) nsPtr, /*isProcCallFrame*/ 0);
+
+                nsPtr = (Namespace *) Tcl_CreateNamespace(interp, nsName,
+		        (ClientData) NULL, (Tcl_NamespaceDeleteProc *) NULL);
+                Tcl_PopCallFrame(interp);
+
+                if (nsPtr == NULL) {
+                   panic("Could not create namespace '%s'", nsName);
+                }
+            } else {		/* namespace not found and wasn't created */
+                nsPtr = NULL;
+            }
+        }
+
+        /*
+         * Look up the namespace qualifier in the alternate search path too.
+         */
+
+        if (altNsPtr != NULL) {
+            entryPtr = Tcl_FindHashEntry(&altNsPtr->childTable, nsName);
+            if (entryPtr != NULL) {
+                altNsPtr = (Namespace *) Tcl_GetHashValue(entryPtr);
+            } else {
+                altNsPtr = NULL;
+            }
+        }
+
+        /*
+         * If both search paths have failed, return NULL results.
+         */
+
+        if ((nsPtr == NULL) && (altNsPtr == NULL)) {
+            *nsPtrPtr      = NULL;
+            *altNsPtrPtr   = NULL;
+            *simpleNamePtr = NULL;
+            Tcl_DStringFree(&buffer);
+            return TCL_OK;
+        }
+
+	start = end;
+    }
+
+    /*
+     * We ignore trailing "::"s in a namespace name, but in a command or
+     * variable name, trailing "::"s refer to the cmd or var named {}.
+     */
+
+    if ((flags & FIND_ONLY_NS)
+	    || ((end > start ) && (*(end-1) != ':'))) {
+	*simpleNamePtr = NULL; /* found namespace name */
+    } else {
+	*simpleNamePtr = end;  /* found cmd/var: points to empty string */
+    }
+
+    /*
+     * As a special case, if we are looking for a namespace and qualName
+     * is "" and the current active namespace (nsPtr) is not the global
+     * namespace, return NULL (no namespace was found). This is because
+     * namespaces can not have empty names except for the global namespace.
+     */
+
+    if ((flags & FIND_ONLY_NS) && (*qualName == '\0')
+	    && (nsPtr != globalNsPtr)) {
+	nsPtr = NULL;
+    }
+
+    *nsPtrPtr    = nsPtr;
+    *altNsPtrPtr = altNsPtr;
+    Tcl_DStringFree(&buffer);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_FindNamespace --
+ *
+ *	Searches for a namespace.
+ *
+ * Results:
+ *	Returns a pointer to the namespace if it is found. Otherwise,
+ *	returns NULL and leaves an error message in the interpreter's
+ *	result object if "flags" contains TCL_LEAVE_ERR_MSG.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Namespace *
+Tcl_FindNamespace(interp, name, contextNsPtr, flags)
+    Tcl_Interp *interp;		 /* The interpreter in which to find the
+				  * namespace. */
+    char *name;			 /* Namespace name. If it starts with "::",
+				  * will be looked up in global namespace.
+				  * Else, looked up first in contextNsPtr
+				  * (current namespace if contextNsPtr is
+				  * NULL), then in global namespace. */
+    Tcl_Namespace *contextNsPtr; /* Ignored if TCL_GLOBAL_ONLY flag is set
+				  * or if the name starts with "::".
+				  * Otherwise, points to namespace in which
+				  * to resolve name; if NULL, look up name
+				  * in the current namespace. */
+    register int flags;		 /* Flags controlling namespace lookup: an
+				  * OR'd combination of TCL_GLOBAL_ONLY and
+				  * TCL_LEAVE_ERR_MSG flags. */
+{
+    Namespace *nsPtr, *dummy1Ptr, *dummy2Ptr;
+    char *dummy;
+
+    /*
+     * Find the namespace(s) that contain the specified namespace name.
+     * Add the FIND_ONLY_NS flag to resolve the name all the way down
+     * to its last component, a namespace.
+     */
+
+    TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr,
+       (flags | FIND_ONLY_NS), &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);
+
+    if (nsPtr != NULL) {
+       return (Tcl_Namespace *) nsPtr;
+    } else if (flags & TCL_LEAVE_ERR_MSG) {
+	Tcl_ResetResult(interp);
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                "unknown namespace \"", name, "\"", (char *) NULL);
+    }
+    return NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_FindCommand --
+ *
+ *	Searches for a command.
+ *
+ * Results:
+ *	Returns a token for the command if it is found. Otherwise, if it
+ *	can't be found or there is an error, returns NULL and leaves an
+ *	error message in the interpreter's result object if "flags"
+ *	contains TCL_LEAVE_ERR_MSG.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Command
+Tcl_FindCommand(interp, name, contextNsPtr, flags)
+    Tcl_Interp *interp;         /* The interpreter in which to find the
+				  * command and to report errors. */
+    char *name;		         /* Command's name. If it starts with "::",
+				  * will be looked up in global namespace.
+				  * Else, looked up first in contextNsPtr
+				  * (current namespace if contextNsPtr is
+				  * NULL), then in global namespace. */
+    Tcl_Namespace *contextNsPtr; /* Ignored if TCL_GLOBAL_ONLY flag set.
+				  * Otherwise, points to namespace in which
+				  * to resolve name. If NULL, look up name
+				  * in the current namespace. */
+    int flags;                   /* An OR'd combination of flags:
+				  * TCL_GLOBAL_ONLY (look up name only in
+				  * global namespace), TCL_NAMESPACE_ONLY
+				  * (look up only in contextNsPtr, or the
+				  * current namespace if contextNsPtr is
+				  * NULL), and TCL_LEAVE_ERR_MSG. If both
+				  * TCL_GLOBAL_ONLY and TCL_NAMESPACE_ONLY
+				  * are given, TCL_GLOBAL_ONLY is
+				  * ignored. */
+{
+    Interp *iPtr = (Interp*)interp;
+
+    ResolverScheme *resPtr;
+    Namespace *nsPtr[2], *cxtNsPtr;
+    char *simpleName;
+    register Tcl_HashEntry *entryPtr;
+    register Command *cmdPtr;
+    register int search;
+    int result;
+    Tcl_Command cmd;
+
+    /*
+     * If this namespace has a command resolver, then give it first
+     * crack at the command resolution.  If the interpreter has any
+     * command resolvers, consult them next.  The command resolver
+     * procedures may return a Tcl_Command value, they may signal
+     * to continue onward, or they may signal an error.
+     */
+    if ((flags & TCL_GLOBAL_ONLY) != 0) {
+        cxtNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
+    }
+    else if (contextNsPtr != NULL) {
+        cxtNsPtr = (Namespace *) contextNsPtr;
+    }
+    else {
+        cxtNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+    }
+
+    if (cxtNsPtr->cmdResProc != NULL || iPtr->resolverPtr != NULL) {
+        resPtr = iPtr->resolverPtr;
+
+        if (cxtNsPtr->cmdResProc) {
+            result = (*cxtNsPtr->cmdResProc)(interp, name,
+                (Tcl_Namespace *) cxtNsPtr, flags, &cmd);
+        } else {
+            result = TCL_CONTINUE;
+        }
+
+        while (result == TCL_CONTINUE && resPtr) {
+            if (resPtr->cmdResProc) {
+                result = (*resPtr->cmdResProc)(interp, name,
+                    (Tcl_Namespace *) cxtNsPtr, flags, &cmd);
+            }
+            resPtr = resPtr->nextPtr;
+        }
+
+        if (result == TCL_OK) {
+            return cmd;
+        }
+        else if (result != TCL_CONTINUE) {
+            return (Tcl_Command) NULL;
+        }
+    }
+
+    /*
+     * Find the namespace(s) that contain the command.
+     */
+
+    TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr,
+       flags, &nsPtr[0], &nsPtr[1], &cxtNsPtr, &simpleName);
+
+    /*
+     * Look for the command in the command table of its namespace.
+     * Be sure to check both possible search paths: from the specified
+     * namespace context and from the global namespace.
+     */
+
+    cmdPtr = NULL;
+    for (search = 0;  (search < 2) && (cmdPtr == NULL);  search++) {
+        if ((nsPtr[search] != NULL) && (simpleName != NULL)) {
+	    entryPtr = Tcl_FindHashEntry(&nsPtr[search]->cmdTable,
+		    simpleName);
+            if (entryPtr != NULL) {
+                cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
+            }
+        }
+    }
+    if (cmdPtr != NULL) {
+        return (Tcl_Command) cmdPtr;
+    } else if (flags & TCL_LEAVE_ERR_MSG) {
+	Tcl_ResetResult(interp);
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                "unknown command \"", name, "\"", (char *) NULL);
+    }
+
+    return (Tcl_Command) NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_FindNamespaceVar --
+ *
+ *	Searches for a namespace variable, a variable not local to a
+ *	procedure. The variable can be either a scalar or an array, but
+ *	may not be an element of an array.
+ *
+ * Results:
+ *	Returns a token for the variable if it is found. Otherwise, if it
+ *	can't be found or there is an error, returns NULL and leaves an
+ *	error message in the interpreter's result object if "flags"
+ *	contains TCL_LEAVE_ERR_MSG.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Var
+Tcl_FindNamespaceVar(interp, name, contextNsPtr, flags)
+    Tcl_Interp *interp;		 /* The interpreter in which to find the
+				  * variable. */
+    char *name;			 /* Variable's name. If it starts with "::",
+				  * will be looked up in global namespace.
+				  * Else, looked up first in contextNsPtr
+				  * (current namespace if contextNsPtr is
+				  * NULL), then in global namespace. */
+    Tcl_Namespace *contextNsPtr; /* Ignored if TCL_GLOBAL_ONLY flag set.
+				  * Otherwise, points to namespace in which
+				  * to resolve name. If NULL, look up name
+				  * in the current namespace. */
+    int flags;			 /* An OR'd combination of flags:
+				  * TCL_GLOBAL_ONLY (look up name only in
+				  * global namespace), TCL_NAMESPACE_ONLY
+				  * (look up only in contextNsPtr, or the
+				  * current namespace if contextNsPtr is
+				  * NULL), and TCL_LEAVE_ERR_MSG. If both
+				  * TCL_GLOBAL_ONLY and TCL_NAMESPACE_ONLY
+				  * are given, TCL_GLOBAL_ONLY is
+				  * ignored. */
+{
+    Interp *iPtr = (Interp*)interp;
+    ResolverScheme *resPtr;
+    Namespace *nsPtr[2], *cxtNsPtr;
+    char *simpleName;
+    Tcl_HashEntry *entryPtr;
+    Var *varPtr;
+    register int search;
+    int result;
+    Tcl_Var var;
+
+    /*
+     * If this namespace has a variable resolver, then give it first
+     * crack at the variable resolution.  It may return a Tcl_Var
+     * value, it may signal to continue onward, or it may signal
+     * an error.
+     */
+    if ((flags & TCL_GLOBAL_ONLY) != 0) {
+        cxtNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
+    }
+    else if (contextNsPtr != NULL) {
+        cxtNsPtr = (Namespace *) contextNsPtr;
+    }
+    else {
+        cxtNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+    }
+
+    if (cxtNsPtr->varResProc != NULL || iPtr->resolverPtr != NULL) {
+        resPtr = iPtr->resolverPtr;
+
+        if (cxtNsPtr->varResProc) {
+            result = (*cxtNsPtr->varResProc)(interp, name,
+                (Tcl_Namespace *) cxtNsPtr, flags, &var);
+        } else {
+            result = TCL_CONTINUE;
+        }
+
+        while (result == TCL_CONTINUE && resPtr) {
+            if (resPtr->varResProc) {
+                result = (*resPtr->varResProc)(interp, name,
+                    (Tcl_Namespace *) cxtNsPtr, flags, &var);
+            }
+            resPtr = resPtr->nextPtr;
+        }
+
+        if (result == TCL_OK) {
+            return var;
+        }
+        else if (result != TCL_CONTINUE) {
+            return (Tcl_Var) NULL;
+        }
+    }
+
+    /*
+     * Find the namespace(s) that contain the variable.
+     */
+
+    TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr,
+       flags, &nsPtr[0], &nsPtr[1], &cxtNsPtr, &simpleName);
+
+    /*
+     * Look for the variable in the variable table of its namespace.
+     * Be sure to check both possible search paths: from the specified
+     * namespace context and from the global namespace.
+     */
+
+    varPtr = NULL;
+    for (search = 0;  (search < 2) && (varPtr == NULL);  search++) {
+        if ((nsPtr[search] != NULL) && (simpleName != NULL)) {
+            entryPtr = Tcl_FindHashEntry(&nsPtr[search]->varTable,
+		    simpleName);
+            if (entryPtr != NULL) {
+                varPtr = (Var *) Tcl_GetHashValue(entryPtr);
+            }
+        }
+    }
+    if (varPtr != NULL) {
+	return (Tcl_Var) varPtr;
+    } else if (flags & TCL_LEAVE_ERR_MSG) {
+	Tcl_ResetResult(interp);
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                "unknown variable \"", name, "\"", (char *) NULL);
+    }
+    return (Tcl_Var) NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclResetShadowedCmdRefs --
+ *
+ *	Called when a command is added to a namespace to check for existing
+ *	command references that the new command may invalidate. Consider the
+ *	following cases that could happen when you add a command "foo" to a
+ *	namespace "b":
+ *	   1. It could shadow a command named "foo" at the global scope.
+ *	      If it does, all command references in the namespace "b" are
+ *	      suspect.
+ *	   2. Suppose the namespace "b" resides in a namespace "a".
+ *	      Then to "a" the new command "b::foo" could shadow another
+ *	      command "b::foo" in the global namespace. If so, then all
+ *	      command references in "a" are suspect.
+ *	The same checks are applied to all parent namespaces, until we
+ *	reach the global :: namespace.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	If the new command shadows an existing command, the cmdRefEpoch
+ *	counter is incremented in each namespace that sees the shadow.
+ *	This invalidates all command references that were previously cached
+ *	in that namespace. The next time the commands are used, they are
+ *	resolved from scratch.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclResetShadowedCmdRefs(interp, newCmdPtr)
+    Tcl_Interp *interp;	       /* Interpreter containing the new command. */
+    Command *newCmdPtr;	       /* Points to the new command. */
+{
+    char *cmdName;
+    Tcl_HashEntry *hPtr;
+    register Namespace *nsPtr;
+    Namespace *trailNsPtr, *shadowNsPtr;
+    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
+    int found, i;
+
+    /*
+     * This procedure generates an array used to hold the trail list. This
+     * starts out with stack-allocated space but uses dynamically-allocated
+     * storage if needed.
+     */
+
+    Namespace *(trailStorage[NUM_TRAIL_ELEMS]);
+    Namespace **trailPtr = trailStorage;
+    int trailFront = -1;
+    int trailSize = NUM_TRAIL_ELEMS;
+
+    /*
+     * Start at the namespace containing the new command, and work up
+     * through the list of parents. Stop just before the global namespace,
+     * since the global namespace can't "shadow" its own entries.
+     *
+     * The namespace "trail" list we build consists of the names of each
+     * namespace that encloses the new command, in order from outermost to
+     * innermost: for example, "a" then "b". Each iteration of this loop
+     * eventually extends the trail upwards by one namespace, nsPtr. We use
+     * this trail list to see if nsPtr (e.g. "a" in 2. above) could have
+     * now-invalid cached command references. This will happen if nsPtr
+     * (e.g. "a") contains a sequence of child namespaces (e.g. "b")
+     * such that there is a identically-named sequence of child namespaces
+     * starting from :: (e.g. "::b") whose tail namespace contains a command
+     * also named cmdName.
+     */
+
+    cmdName = Tcl_GetHashKey(newCmdPtr->hPtr->tablePtr, newCmdPtr->hPtr);
+    for (nsPtr = newCmdPtr->nsPtr;
+	    (nsPtr != NULL) && (nsPtr != globalNsPtr);
+            nsPtr = nsPtr->parentPtr) {
+        /*
+	 * Find the maximal sequence of child namespaces contained in nsPtr
+	 * such that there is a identically-named sequence of child
+	 * namespaces starting from ::. shadowNsPtr will be the tail of this
+	 * sequence, or the deepest namespace under :: that might contain a
+	 * command now shadowed by cmdName. We check below if shadowNsPtr
+	 * actually contains a command cmdName.
+	 */
+
+        found = 1;
+        shadowNsPtr = globalNsPtr;
+
+        for (i = trailFront;  i >= 0;  i--) {
+            trailNsPtr = trailPtr[i];
+            hPtr = Tcl_FindHashEntry(&shadowNsPtr->childTable,
+		    trailNsPtr->name);
+            if (hPtr != NULL) {
+                shadowNsPtr = (Namespace *) Tcl_GetHashValue(hPtr);
+            } else {
+                found = 0;
+                break;
+            }
+        }
+
+        /*
+	 * If shadowNsPtr contains a command named cmdName, we invalidate
+         * all of the command refs cached in nsPtr. As a boundary case,
+	 * shadowNsPtr is initially :: and we check for case 1. above.
+	 */
+
+        if (found) {
+            hPtr = Tcl_FindHashEntry(&shadowNsPtr->cmdTable, cmdName);
+            if (hPtr != NULL) {
+                nsPtr->cmdRefEpoch++;
+            }
+        }
+
+        /*
+	 * Insert nsPtr at the front of the trail list: i.e., at the end
+	 * of the trailPtr array.
+	 */
+
+	trailFront++;
+	if (trailFront == trailSize) {
+	    size_t currBytes = trailSize * sizeof(Namespace *);
+	    int newSize = 2*trailSize;
+	    size_t newBytes = newSize * sizeof(Namespace *);
+	    Namespace **newPtr =
+		    (Namespace **) ckalloc((unsigned) newBytes);
+	    
+	    memcpy((VOID *) newPtr, (VOID *) trailPtr, currBytes);
+	    if (trailPtr != trailStorage) {
+		ckfree((char *) trailPtr);
+	    }
+	    trailPtr = newPtr;
+	    trailSize = newSize;
+	}
+	trailPtr[trailFront] = nsPtr;
+    }
+
+    /*
+     * Free any allocated storage.
+     */
+    
+    if (trailPtr != trailStorage) {
+	ckfree((char *) trailPtr);
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetNamespaceFromObj --
+ *
+ *	Returns the namespace specified by the name in a Tcl_Obj.
+ *
+ * Results:
+ *	Returns TCL_OK if the namespace was resolved successfully, and
+ *	stores a pointer to the namespace in the location specified by
+ *	nsPtrPtr. If the namespace can't be found, the procedure stores
+ *	NULL in *nsPtrPtr and returns TCL_OK. If anything else goes wrong,
+ *	this procedure returns TCL_ERROR.
+ *
+ * Side effects:
+ *	May update the internal representation for the object, caching the
+ *	namespace reference. The next time this procedure is called, the
+ *	namespace value can be found quickly.
+ *
+ *	If anything goes wrong, an error message is left in the
+ *	interpreter's result object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetNamespaceFromObj(interp, objPtr, nsPtrPtr)
+    Tcl_Interp *interp;		/* The current interpreter. */
+    Tcl_Obj *objPtr;		/* The object to be resolved as the name
+				 * of a namespace. */
+    Tcl_Namespace **nsPtrPtr;	/* Result namespace pointer goes here. */
+{
+    register ResolvedNsName *resNamePtr;
+    register Namespace *nsPtr;
+    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+    int result;
+
+    /*
+     * Get the internal representation, converting to a namespace type if
+     * needed. The internal representation is a ResolvedNsName that points
+     * to the actual namespace.
+     */
+
+    if (objPtr->typePtr != &tclNsNameType) {
+        result = tclNsNameType.setFromAnyProc(interp, objPtr);
+        if (result != TCL_OK) {
+            return TCL_ERROR;
+        }
+    }
+    resNamePtr = (ResolvedNsName *) objPtr->internalRep.otherValuePtr;
+
+    /*
+     * Check the context namespace of the resolved symbol to make sure that
+     * it is fresh. If not, then force another conversion to the namespace
+     * type, to discard the old rep and create a new one. Note that we
+     * verify that the namespace id of the cached namespace is the same as
+     * the id when we cached it; this insures that the namespace wasn't
+     * deleted and a new one created at the same address.
+     */
+
+    nsPtr = NULL;
+    if ((resNamePtr != NULL)
+	    && (resNamePtr->refNsPtr == currNsPtr)
+	    && (resNamePtr->nsId == resNamePtr->nsPtr->nsId)) {
+        nsPtr = resNamePtr->nsPtr;
+	if (nsPtr->flags & NS_DEAD) {
+	    nsPtr = NULL;
+	}
+    }
+    if (nsPtr == NULL) {	/* try again */
+        result = tclNsNameType.setFromAnyProc(interp, objPtr);
+        if (result != TCL_OK) {
+            return TCL_ERROR;
+        }
+        resNamePtr = (ResolvedNsName *) objPtr->internalRep.otherValuePtr;
+        if (resNamePtr != NULL) {
+            nsPtr = resNamePtr->nsPtr;
+            if (nsPtr->flags & NS_DEAD) {
+                nsPtr = NULL;
+            }
+        }
+    }
+    *nsPtrPtr = (Tcl_Namespace *) nsPtr;
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_NamespaceObjCmd --
+ *
+ *	Invoked to implement the "namespace" command that creates, deletes,
+ *	or manipulates Tcl namespaces. Handles the following syntax:
+ *
+ *	    namespace children ?name? ?pattern?
+ *	    namespace code arg
+ *	    namespace current
+ *	    namespace delete ?name name...?
+ *	    namespace eval name arg ?arg...?
+ *	    namespace export ?-clear? ?pattern pattern...?
+ *	    namespace forget ?pattern pattern...?
+ *	    namespace import ?-force? ?pattern pattern...?
+ *	    namespace inscope name arg ?arg...?
+ *	    namespace origin name
+ *	    namespace parent ?name?
+ *	    namespace qualifiers string
+ *	    namespace tail string
+ *	    namespace which ?-command? ?-variable? name
+ *
+ * Results:
+ *	Returns TCL_OK if the command is successful. Returns TCL_ERROR if
+ *	anything goes wrong.
+ *
+ * Side effects:
+ *	Based on the subcommand name (e.g., "import"), this procedure
+ *	dispatches to a corresponding procedure NamespaceXXXCmd defined
+ *	statically in this file. This procedure's side effects depend on
+ *	whatever that subcommand procedure does. If there is an error, this
+ *	procedure returns an error message in the interpreter's result
+ *	object. Otherwise it may return a result in the interpreter's result
+ *	object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_NamespaceObjCmd(clientData, interp, objc, objv)
+    ClientData clientData;		/* Arbitrary value passed to cmd. */
+    Tcl_Interp *interp;			/* Current interpreter. */
+    register int objc;			/* Number of arguments. */
+    register Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    static char *subCmds[] = {
+            "children", "code", "current", "delete",
+	    "eval", "export", "forget", "import",
+	    "inscope", "origin", "parent", "qualifiers",
+	    "tail", "which", (char *) NULL};
+    enum NSSubCmdIdx {
+	    NSChildrenIdx, NSCodeIdx, NSCurrentIdx, NSDeleteIdx,
+	    NSEvalIdx, NSExportIdx, NSForgetIdx, NSImportIdx,
+	    NSInscopeIdx, NSOriginIdx, NSParentIdx, NSQualifiersIdx,
+	    NSTailIdx, NSWhichIdx
+    } index;
+    int result;
+
+    if (objc < 2) {
+        Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?arg ...?");
+        return TCL_ERROR;
+    }
+
+    /*
+     * Return an index reflecting the particular subcommand.
+     */
+
+    result = Tcl_GetIndexFromObj((Tcl_Interp *) interp, objv[1], subCmds,
+	    "option", /*flags*/ 0, (int *) &index);
+    if (result != TCL_OK) {
+	return result;
+    }
+    
+    switch (index) {
+        case NSChildrenIdx:
+	    result = NamespaceChildrenCmd(clientData, interp, objc, objv);
+            break;
+        case NSCodeIdx:
+	    result = NamespaceCodeCmd(clientData, interp, objc, objv);
+            break;
+        case NSCurrentIdx:
+	    result = NamespaceCurrentCmd(clientData, interp, objc, objv);
+            break;
+        case NSDeleteIdx:
+	    result = NamespaceDeleteCmd(clientData, interp, objc, objv);
+            break;
+        case NSEvalIdx:
+	    result = NamespaceEvalCmd(clientData, interp, objc, objv);
+            break;
+        case NSExportIdx:
+	    result = NamespaceExportCmd(clientData, interp, objc, objv);
+            break;
+        case NSForgetIdx:
+	    result = NamespaceForgetCmd(clientData, interp, objc, objv);
+            break;
+        case NSImportIdx:
+	    result = NamespaceImportCmd(clientData, interp, objc, objv);
+            break;
+        case NSInscopeIdx:
+	    result = NamespaceInscopeCmd(clientData, interp, objc, objv);
+            break;
+        case NSOriginIdx:
+	    result = NamespaceOriginCmd(clientData, interp, objc, objv);
+            break;
+        case NSParentIdx:
+	    result = NamespaceParentCmd(clientData, interp, objc, objv);
+            break;
+        case NSQualifiersIdx:
+	    result = NamespaceQualifiersCmd(clientData, interp, objc, objv);
+            break;
+        case NSTailIdx:
+	    result = NamespaceTailCmd(clientData, interp, objc, objv);
+            break;
+        case NSWhichIdx:
+	    result = NamespaceWhichCmd(clientData, interp, objc, objv);
+            break;
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NamespaceChildrenCmd --
+ *
+ *	Invoked to implement the "namespace children" command that returns a
+ *	list containing the fully-qualified names of the child namespaces of
+ *	a given namespace. Handles the following syntax:
+ *
+ *	    namespace children ?name? ?pattern?
+ *
+ * Results:
+ *	Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ *	Returns a result in the interpreter's result object. If anything
+ *	goes wrong, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespaceChildrenCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Tcl_Namespace *namespacePtr;
+    Namespace *nsPtr, *childNsPtr;
+    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
+    char *pattern = NULL;
+    Tcl_DString buffer;
+    register Tcl_HashEntry *entryPtr;
+    Tcl_HashSearch search;
+    Tcl_Obj *listPtr, *elemPtr;
+
+    /*
+     * Get a pointer to the specified namespace, or the current namespace.
+     */
+
+    if (objc == 2) {
+	nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+    } else if ((objc == 3) || (objc == 4)) {
+        if (GetNamespaceFromObj(interp, objv[2], &namespacePtr) != TCL_OK) {
+            return TCL_ERROR;
+        }
+        if (namespacePtr == NULL) {
+	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                    "unknown namespace \"",
+		    Tcl_GetStringFromObj(objv[2], (int *) NULL),
+		    "\" in namespace children command", (char *) NULL);
+            return TCL_ERROR;
+        }
+        nsPtr = (Namespace *) namespacePtr;
+    } else {
+	Tcl_WrongNumArgs(interp, 2, objv, "?name? ?pattern?");
+        return TCL_ERROR;
+    }
+
+    /*
+     * Get the glob-style pattern, if any, used to narrow the search.
+     */
+
+    Tcl_DStringInit(&buffer);
+    if (objc == 4) {
+        char *name = Tcl_GetStringFromObj(objv[3], (int *) NULL);
+	
+        if ((*name == ':') && (*(name+1) == ':')) {
+            pattern = name;
+        } else {
+            Tcl_DStringAppend(&buffer, nsPtr->fullName, -1);
+            if (nsPtr != globalNsPtr) {
+                Tcl_DStringAppend(&buffer, "::", 2);
+            }
+            Tcl_DStringAppend(&buffer, name, -1);
+            pattern = Tcl_DStringValue(&buffer);
+        }
+    }
+
+    /*
+     * Create a list containing the full names of all child namespaces
+     * whose names match the specified pattern, if any.
+     */
+
+    listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+    entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
+    while (entryPtr != NULL) {
+        childNsPtr = (Namespace *) Tcl_GetHashValue(entryPtr);
+        if ((pattern == NULL)
+	        || Tcl_StringMatch(childNsPtr->fullName, pattern)) {
+            elemPtr = Tcl_NewStringObj(childNsPtr->fullName, -1);
+            Tcl_ListObjAppendElement(interp, listPtr, elemPtr);
+        }
+        entryPtr = Tcl_NextHashEntry(&search);
+    }
+
+    Tcl_SetObjResult(interp, listPtr);
+    Tcl_DStringFree(&buffer);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NamespaceCodeCmd --
+ *
+ *	Invoked to implement the "namespace code" command to capture the
+ *	namespace context of a command. Handles the following syntax:
+ *
+ *	    namespace code arg
+ *
+ *	Here "arg" can be a list. "namespace code arg" produces a result
+ *	equivalent to that produced by the command
+ *
+ *	    list namespace inscope [namespace current] $arg
+ *
+ *	However, if "arg" is itself a scoped value starting with
+ *	"namespace inscope", then the result is just "arg".
+ *
+ * Results:
+ *	Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ *	If anything goes wrong, this procedure returns an error
+ *	message as the result in the interpreter's result object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespaceCodeCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Namespace *currNsPtr;
+    Tcl_Obj *listPtr, *objPtr;
+    register char *arg, *p;
+    int length;
+
+    if (objc != 3) {
+	Tcl_WrongNumArgs(interp, 2, objv, "arg");
+        return TCL_ERROR;
+    }
+
+    /*
+     * If "arg" is already a scoped value, then return it directly.
+     */
+
+    arg = Tcl_GetStringFromObj(objv[2], &length);
+    if ((*arg == 'n') && (length > 17)
+	    && (strncmp(arg, "namespace", 9) == 0)) {
+	for (p = (arg + 9);  (*p == ' ');  p++) {
+	    /* empty body: skip over spaces */
+	}
+	if ((*p == 'i') && ((p + 7) <= (arg + length))
+	        && (strncmp(p, "inscope", 7) == 0)) {
+	    Tcl_SetObjResult(interp, objv[2]);
+	    return TCL_OK;
+	}
+    }
+
+    /*
+     * Otherwise, construct a scoped command by building a list with
+     * "namespace inscope", the full name of the current namespace, and 
+     * the argument "arg". By constructing a list, we ensure that scoped
+     * commands are interpreted properly when they are executed later,
+     * by the "namespace inscope" command.
+     */
+
+    listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+    Tcl_ListObjAppendElement(interp, listPtr,
+            Tcl_NewStringObj("namespace", -1));
+    Tcl_ListObjAppendElement(interp, listPtr,
+	    Tcl_NewStringObj("inscope", -1));
+
+    currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+    if (currNsPtr == (Namespace *) Tcl_GetGlobalNamespace(interp)) {
+	objPtr = Tcl_NewStringObj("::", -1);
+    } else {
+	objPtr = Tcl_NewStringObj(currNsPtr->fullName, -1);
+    }
+    Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+    
+    Tcl_ListObjAppendElement(interp, listPtr, objv[2]);
+
+    Tcl_SetObjResult(interp, listPtr);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NamespaceCurrentCmd --
+ *
+ *	Invoked to implement the "namespace current" command which returns
+ *	the fully-qualified name of the current namespace. Handles the
+ *	following syntax:
+ *
+ *	    namespace current
+ *
+ * Results:
+ *	Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ *	Returns a result in the interpreter's result object. If anything
+ *	goes wrong, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespaceCurrentCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    register Namespace *currNsPtr;
+
+    if (objc != 2) {
+	Tcl_WrongNumArgs(interp, 2, objv, NULL);
+        return TCL_ERROR;
+    }
+
+    /*
+     * The "real" name of the global namespace ("::") is the null string,
+     * but we return "::" for it as a convenience to programmers. Note that
+     * "" and "::" are treated as synonyms by the namespace code so that it
+     * is still easy to do things like:
+     *
+     *    namespace [namespace current]::bar { ... }
+     */
+
+    currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+    if (currNsPtr == (Namespace *) Tcl_GetGlobalNamespace(interp)) {
+        Tcl_AppendToObj(Tcl_GetObjResult(interp), "::", -1);
+    } else {
+	Tcl_AppendToObj(Tcl_GetObjResult(interp), currNsPtr->fullName, -1);
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NamespaceDeleteCmd --
+ *
+ *	Invoked to implement the "namespace delete" command to delete
+ *	namespace(s). Handles the following syntax:
+ *
+ *	    namespace delete ?name name...?
+ *
+ *	Each name identifies a namespace. It may include a sequence of
+ *	namespace qualifiers separated by "::"s. If a namespace is found, it
+ *	is deleted: all variables and procedures contained in that namespace
+ *	are deleted. If that namespace is being used on the call stack, it
+ *	is kept alive (but logically deleted) until it is removed from the
+ *	call stack: that is, it can no longer be referenced by name but any
+ *	currently executing procedure that refers to it is allowed to do so
+ *	until the procedure returns. If the namespace can't be found, this
+ *	procedure returns an error. If no namespaces are specified, this
+ *	command does nothing.
+ *
+ * Results:
+ *	Returns TCL_OK if successful, and  TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ *	Deletes the specified namespaces. If anything goes wrong, this
+ *	procedure returns an error message in the interpreter's
+ *	result object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespaceDeleteCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Tcl_Namespace *namespacePtr;
+    char *name;
+    register int i;
+
+    if (objc < 2) {
+        Tcl_WrongNumArgs(interp, 2, objv, "?name name...?");
+        return TCL_ERROR;
+    }
+
+    /*
+     * Destroying one namespace may cause another to be destroyed. Break
+     * this into two passes: first check to make sure that all namespaces on
+     * the command line are valid, and report any errors.
+     */
+
+    for (i = 2;  i < objc;  i++) {
+        name = Tcl_GetStringFromObj(objv[i], (int *) NULL);
+	namespacePtr = Tcl_FindNamespace(interp, name,
+		(Tcl_Namespace *) NULL, /*flags*/ 0);
+        if (namespacePtr == NULL) {
+	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                    "unknown namespace \"",
+		    Tcl_GetStringFromObj(objv[i], (int *) NULL),
+		    "\" in namespace delete command", (char *) NULL);
+            return TCL_ERROR;
+        }
+    }
+
+    /*
+     * Okay, now delete each namespace.
+     */
+
+    for (i = 2;  i < objc;  i++) {
+        name = Tcl_GetStringFromObj(objv[i], (int *) NULL);
+	namespacePtr = Tcl_FindNamespace(interp, name,
+	    (Tcl_Namespace *) NULL, /* flags */ 0);
+	if (namespacePtr) {
+            Tcl_DeleteNamespace(namespacePtr);
+        }
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NamespaceEvalCmd --
+ *
+ *	Invoked to implement the "namespace eval" command. Executes
+ *	commands in a namespace. If the namespace does not already exist,
+ *	it is created. Handles the following syntax:
+ *
+ *	    namespace eval name arg ?arg...?
+ *
+ *	If more than one arg argument is specified, the command that is
+ *	executed is the result of concatenating the arguments together with
+ *	a space between each argument.
+ *
+ * Results:
+ *	Returns TCL_OK if the namespace is found and the commands are
+ *	executed successfully. Returns TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ *	Returns the result of the command in the interpreter's result
+ *	object. If anything goes wrong, this procedure returns an error
+ *	message as the result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespaceEvalCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Tcl_Namespace *namespacePtr;
+    Tcl_CallFrame frame;
+    Tcl_Obj *objPtr;
+    char *name;
+    int length, result;
+
+    if (objc < 4) {
+        Tcl_WrongNumArgs(interp, 2, objv, "name arg ?arg...?");
+        return TCL_ERROR;
+    }
+
+    /*
+     * Try to resolve the namespace reference, caching the result in the
+     * namespace object along the way.
+     */
+
+    result = GetNamespaceFromObj(interp, objv[2], &namespacePtr);
+    if (result != TCL_OK) {
+        return result;
+    }
+
+    /*
+     * If the namespace wasn't found, try to create it.
+     */
+    
+    if (namespacePtr == NULL) {
+	name = Tcl_GetStringFromObj(objv[2], &length);
+	namespacePtr = Tcl_CreateNamespace(interp, name, (ClientData) NULL, 
+                (Tcl_NamespaceDeleteProc *) NULL);
+	if (namespacePtr == NULL) {
+	    return TCL_ERROR;
+	}
+    }
+
+    /*
+     * Make the specified namespace the current namespace and evaluate
+     * the command(s).
+     */
+
+    result = Tcl_PushCallFrame(interp, &frame, namespacePtr,
+	    /*isProcCallFrame*/ 0);
+    if (result != TCL_OK) {
+        return TCL_ERROR;
+    }
+
+    if (objc == 4) {
+        result = Tcl_EvalObj(interp, objv[3]);
+    } else {
+        objPtr = Tcl_ConcatObj(objc-3, objv+3);
+        result = Tcl_EvalObj(interp, objPtr);
+        Tcl_DecrRefCount(objPtr);  /* we're done with the object */
+    }
+    if (result == TCL_ERROR) {
+        char msg[256];
+	
+        sprintf(msg, "\n    (in namespace eval \"%.200s\" script line %d)",
+            namespacePtr->fullName, interp->errorLine);
+        Tcl_AddObjErrorInfo(interp, msg, -1);
+    }
+
+    /*
+     * Restore the previous "current" namespace.
+     */
+    
+    Tcl_PopCallFrame(interp);
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NamespaceExportCmd --
+ *
+ *	Invoked to implement the "namespace export" command that specifies
+ *	which commands are exported from a namespace. The exported commands
+ *	are those that can be imported into another namespace using
+ *	"namespace import". Both commands defined in a namespace and
+ *	commands the namespace has imported can be exported by a
+ *	namespace. This command has the following syntax:
+ *
+ *	    namespace export ?-clear? ?pattern pattern...?
+ *
+ *	Each pattern may contain "string match"-style pattern matching
+ *	special characters, but the pattern may not include any namespace
+ *	qualifiers: that is, the pattern must specify commands in the
+ *	current (exporting) namespace. The specified patterns are appended
+ *	onto the namespace's list of export patterns.
+ *
+ *	To reset the namespace's export pattern list, specify the "-clear"
+ *	flag.
+ *
+ *	If there are no export patterns and the "-clear" flag isn't given,
+ *	this command returns the namespace's current export list.
+ *
+ * Results:
+ *	Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ *	Returns a result in the interpreter's result object. If anything
+ *	goes wrong, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespaceExportCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Namespace *currNsPtr = (Namespace*) Tcl_GetCurrentNamespace(interp);
+    char *pattern, *string;
+    int resetListFirst = 0;
+    int firstArg, patternCt, i, result;
+
+    if (objc < 2) {
+	Tcl_WrongNumArgs(interp, 2, objv,
+	        "?-clear? ?pattern pattern...?");
+        return TCL_ERROR;
+    }
+
+    /*
+     * Process the optional "-clear" argument.
+     */
+
+    firstArg = 2;
+    if (firstArg < objc) {
+	string = Tcl_GetStringFromObj(objv[firstArg], (int *) NULL);
+	if (strcmp(string, "-clear") == 0) {
+	    resetListFirst = 1;
+	    firstArg++;
+	}
+    }
+
+    /*
+     * If no pattern arguments are given, and "-clear" isn't specified,
+     * return the namespace's current export pattern list.
+     */
+
+    patternCt = (objc - firstArg);
+    if (patternCt == 0) {
+	if (firstArg > 2) {
+	    return TCL_OK;
+	} else {		/* create list with export patterns */
+	    Tcl_Obj *listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+	    result = Tcl_AppendExportList(interp,
+		    (Tcl_Namespace *) currNsPtr, listPtr);
+	    if (result != TCL_OK) {
+		return result;
+	    }
+	    Tcl_SetObjResult(interp, listPtr);
+	    return TCL_OK;
+	}
+    }
+
+    /*
+     * Add each pattern to the namespace's export pattern list.
+     */
+    
+    for (i = firstArg;  i < objc;  i++) {
+	pattern = Tcl_GetStringFromObj(objv[i], (int *) NULL);
+	result = Tcl_Export(interp, (Tcl_Namespace *) currNsPtr, pattern,
+		((i == firstArg)? resetListFirst : 0));
+        if (result != TCL_OK) {
+            return result;
+        }
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NamespaceForgetCmd --
+ *
+ *	Invoked to implement the "namespace forget" command to remove
+ *	imported commands from a namespace. Handles the following syntax:
+ *
+ *	    namespace forget ?pattern pattern...?
+ *
+ *	Each pattern is a name like "foo::*" or "a::b::x*". That is, the
+ *	pattern may include the special pattern matching characters
+ *	recognized by the "string match" command, but only in the command
+ *	name at the end of the qualified name; the special pattern
+ *	characters may not appear in a namespace name. All of the commands
+ *	that match that pattern are checked to see if they have an imported
+ *	command in the current namespace that refers to the matched
+ *	command. If there is an alias, it is removed.
+ *	
+ * Results:
+ *	Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ *	Imported commands are removed from the current namespace. If
+ *	anything goes wrong, this procedure returns an error message in the
+ *	interpreter's result object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespaceForgetCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    char *pattern;
+    register int i, result;
+
+    if (objc < 2) {
+        Tcl_WrongNumArgs(interp, 2, objv, "?pattern pattern...?");
+        return TCL_ERROR;
+    }
+
+    for (i = 2;  i < objc;  i++) {
+        pattern = Tcl_GetStringFromObj(objv[i], (int *) NULL);
+	result = Tcl_ForgetImport(interp, (Tcl_Namespace *) NULL, pattern);
+        if (result != TCL_OK) {
+            return result;
+        }
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NamespaceImportCmd --
+ *
+ *	Invoked to implement the "namespace import" command that imports
+ *	commands into a namespace. Handles the following syntax:
+ *
+ *	    namespace import ?-force? ?pattern pattern...?
+ *
+ *	Each pattern is a namespace-qualified name like "foo::*",
+ *	"a::b::x*", or "bar::p". That is, the pattern may include the
+ *	special pattern matching characters recognized by the "string match"
+ *	command, but only in the command name at the end of the qualified
+ *	name; the special pattern characters may not appear in a namespace
+ *	name. All of the commands that match the pattern and which are
+ *	exported from their namespace are made accessible from the current
+ *	namespace context. This is done by creating a new "imported command"
+ *	in the current namespace that points to the real command in its
+ *	original namespace; when the imported command is called, it invokes
+ *	the real command.
+ *
+ *	If an imported command conflicts with an existing command, it is
+ *	treated as an error. But if the "-force" option is included, then
+ *	existing commands are overwritten by the imported commands.
+ *	
+ * Results:
+ *	Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ *	Adds imported commands to the current namespace. If anything goes
+ *	wrong, this procedure returns an error message in the interpreter's
+ *	result object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespaceImportCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    int allowOverwrite = 0;
+    char *string, *pattern;
+    register int i, result;
+    int firstArg;
+
+    if (objc < 2) {
+        Tcl_WrongNumArgs(interp, 2, objv,
+	        "?-force? ?pattern pattern...?");
+        return TCL_ERROR;
+    }
+
+    /*
+     * Skip over the optional "-force" as the first argument.
+     */
+
+    firstArg = 2;
+    if (firstArg < objc) {
+	string = Tcl_GetStringFromObj(objv[firstArg], (int *) NULL);
+	if ((*string == '-') && (strcmp(string, "-force") == 0)) {
+	    allowOverwrite = 1;
+	    firstArg++;
+	}
+    }
+
+    /*
+     * Handle the imports for each of the patterns.
+     */
+
+    for (i = firstArg;  i < objc;  i++) {
+        pattern = Tcl_GetStringFromObj(objv[i], (int *) NULL);
+	result = Tcl_Import(interp, (Tcl_Namespace *) NULL, pattern,
+	        allowOverwrite);
+        if (result != TCL_OK) {
+            return result;
+        }
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NamespaceInscopeCmd --
+ *
+ *	Invoked to implement the "namespace inscope" command that executes a
+ *	script in the context of a particular namespace. This command is not
+ *	expected to be used directly by programmers; calls to it are
+ *	generated implicitly when programs use "namespace code" commands
+ *	to register callback scripts. Handles the following syntax:
+ *
+ *	    namespace inscope name arg ?arg...?
+ *
+ *	The "namespace inscope" command is much like the "namespace eval"
+ *	command except that it has lappend semantics and the namespace must
+ *	already exist. It treats the first argument as a list, and appends
+ *	any arguments after the first onto the end as proper list elements.
+ *	For example,
+ *
+ *	    namespace inscope ::foo a b c d
+ *
+ *	is equivalent to
+ *
+ *	    namespace eval ::foo [concat a [list b c d]]
+ *
+ *	This lappend semantics is important because many callback scripts
+ *	are actually prefixes.
+ *
+ * Results:
+ *	Returns TCL_OK to indicate success, or TCL_ERROR to indicate
+ *	failure.
+ *
+ * Side effects:
+ *	Returns a result in the Tcl interpreter's result object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespaceInscopeCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Tcl_Namespace *namespacePtr;
+    Tcl_CallFrame frame;
+    int i, result;
+
+    if (objc < 4) {
+	Tcl_WrongNumArgs(interp, 2, objv, "name arg ?arg...?");
+        return TCL_ERROR;
+    }
+
+    /*
+     * Resolve the namespace reference.
+     */
+
+    result = GetNamespaceFromObj(interp, objv[2], &namespacePtr);
+    if (result != TCL_OK) {
+        return result;
+    }
+    if (namespacePtr == NULL) {
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+	        "unknown namespace \"",
+		Tcl_GetStringFromObj(objv[2], (int *) NULL),
+		"\" in inscope namespace command", (char *) NULL);
+        return TCL_ERROR;
+    }
+
+    /*
+     * Make the specified namespace the current namespace.
+     */
+
+    result = Tcl_PushCallFrame(interp, &frame, namespacePtr,
+	    /*isProcCallFrame*/ 0);
+    if (result != TCL_OK) {
+        return result;
+    }
+
+    /*
+     * Execute the command. If there is just one argument, just treat it as
+     * a script and evaluate it. Otherwise, create a list from the arguments
+     * after the first one, then concatenate the first argument and the list
+     * of extra arguments to form the command to evaluate.
+     */
+
+    if (objc == 4) {
+        result = Tcl_EvalObj(interp, objv[3]);
+    } else {
+	Tcl_Obj *concatObjv[2];
+	register Tcl_Obj *listPtr, *cmdObjPtr;
+	
+        listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+        for (i = 4;  i < objc;  i++) {
+	    result = Tcl_ListObjAppendElement(interp, listPtr, objv[i]);
+            if (result != TCL_OK) {
+                Tcl_DecrRefCount(listPtr); /* free unneeded obj */
+                return result;
+            }
+        }
+
+	concatObjv[0] = objv[3];
+	concatObjv[1] = listPtr;
+	cmdObjPtr = Tcl_ConcatObj(2, concatObjv);
+        result = Tcl_EvalObj(interp, cmdObjPtr);
+	
+	Tcl_DecrRefCount(cmdObjPtr);  /* we're done with the cmd object */
+	Tcl_DecrRefCount(listPtr);    /* we're done with the list object */
+    }
+    if (result == TCL_ERROR) {
+        char msg[256];
+	
+        sprintf(msg,
+	    "\n    (in namespace inscope \"%.200s\" script line %d)",
+            namespacePtr->fullName, interp->errorLine);
+        Tcl_AddObjErrorInfo(interp, msg, -1);
+    }
+
+    /*
+     * Restore the previous "current" namespace.
+     */
+
+    Tcl_PopCallFrame(interp);
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NamespaceOriginCmd --
+ *
+ *	Invoked to implement the "namespace origin" command to return the
+ *	fully-qualified name of the "real" command to which the specified
+ *	"imported command" refers. Handles the following syntax:
+ *
+ *	    namespace origin name
+ *
+ * Results:
+ *	An imported command is created in an namespace when that namespace
+ *	imports a command from another namespace. If a command is imported
+ *	into a sequence of namespaces a, b,...,n where each successive
+ *	namespace just imports the command from the previous namespace, this
+ *	command returns the fully-qualified name of the original command in
+ *	the first namespace, a. If "name" does not refer to an alias, its
+ *	fully-qualified name is returned. The returned name is stored in the
+ *	interpreter's result object. This procedure returns TCL_OK if
+ *	successful, and TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ *	If anything goes wrong, this procedure returns an error message in
+ *	the interpreter's result object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespaceOriginCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Tcl_Command command, origCommand;
+
+    if (objc != 3) {
+        Tcl_WrongNumArgs(interp, 2, objv, "name");
+        return TCL_ERROR;
+    }
+
+    command = Tcl_GetCommandFromObj(interp, objv[2]);
+    if (command == (Tcl_Command) NULL) {
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		"invalid command name \"",
+		Tcl_GetStringFromObj(objv[2], (int *) NULL),
+		"\"", (char *) NULL);
+	return TCL_ERROR;
+    }
+    origCommand = TclGetOriginalCommand(command);
+    if (origCommand == (Tcl_Command) NULL) {
+	/*
+	 * The specified command isn't an imported command. Return the
+	 * command's name qualified by the full name of the namespace it
+	 * was defined in.
+	 */
+	
+	Tcl_GetCommandFullName(interp, command, Tcl_GetObjResult(interp));
+    } else {
+	Tcl_GetCommandFullName(interp, origCommand, Tcl_GetObjResult(interp));
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NamespaceParentCmd --
+ *
+ *	Invoked to implement the "namespace parent" command that returns the
+ *	fully-qualified name of the parent namespace for a specified
+ *	namespace. Handles the following syntax:
+ *
+ *	    namespace parent ?name?
+ *
+ * Results:
+ *	Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ *	Returns a result in the interpreter's result object. If anything
+ *	goes wrong, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespaceParentCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Tcl_Namespace *nsPtr;
+    int result;
+
+    if (objc == 2) {
+        nsPtr = Tcl_GetCurrentNamespace(interp);
+    } else if (objc == 3) {
+	result = GetNamespaceFromObj(interp, objv[2], &nsPtr);
+        if (result != TCL_OK) {
+            return result;
+        }
+        if (nsPtr == NULL) {
+            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                    "unknown namespace \"",
+		    Tcl_GetStringFromObj(objv[2], (int *) NULL),
+		    "\" in namespace parent command", (char *) NULL);
+            return TCL_ERROR;
+        }
+    } else {
+        Tcl_WrongNumArgs(interp, 2, objv, "?name?");
+        return TCL_ERROR;
+    }
+
+    /*
+     * Report the parent of the specified namespace.
+     */
+
+    if (nsPtr->parentPtr != NULL) {
+        Tcl_SetStringObj(Tcl_GetObjResult(interp),
+	        nsPtr->parentPtr->fullName, -1);
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NamespaceQualifiersCmd --
+ *
+ *	Invoked to implement the "namespace qualifiers" command that returns
+ *	any leading namespace qualifiers in a string. These qualifiers are
+ *	namespace names separated by "::"s. For example, for "::foo::p" this
+ *	command returns "::foo", and for "::" it returns "". This command
+ *	is the complement of the "namespace tail" command. Note that this
+ *	command does not check whether the "namespace" names are, in fact,
+ *	the names of currently defined namespaces. Handles the following
+ *	syntax:
+ *
+ *	    namespace qualifiers string
+ *
+ * Results:
+ *	Returns TCL_OK if successful, and  TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ *	Returns a result in the interpreter's result object. If anything
+ *	goes wrong, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespaceQualifiersCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    register char *name, *p;
+    int length;
+
+    if (objc != 3) {
+	Tcl_WrongNumArgs(interp, 2, objv, "string");
+        return TCL_ERROR;
+    }
+
+    /*
+     * Find the end of the string, then work backward and find
+     * the start of the last "::" qualifier.
+     */
+
+    name = Tcl_GetStringFromObj(objv[2], (int *) NULL);
+    for (p = name;  *p != '\0';  p++) {
+	/* empty body */
+    }
+    while (--p >= name) {
+        if ((*p == ':') && (p > name) && (*(p-1) == ':')) {
+	    p -= 2;		/* back up over the :: */
+	    while ((p >= name) && (*p == ':')) {
+		p--;		/* back up over the preceeding : */
+	    }
+	    break;
+        }
+    }
+
+    if (p >= name) {
+        length = p-name+1;
+        Tcl_AppendToObj(Tcl_GetObjResult(interp), name, length);
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NamespaceTailCmd --
+ *
+ *	Invoked to implement the "namespace tail" command that returns the
+ *	trailing name at the end of a string with "::" namespace
+ *	qualifiers. These qualifiers are namespace names separated by
+ *	"::"s. For example, for "::foo::p" this command returns "p", and for
+ *	"::" it returns "". This command is the complement of the "namespace
+ *	qualifiers" command. Note that this command does not check whether
+ *	the "namespace" names are, in fact, the names of currently defined
+ *	namespaces. Handles the following syntax:
+ *
+ *	    namespace tail string
+ *
+ * Results:
+ *	Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ *	Returns a result in the interpreter's result object. If anything
+ *	goes wrong, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespaceTailCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    register char *name, *p;
+
+    if (objc != 3) {
+	Tcl_WrongNumArgs(interp, 2, objv, "string");
+        return TCL_ERROR;
+    }
+
+    /*
+     * Find the end of the string, then work backward and find the
+     * last "::" qualifier.
+     */
+
+    name = Tcl_GetStringFromObj(objv[2], (int *) NULL);
+    for (p = name;  *p != '\0';  p++) {
+	/* empty body */
+    }
+    while (--p > name) {
+        if ((*p == ':') && (*(p-1) == ':')) {
+            p++;		/* just after the last "::" */
+            break;
+        }
+    }
+    
+    if (p >= name) {
+        Tcl_AppendToObj(Tcl_GetObjResult(interp), p, -1);
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NamespaceWhichCmd --
+ *
+ *	Invoked to implement the "namespace which" command that returns the
+ *	fully-qualified name of a command or variable. If the specified
+ *	command or variable does not exist, it returns "". Handles the
+ *	following syntax:
+ *
+ *	    namespace which ?-command? ?-variable? name
+ *
+ * Results:
+ *	Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ *	Returns a result in the interpreter's result object. If anything
+ *	goes wrong, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespaceWhichCmd(dummy, interp, objc, objv)
+    ClientData dummy;                   /* Not used. */
+    Tcl_Interp *interp;                 /* Current interpreter. */
+    int objc;                           /* Number of arguments. */
+    Tcl_Obj *CONST objv[];              /* Argument objects. */
+{
+    register char *arg;
+    Tcl_Command cmd;
+    Tcl_Var variable;
+    int argIndex, lookup;
+
+    if (objc < 3) {
+        badArgs:
+        Tcl_WrongNumArgs(interp, 2, objv,
+	        "?-command? ?-variable? name");
+        return TCL_ERROR;
+    }
+
+    /*
+     * Look for a flag controlling the lookup.
+     */
+
+    argIndex = 2;
+    lookup = 0;			/* assume command lookup by default */
+    arg = Tcl_GetStringFromObj(objv[2], (int *) NULL);
+    if (*arg == '-') {
+	if (strncmp(arg, "-command", 8) == 0) {
+	    lookup = 0;
+	} else if (strncmp(arg, "-variable", 9) == 0) {
+	    lookup = 1;
+	} else {
+	    goto badArgs;
+	}
+	argIndex = 3;
+    }
+    if (objc != (argIndex + 1)) {
+	goto badArgs;
+    }
+
+    switch (lookup) {
+    case 0:			/* -command */
+	cmd = Tcl_GetCommandFromObj(interp, objv[argIndex]);
+        if (cmd == (Tcl_Command) NULL) {	
+            return TCL_OK;	/* cmd not found, just return (no error) */
+        }
+	Tcl_GetCommandFullName(interp, cmd, Tcl_GetObjResult(interp));
+        break;
+
+    case 1:			/* -variable */
+        arg = Tcl_GetStringFromObj(objv[argIndex], (int *) NULL);
+	variable = Tcl_FindNamespaceVar(interp, arg, (Tcl_Namespace *) NULL,
+		/*flags*/ 0);
+        if (variable != (Tcl_Var) NULL) {
+            Tcl_GetVariableFullName(interp, variable, Tcl_GetObjResult(interp));
+        }
+        break;
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeNsNameInternalRep --
+ *
+ *	Frees the resources associated with a nsName object's internal
+ *	representation.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Decrements the ref count of any Namespace structure pointed
+ *	to by the nsName's internal representation. If there are no more
+ *	references to the namespace, it's structure will be freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeNsNameInternalRep(objPtr)
+    register Tcl_Obj *objPtr;   /* nsName object with internal
+                                 * representation to free */
+{
+    register ResolvedNsName *resNamePtr =
+        (ResolvedNsName *) objPtr->internalRep.otherValuePtr;
+    Namespace *nsPtr;
+
+    /*
+     * Decrement the reference count of the namespace. If there are no
+     * more references, free it up.
+     */
+
+    if (resNamePtr != NULL) {
+        resNamePtr->refCount--;
+        if (resNamePtr->refCount == 0) {
+
+            /*
+	     * Decrement the reference count for the cached namespace.  If
+	     * the namespace is dead, and there are no more references to
+	     * it, free it.
+	     */
+
+            nsPtr = resNamePtr->nsPtr;
+            nsPtr->refCount--;
+            if ((nsPtr->refCount == 0) && (nsPtr->flags & NS_DEAD)) {
+                NamespaceFree(nsPtr);
+            }
+            ckfree((char *) resNamePtr);
+        }
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupNsNameInternalRep --
+ *
+ *	Initializes the internal representation of a nsName object to a copy
+ *	of the internal representation of another nsName object.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	copyPtr's internal rep is set to refer to the same namespace
+ *	referenced by srcPtr's internal rep. Increments the ref count of
+ *	the ResolvedNsName structure used to hold the namespace reference.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DupNsNameInternalRep(srcPtr, copyPtr)
+    Tcl_Obj *srcPtr;                /* Object with internal rep to copy. */
+    register Tcl_Obj *copyPtr;      /* Object with internal rep to set. */
+{
+    register ResolvedNsName *resNamePtr =
+        (ResolvedNsName *) srcPtr->internalRep.otherValuePtr;
+
+    copyPtr->internalRep.otherValuePtr = (VOID *) resNamePtr;
+    if (resNamePtr != NULL) {
+        resNamePtr->refCount++;
+    }
+    copyPtr->typePtr = &tclNsNameType;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetNsNameFromAny --
+ *
+ *	Attempt to generate a nsName internal representation for a
+ *	Tcl object.
+ *
+ * Results:
+ *	Returns TCL_OK if the value could be converted to a proper
+ *	namespace reference. Otherwise, it returns TCL_ERROR, along
+ *	with an error message in the interpreter's result object.
+ *
+ * Side effects:
+ *	If successful, the object is made a nsName object. Its internal rep
+ *	is set to point to a ResolvedNsName, which contains a cached pointer
+ *	to the Namespace. Reference counts are kept on both the
+ *	ResolvedNsName and the Namespace, so we can keep track of their
+ *	usage and free them when appropriate.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetNsNameFromAny(interp, objPtr)
+    Tcl_Interp *interp;		/* Points to the namespace in which to
+				 * resolve name. Also used for error
+				 * reporting if not NULL. */
+    register Tcl_Obj *objPtr;	/* The object to convert. */
+{
+    register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
+    char *name, *dummy;
+    Namespace *nsPtr, *dummy1Ptr, *dummy2Ptr;
+    register ResolvedNsName *resNamePtr;
+
+    /*
+     * Get the string representation. Make it up-to-date if necessary.
+     */
+
+    name = objPtr->bytes;
+    if (name == NULL) {
+	name = Tcl_GetStringFromObj(objPtr, (int *) NULL);
+    }
+
+    /*
+     * Look for the namespace "name" in the current namespace. If there is
+     * an error parsing the (possibly qualified) name, return an error.
+     * If the namespace isn't found, we convert the object to an nsName
+     * object with a NULL ResolvedNsName* internal rep.
+     */
+
+    TclGetNamespaceForQualName(interp, name, (Namespace *) NULL,
+       /*flags*/ FIND_ONLY_NS, &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);
+
+    /*
+     * If we found a namespace, then create a new ResolvedNsName structure
+     * that holds a reference to it.
+     */
+
+    if (nsPtr != NULL) {
+	Namespace *currNsPtr =
+	        (Namespace *) Tcl_GetCurrentNamespace(interp);
+	
+        nsPtr->refCount++;
+        resNamePtr = (ResolvedNsName *) ckalloc(sizeof(ResolvedNsName));
+        resNamePtr->nsPtr = nsPtr;
+        resNamePtr->nsId = nsPtr->nsId;
+        resNamePtr->refNsPtr = currNsPtr;
+        resNamePtr->refCount = 1;
+    } else {
+        resNamePtr = NULL;
+    }
+
+    /*
+     * Free the old internalRep before setting the new one.
+     * We do this as late as possible to allow the conversion code
+     * (in particular, Tcl_GetStringFromObj) to use that old internalRep.
+     */
+
+    if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
+        oldTypePtr->freeIntRepProc(objPtr);
+    }
+
+    objPtr->internalRep.otherValuePtr = (VOID *) resNamePtr;
+    objPtr->typePtr = &tclNsNameType;
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateStringOfNsName --
+ *
+ *	Updates the string representation for a nsName object.
+ *	Note: This procedure does not free an existing old string rep
+ *	so storage will be lost if this has not already been done.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The object's string is set to a copy of the fully qualified
+ *	namespace name.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateStringOfNsName(objPtr)
+    register Tcl_Obj *objPtr; /* nsName object with string rep to update. */
+{
+    ResolvedNsName *resNamePtr =
+        (ResolvedNsName *) objPtr->internalRep.otherValuePtr;
+    register Namespace *nsPtr;
+    char *name = "";
+    int length;
+
+    if ((resNamePtr != NULL)
+	    && (resNamePtr->nsId == resNamePtr->nsPtr->nsId)) {
+        nsPtr = resNamePtr->nsPtr;
+        if (nsPtr->flags & NS_DEAD) {
+            nsPtr = NULL;
+        }
+        if (nsPtr != NULL) {
+            name = nsPtr->fullName;
+        }
+    }
+
+    /*
+     * The following sets the string rep to an empty string on the heap
+     * if the internal rep is NULL.
+     */
+
+    length = strlen(name);
+    if (length == 0) {
+	objPtr->bytes = tclEmptyStringRep;
+    } else {
+	objPtr->bytes = (char *) ckalloc((unsigned) (length + 1));
+	memcpy((VOID *) objPtr->bytes, (VOID *) name, (unsigned) length);
+	objPtr->bytes[length] = '\0';
+    }
+    objPtr->length = length;
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclObj.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclObj.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclObj.c	(revision 5)
@@ -0,0 +1,2184 @@
+/* 
+ * tclObj.c --
+ *
+ *	This file contains Tcl object-related procedures that are used by
+ * 	many Tcl commands.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclObj.c,v 1.1 2008-06-04 13:58:08 demin Exp $
+ */
+
+#include "tclInt.h"
+#include "tclPort.h"
+
+/*
+ * Table of all object types.
+ */
+
+static Tcl_HashTable typeTable;
+static int typeTableInitialized = 0;    /* 0 means not yet initialized. */
+
+/*
+ * Head of the list of free Tcl_Objs we maintain.
+ */
+
+Tcl_Obj *tclFreeObjList = NULL;
+
+/*
+ * Pointer to a heap-allocated string of length zero that the Tcl core uses
+ * as the value of an empty string representation for an object. This value
+ * is shared by all new objects allocated by Tcl_NewObj.
+ */
+
+char *tclEmptyStringRep = NULL;
+
+/*
+ * Count of the number of Tcl objects every allocated (by Tcl_NewObj) and
+ * freed (by TclFreeObj).
+ */
+
+#ifdef TCL_COMPILE_STATS
+long tclObjsAlloced = 0;
+long tclObjsFreed = 0;
+#endif /* TCL_COMPILE_STATS */
+
+/*
+ * Prototypes for procedures defined later in this file:
+ */
+
+static void		DupBooleanInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
+			    Tcl_Obj *copyPtr));
+static void		DupDoubleInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
+			    Tcl_Obj *copyPtr));
+static void		DupIntInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
+			    Tcl_Obj *copyPtr));
+static void		FinalizeTypeTable _ANSI_ARGS_((void));
+static void		FinalizeFreeObjList _ANSI_ARGS_((void));
+static void		InitTypeTable _ANSI_ARGS_((void));
+static int		SetBooleanFromAny _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr));
+static int		SetDoubleFromAny _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr));
+static int		SetIntFromAny _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr));
+static void		UpdateStringOfBoolean _ANSI_ARGS_((Tcl_Obj *objPtr));
+static void		UpdateStringOfDouble _ANSI_ARGS_((Tcl_Obj *objPtr));
+static void		UpdateStringOfInt _ANSI_ARGS_((Tcl_Obj *objPtr));
+
+/*
+ * The structures below defines the Tcl object types defined in this file by
+ * means of procedures that can be invoked by generic object code. See also
+ * tclStringObj.c, tclListObj.c, tclByteCode.c for other type manager
+ * implementations.
+ */
+
+Tcl_ObjType tclBooleanType = {
+    "boolean",				/* name */
+    (Tcl_FreeInternalRepProc *) NULL,   /* freeIntRepProc */
+    DupBooleanInternalRep,		/* dupIntRepProc */
+    UpdateStringOfBoolean,		/* updateStringProc */
+    SetBooleanFromAny			/* setFromAnyProc */
+};
+
+Tcl_ObjType tclDoubleType = {
+    "double",				/* name */
+    (Tcl_FreeInternalRepProc *) NULL,   /* freeIntRepProc */
+    DupDoubleInternalRep,		/* dupIntRepProc */
+    UpdateStringOfDouble,		/* updateStringProc */
+    SetDoubleFromAny			/* setFromAnyProc */
+};
+
+Tcl_ObjType tclIntType = {
+    "int",				/* name */
+    (Tcl_FreeInternalRepProc *) NULL,   /* freeIntRepProc */
+    DupIntInternalRep,		        /* dupIntRepProc */
+    UpdateStringOfInt,			/* updateStringProc */
+    SetIntFromAny			/* setFromAnyProc */
+};
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * InitTypeTable --
+ *
+ *	This procedure is invoked to perform once-only initialization of
+ *	the type table. It also registers the object types defined in 
+ *	this file.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Initializes the table of defined object types "typeTable" with
+ *	builtin object types defined in this file. It also initializes the
+ *	value of tclEmptyStringRep, which points to the heap-allocated
+ *	string of length zero used as the string representation for
+ *	newly-created objects.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+InitTypeTable()
+{
+    typeTableInitialized = 1;
+
+    Tcl_InitHashTable(&typeTable, TCL_STRING_KEYS);
+    Tcl_RegisterObjType(&tclBooleanType);
+    Tcl_RegisterObjType(&tclDoubleType);
+    Tcl_RegisterObjType(&tclIntType);
+    Tcl_RegisterObjType(&tclStringType);
+    Tcl_RegisterObjType(&tclListType);
+    Tcl_RegisterObjType(&tclByteCodeType);
+    Tcl_RegisterObjType(&tclProcBodyType);
+
+    tclEmptyStringRep = (char *) ckalloc((unsigned) 1);
+    tclEmptyStringRep[0] = '\0';
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FinalizeTypeTable --
+ *
+ *	This procedure is called by Tcl_Finalize after all exit handlers
+ *	have been run to free up storage associated with the table of Tcl
+ *	object types.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Deletes all entries in the hash table of object types, "typeTable".
+ *	Then sets "typeTableInitialized" to 0 so that the Tcl type system
+ *	will be properly reinitialized if Tcl is restarted. Also deallocates
+ *	the storage for tclEmptyStringRep.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FinalizeTypeTable()
+{
+    if (typeTableInitialized) {
+        Tcl_DeleteHashTable(&typeTable);
+	ckfree(tclEmptyStringRep);
+        typeTableInitialized = 0;
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FinalizeFreeObjList --
+ *
+ *	Resets the free object list so it can later be reinitialized.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Resets the value of tclFreeObjList.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FinalizeFreeObjList()
+{
+    tclFreeObjList = NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFinalizeCompExecEnv --
+ *
+ *	Clean up the compiler execution environment so it can later be
+ *	properly reinitialized.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Cleans up the execution environment
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclFinalizeCompExecEnv()
+{
+    FinalizeTypeTable();
+    FinalizeFreeObjList();
+    TclFinalizeExecEnv();
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tcl_RegisterObjType --
+ *
+ *	This procedure is called to register a new Tcl object type
+ *	in the table of all object types supported by Tcl.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The type is registered in the Tcl type table. If there was already
+ *	a type with the same name as in typePtr, it is replaced with the
+ *	new type.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tcl_RegisterObjType(typePtr)
+    Tcl_ObjType *typePtr;	/* Information about object type;
+				 * storage must be statically
+				 * allocated (must live forever). */
+{
+    register Tcl_HashEntry *hPtr;
+    int new;
+
+    if (!typeTableInitialized) {
+	InitTypeTable();
+    }
+
+    /*
+     * If there's already an object type with the given name, remove it.
+     */
+
+    hPtr = Tcl_FindHashEntry(&typeTable, typePtr->name);
+    if (hPtr != (Tcl_HashEntry *) NULL) {
+        Tcl_DeleteHashEntry(hPtr);
+    }
+
+    /*
+     * Now insert the new object type.
+     */
+
+    hPtr = Tcl_CreateHashEntry(&typeTable, typePtr->name, &new);
+    if (new) {
+	Tcl_SetHashValue(hPtr, typePtr);
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AppendAllObjTypes --
+ *
+ *	This procedure appends onto the argument object the name of each
+ *	object type as a list element. This includes the builtin object
+ *	types (e.g. int, list) as well as those added using
+ *	Tcl_CreateObjType. These names can be used, for example, with
+ *	Tcl_GetObjType to get pointers to the corresponding Tcl_ObjType
+ *	structures.
+ *
+ * Results:
+ *	The return value is normally TCL_OK; in this case the object
+ *	referenced by objPtr has each type name appended to it. If an
+ *	error occurs, TCL_ERROR is returned and the interpreter's result
+ *	holds an error message.
+ *
+ * Side effects:
+ *	If necessary, the object referenced by objPtr is converted into
+ *	a list object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_AppendAllObjTypes(interp, objPtr)
+    Tcl_Interp *interp;		/* Interpreter used for error reporting. */
+    Tcl_Obj *objPtr;		/* Points to the Tcl object onto which the
+				 * name of each registered type is appended
+				 * as a list element. */
+{
+    register Tcl_HashEntry *hPtr;
+    Tcl_HashSearch search;
+    Tcl_ObjType *typePtr;
+    int result;
+ 
+    if (!typeTableInitialized) {
+	InitTypeTable();
+    }
+
+    /*
+     * This code assumes that types names do not contain embedded NULLs.
+     */
+
+    for (hPtr = Tcl_FirstHashEntry(&typeTable, &search);
+	    hPtr != NULL;  hPtr = Tcl_NextHashEntry(&search)) {
+        typePtr = (Tcl_ObjType *) Tcl_GetHashValue(hPtr);
+	result = Tcl_ListObjAppendElement(interp, objPtr,
+	        Tcl_NewStringObj(typePtr->name, -1));
+	if (result == TCL_ERROR) {
+	    return result;
+	}
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetObjType --
+ *
+ *	This procedure looks up an object type by name.
+ *
+ * Results:
+ *	If an object type with name matching "typeName" is found, a pointer
+ *	to its Tcl_ObjType structure is returned; otherwise, NULL is
+ *	returned.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_ObjType *
+Tcl_GetObjType(typeName)
+    char *typeName;		/* Name of Tcl object type to look up. */
+{
+    register Tcl_HashEntry *hPtr;
+    Tcl_ObjType *typePtr;
+
+    if (!typeTableInitialized) {
+	InitTypeTable();
+    }
+
+    hPtr = Tcl_FindHashEntry(&typeTable, typeName);
+    if (hPtr != (Tcl_HashEntry *) NULL) {
+        typePtr = (Tcl_ObjType *) Tcl_GetHashValue(hPtr);
+	return typePtr;
+    }
+    return NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ConvertToType --
+ *
+ *	Convert the Tcl object "objPtr" to have type "typePtr" if possible.
+ *
+ * Results:
+ *	The return value is TCL_OK on success and TCL_ERROR on failure. If
+ *	TCL_ERROR is returned, then the interpreter's result contains an
+ *	error message unless "interp" is NULL. Passing a NULL "interp"
+ *	allows this procedure to be used as a test whether the conversion
+ *	could be done (and in fact was done).
+ *
+ * Side effects:
+ *	Any internal representation for the old type is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_ConvertToType(interp, objPtr, typePtr)
+    Tcl_Interp *interp;		/* Used for error reporting if not NULL. */
+    Tcl_Obj *objPtr;		/* The object to convert. */
+    Tcl_ObjType *typePtr;	/* The target type. */
+{
+    if (objPtr->typePtr == typePtr) {
+	return TCL_OK;
+    }
+
+    /*
+     * Use the target type's Tcl_SetFromAnyProc to set "objPtr"s internal
+     * form as appropriate for the target type. This frees the old internal
+     * representation.
+     */
+
+    return typePtr->setFromAnyProc(interp, objPtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_NewObj --
+ *
+ *	This procedure is normally called when not debugging: i.e., when
+ *	TCL_MEM_DEBUG is not defined. It creates new Tcl objects that denote
+ *	the empty string. These objects have a NULL object type and NULL
+ *	string representation byte pointer. Type managers call this routine
+ *	to allocate new objects that they further initialize.
+ *
+ *	When TCL_MEM_DEBUG is defined, this procedure just returns the
+ *	result of calling the debugging version Tcl_DbNewObj.
+ *
+ * Results:
+ *	The result is a newly allocated object that represents the empty
+ *	string. The new object's typePtr is set NULL and its ref count
+ *	is set to 0.
+ *
+ * Side effects:
+ *	If compiling with TCL_COMPILE_STATS, this procedure increments
+ *	the global count of allocated objects (tclObjsAlloced).
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_MEM_DEBUG
+#undef Tcl_NewObj
+
+Tcl_Obj *
+Tcl_NewObj()
+{
+    return Tcl_DbNewObj("unknown", 0);
+}
+
+#else /* if not TCL_MEM_DEBUG */
+
+Tcl_Obj *
+Tcl_NewObj()
+{
+    register Tcl_Obj *objPtr;
+
+    /*
+     * Allocate the object using the list of free Tcl_Objs we maintain.
+     */
+
+    if (tclFreeObjList == NULL) {
+	TclAllocateFreeObjects();
+    }
+    objPtr = tclFreeObjList;
+    tclFreeObjList = (Tcl_Obj *) tclFreeObjList->internalRep.otherValuePtr;
+    
+    objPtr->refCount = 0;
+    objPtr->bytes    = tclEmptyStringRep;
+    objPtr->length   = 0;
+    objPtr->typePtr  = NULL;
+#ifdef TCL_COMPILE_STATS
+    tclObjsAlloced++;
+#endif /* TCL_COMPILE_STATS */
+    return objPtr;
+}
+#endif /* TCL_MEM_DEBUG */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DbNewObj --
+ *
+ *	This procedure is normally called when debugging: i.e., when
+ *	TCL_MEM_DEBUG is defined. It creates new Tcl objects that denote the
+ *	empty string. It is the same as the Tcl_NewObj procedure above
+ *	except that it calls Tcl_DbCkalloc directly with the file name and
+ *	line number from its caller. This simplifies debugging since then
+ *	the checkmem command will report the correct file name and line
+ *	number when reporting objects that haven't been freed.
+ *
+ *	When TCL_MEM_DEBUG is not defined, this procedure just returns the
+ *	result of calling Tcl_NewObj.
+ *
+ * Results:
+ *	The result is a newly allocated that represents the empty string.
+ *	The new object's typePtr is set NULL and its ref count is set to 0.
+ *
+ * Side effects:
+ *	If compiling with TCL_COMPILE_STATS, this procedure increments
+ *	the global count of allocated objects (tclObjsAlloced).
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_MEM_DEBUG
+
+Tcl_Obj *
+Tcl_DbNewObj(file, line)
+    register char *file;	/* The name of the source file calling this
+				 * procedure; used for debugging. */
+    register int line;		/* Line number in the source file; used
+				 * for debugging. */
+{
+    register Tcl_Obj *objPtr;
+
+    /*
+     * If debugging Tcl's memory usage, allocate the object using ckalloc.
+     * Otherwise, allocate it using the list of free Tcl_Objs we maintain.
+     */
+
+    objPtr = (Tcl_Obj *) Tcl_DbCkalloc(sizeof(Tcl_Obj), file, line);
+    objPtr->refCount = 0;
+    objPtr->bytes    = tclEmptyStringRep;
+    objPtr->length   = 0;
+    objPtr->typePtr  = NULL;
+#ifdef TCL_COMPILE_STATS
+    tclObjsAlloced++;
+#endif /* TCL_COMPILE_STATS */
+    return objPtr;
+}
+
+#else /* if not TCL_MEM_DEBUG */
+
+Tcl_Obj *
+Tcl_DbNewObj(file, line)
+    char *file;			/* The name of the source file calling this
+				 * procedure; used for debugging. */
+    int line;			/* Line number in the source file; used
+				 * for debugging. */
+{
+    return Tcl_NewObj();
+}
+#endif /* TCL_MEM_DEBUG */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclAllocateFreeObjects --
+ *
+ *	Procedure to allocate a number of free Tcl_Objs. This is done using
+ *	a single ckalloc to reduce the overhead for Tcl_Obj allocation.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	tclFreeObjList, the head of the list of free Tcl_Objs, is set to the
+ *	first of a number of free Tcl_Obj's linked together by their
+ *	internalRep.otherValuePtrs.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#define OBJS_TO_ALLOC_EACH_TIME 100
+
+void
+TclAllocateFreeObjects()
+{
+    Tcl_Obj tmp[2];
+    size_t objSizePlusPadding =	/* NB: this assumes byte addressing. */
+	((int)(&(tmp[1])) - (int)(&(tmp[0])));
+    size_t bytesToAlloc = (OBJS_TO_ALLOC_EACH_TIME * objSizePlusPadding);
+    char *basePtr;
+    register Tcl_Obj *prevPtr, *objPtr;
+    register int i;
+
+    basePtr = (char *) ckalloc(bytesToAlloc);
+    memset(basePtr, 0, bytesToAlloc);
+
+    prevPtr = NULL;
+    objPtr = (Tcl_Obj *) basePtr;
+    for (i = 0;  i < OBJS_TO_ALLOC_EACH_TIME;  i++) {
+	objPtr->internalRep.otherValuePtr = (VOID *) prevPtr;
+	prevPtr = objPtr;
+	objPtr = (Tcl_Obj *) (((char *)objPtr) + objSizePlusPadding);
+    }
+    tclFreeObjList = prevPtr;
+}
+#undef OBJS_TO_ALLOC_EACH_TIME
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFreeObj --
+ *
+ *	This procedure frees the memory associated with the argument
+ *	object. It is called by the tcl.h macro Tcl_DecrRefCount when an
+ *	object's ref count is zero. It is only "public" since it must
+ *	be callable by that macro wherever the macro is used. It should not
+ *	be directly called by clients.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Deallocates the storage for the object's Tcl_Obj structure
+ *	after deallocating the string representation and calling the
+ *	type-specific Tcl_FreeInternalRepProc to deallocate the object's
+ *	internal representation. If compiling with TCL_COMPILE_STATS,
+ *	this procedure increments the global count of freed objects
+ *	(tclObjsFreed).
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclFreeObj(objPtr)
+    register Tcl_Obj *objPtr;	/* The object to be freed. */
+{
+    register Tcl_ObjType *typePtr = objPtr->typePtr;
+    
+#ifdef TCL_MEM_DEBUG
+    if ((objPtr)->refCount < -1) {
+	panic("Reference count for %lx was negative", objPtr);
+    }
+#endif /* TCL_MEM_DEBUG */
+
+    Tcl_InvalidateStringRep(objPtr);
+    if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+	typePtr->freeIntRepProc(objPtr);
+    }
+
+    /*
+     * If debugging Tcl's memory usage, deallocate the object using ckfree.
+     * Otherwise, deallocate it by adding it onto the list of free
+     * Tcl_Objs we maintain.
+     */
+    
+#ifdef TCL_MEM_DEBUG
+    ckfree((char *) objPtr);
+#else
+    objPtr->internalRep.otherValuePtr = (VOID *) tclFreeObjList;
+    tclFreeObjList = objPtr;
+#endif /* TCL_MEM_DEBUG */
+
+#ifdef TCL_COMPILE_STATS    
+    tclObjsFreed++;
+#endif /* TCL_COMPILE_STATS */    
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DuplicateObj --
+ *
+ *	Create and return a new object that is a duplicate of the argument
+ *	object.
+ *
+ * Results:
+ *	The return value is a pointer to a newly created Tcl_Obj. This
+ *	object has reference count 0 and the same type, if any, as the
+ *	source object objPtr. Also:
+ *	  1) If the source object has a valid string rep, we copy it;
+ *	     otherwise, the duplicate's string rep is set NULL to mark
+ *	     it invalid.
+ *	  2) If the source object has an internal representation (i.e. its
+ *	     typePtr is non-NULL), the new object's internal rep is set to
+ *	     a copy; otherwise the new internal rep is marked invalid.
+ *
+ * Side effects:
+ *      What constitutes "copying" the internal representation depends on
+ *	the type. For example, if the argument object is a list,
+ *	the element objects it points to will not actually be copied but
+ *	will be shared with the duplicate list. That is, the ref counts of
+ *	the element objects will be incremented.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_DuplicateObj(objPtr)
+    register Tcl_Obj *objPtr;		/* The object to duplicate. */
+{
+    register Tcl_ObjType *typePtr = objPtr->typePtr;
+    register Tcl_Obj *dupPtr;
+
+    TclNewObj(dupPtr);
+
+    if (objPtr->bytes == NULL) {
+	dupPtr->bytes = NULL;
+    } else if (objPtr->bytes != tclEmptyStringRep) {
+	int len = objPtr->length;
+	
+	dupPtr->bytes = (char *) ckalloc((unsigned) len+1);
+	if (len > 0) {
+	    memcpy((VOID *) dupPtr->bytes, (VOID *) objPtr->bytes,
+		   (unsigned) len);
+	}
+	dupPtr->bytes[len] = '\0';
+	dupPtr->length = len;
+    }
+    
+    if (typePtr != NULL) {
+	typePtr->dupIntRepProc(objPtr, dupPtr);
+    }
+    return dupPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetStringFromObj --
+ *
+ *	Returns the string representation's byte array pointer and length
+ *	for an object.
+ *
+ * Results:
+ *	Returns a pointer to the string representation of objPtr. If
+ *	lengthPtr isn't NULL, the length of the string representation is
+ *	stored at *lengthPtr. The byte array referenced by the returned
+ *	pointer must not be modified by the caller. Furthermore, the
+ *	caller must copy the bytes if they need to retain them since the
+ *	object's string rep can change as a result of other operations.
+ *
+ * Side effects:
+ *	May call the object's updateStringProc to update the string
+ *	representation from the internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_GetStringFromObj(objPtr, lengthPtr)
+    register Tcl_Obj *objPtr;	/* Object whose string rep byte pointer
+				 * should be returned. */
+    register int *lengthPtr;	/* If non-NULL, the location where the
+				 * string rep's byte array length should be
+				 * stored. If NULL, no length is stored. */
+{
+    if (objPtr->bytes != NULL) {
+	if (lengthPtr != NULL) {
+	    *lengthPtr = objPtr->length;
+	}
+	return objPtr->bytes;
+    }
+
+    objPtr->typePtr->updateStringProc(objPtr);
+    if (lengthPtr != NULL) {
+	*lengthPtr = objPtr->length;
+    }
+    return objPtr->bytes;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_InvalidateStringRep --
+ *
+ *	This procedure is called to invalidate an object's string
+ *	representation. 
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Deallocates the storage for any old string representation, then
+ *	sets the string representation NULL to mark it invalid.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_InvalidateStringRep(objPtr)
+     register Tcl_Obj *objPtr;	/* Object whose string rep byte pointer
+				 * should be freed. */
+{
+    if (objPtr->bytes != NULL) {
+	if (objPtr->bytes != tclEmptyStringRep) {
+	    ckfree((char *) objPtr->bytes);
+	}
+	objPtr->bytes = NULL;
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_NewBooleanObj --
+ *
+ *	This procedure is normally called when not debugging: i.e., when
+ *	TCL_MEM_DEBUG is not defined. It creates a new boolean object and
+ *	initializes it from the argument boolean value. A nonzero
+ *	"boolValue" is coerced to 1.
+ *
+ *	When TCL_MEM_DEBUG is defined, this procedure just returns the
+ *	result of calling the debugging version Tcl_DbNewBooleanObj.
+ *
+ * Results:
+ *	The newly created object is returned. This object will have an
+ *	invalid string representation. The returned object has ref count 0.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_MEM_DEBUG
+#undef Tcl_NewBooleanObj
+
+Tcl_Obj *
+Tcl_NewBooleanObj(boolValue)
+    register int boolValue;	/* Boolean used to initialize new object. */
+{
+    return Tcl_DbNewBooleanObj(boolValue, "unknown", 0);
+}
+
+#else /* if not TCL_MEM_DEBUG */
+
+Tcl_Obj *
+Tcl_NewBooleanObj(boolValue)
+    register int boolValue;	/* Boolean used to initialize new object. */
+{
+    register Tcl_Obj *objPtr;
+
+    TclNewObj(objPtr);
+    objPtr->bytes = NULL;
+    
+    objPtr->internalRep.longValue = (boolValue? 1 : 0);
+    objPtr->typePtr = &tclBooleanType;
+    return objPtr;
+}
+#endif /* TCL_MEM_DEBUG */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DbNewBooleanObj --
+ *
+ *	This procedure is normally called when debugging: i.e., when
+ *	TCL_MEM_DEBUG is defined. It creates new boolean objects. It is the
+ *	same as the Tcl_NewBooleanObj procedure above except that it calls
+ *	Tcl_DbCkalloc directly with the file name and line number from its
+ *	caller. This simplifies debugging since then the checkmem command
+ *	will report the correct file name and line number when reporting
+ *	objects that haven't been freed.
+ *
+ *	When TCL_MEM_DEBUG is not defined, this procedure just returns the
+ *	result of calling Tcl_NewBooleanObj.
+ *
+ * Results:
+ *	The newly created object is returned. This object will have an
+ *	invalid string representation. The returned object has ref count 0.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_MEM_DEBUG
+
+Tcl_Obj *
+Tcl_DbNewBooleanObj(boolValue, file, line)
+    register int boolValue;	/* Boolean used to initialize new object. */
+    char *file;			/* The name of the source file calling this
+				 * procedure; used for debugging. */
+    int line;			/* Line number in the source file; used
+				 * for debugging. */
+{
+    register Tcl_Obj *objPtr;
+
+    TclDbNewObj(objPtr, file, line);
+    objPtr->bytes = NULL;
+    
+    objPtr->internalRep.longValue = (boolValue? 1 : 0);
+    objPtr->typePtr = &tclBooleanType;
+    return objPtr;
+}
+
+#else /* if not TCL_MEM_DEBUG */
+
+Tcl_Obj *
+Tcl_DbNewBooleanObj(boolValue, file, line)
+    register int boolValue;	/* Boolean used to initialize new object. */
+    char *file;			/* The name of the source file calling this
+				 * procedure; used for debugging. */
+    int line;			/* Line number in the source file; used
+				 * for debugging. */
+{
+    return Tcl_NewBooleanObj(boolValue);
+}
+#endif /* TCL_MEM_DEBUG */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetBooleanObj --
+ *
+ *	Modify an object to be a boolean object and to have the specified
+ *	boolean value. A nonzero "boolValue" is coerced to 1.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The object's old string rep, if any, is freed. Also, any old
+ *	internal rep is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetBooleanObj(objPtr, boolValue)
+    register Tcl_Obj *objPtr;	/* Object whose internal rep to init. */
+    register int boolValue;	/* Boolean used to set object's value. */
+{
+    register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
+
+    if (Tcl_IsShared(objPtr)) {
+	panic("Tcl_SetBooleanObj called with shared object");
+    }
+    
+    Tcl_InvalidateStringRep(objPtr);
+    if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
+	oldTypePtr->freeIntRepProc(objPtr);
+    }
+    
+    objPtr->internalRep.longValue = (boolValue? 1 : 0);
+    objPtr->typePtr = &tclBooleanType;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetBooleanFromObj --
+ *
+ *	Attempt to return a boolean from the Tcl object "objPtr". If the
+ *	object is not already a boolean, an attempt will be made to convert
+ *	it to one.
+ *
+ * Results:
+ *	The return value is a standard Tcl object result. If an error occurs
+ *	during conversion, an error message is left in the interpreter's
+ *	result unless "interp" is NULL.
+ *
+ * Side effects:
+ *	If the object is not already a boolean, the conversion will free
+ *	any old internal representation. 
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetBooleanFromObj(interp, objPtr, boolPtr)
+    Tcl_Interp *interp; 	/* Used for error reporting if not NULL. */
+    register Tcl_Obj *objPtr;	/* The object from which to get boolean. */
+    register int *boolPtr;	/* Place to store resulting boolean. */
+{
+    register int result;
+
+    result = SetBooleanFromAny(interp, objPtr);
+    if (result == TCL_OK) {
+	*boolPtr = (int) objPtr->internalRep.longValue;
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupBooleanInternalRep --
+ *
+ *	Initialize the internal representation of a boolean Tcl_Obj to a
+ *	copy of the internal representation of an existing boolean object. 
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	"copyPtr"s internal rep is set to the boolean (an integer)
+ *	corresponding to "srcPtr"s internal rep.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DupBooleanInternalRep(srcPtr, copyPtr)
+    register Tcl_Obj *srcPtr;	/* Object with internal rep to copy. */
+    register Tcl_Obj *copyPtr;	/* Object with internal rep to set. */
+{
+    copyPtr->internalRep.longValue = srcPtr->internalRep.longValue;
+    copyPtr->typePtr = &tclBooleanType;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetBooleanFromAny --
+ *
+ *	Attempt to generate a boolean internal form for the Tcl object
+ *	"objPtr".
+ *
+ * Results:
+ *	The return value is a standard Tcl result. If an error occurs during
+ *	conversion, an error message is left in the interpreter's result
+ *	unless "interp" is NULL.
+ *
+ * Side effects:
+ *	If no error occurs, an integer 1 or 0 is stored as "objPtr"s
+ *	internal representation and the type of "objPtr" is set to boolean.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetBooleanFromAny(interp, objPtr)
+    Tcl_Interp *interp;		/* Used for error reporting if not NULL. */
+    register Tcl_Obj *objPtr;	/* The object to convert. */
+{
+    Tcl_ObjType *oldTypePtr = objPtr->typePtr;
+    char *string, *end;
+    register char c;
+    char lowerCase[10];
+    int newBool, length;
+    register int i;
+    double dbl;
+
+    /*
+     * Get the string representation. Make it up-to-date if necessary.
+     */
+
+    string = TclGetStringFromObj(objPtr, &length);
+
+    /*
+     * Copy the string converting its characters to lower case.
+     */
+
+    for (i = 0;  (i < 9) && (i < length);  i++) {
+	c = string[i];
+	if (isupper(UCHAR(c))) {
+	    c = (char) tolower(UCHAR(c));
+	}
+	lowerCase[i] = c;
+    }
+    lowerCase[i] = 0;
+
+    /*
+     * Parse the string as a boolean. We use an implementation here that
+     * doesn't report errors in interp if interp is NULL.
+     */
+
+    c = lowerCase[0];
+    if ((c == '0') && (lowerCase[1] == '\0')) {
+	newBool = 0;
+    } else if ((c == '1') && (lowerCase[1] == '\0')) {
+	newBool = 1;
+    } else if ((c == 'y') && (strncmp(lowerCase, "yes", (size_t) length) == 0)) {
+	newBool = 1;
+    } else if ((c == 'n') && (strncmp(lowerCase, "no", (size_t) length) == 0)) {
+	newBool = 0;
+    } else if ((c == 't') && (strncmp(lowerCase, "true", (size_t) length) == 0)) {
+	newBool = 1;
+    } else if ((c == 'f') && (strncmp(lowerCase, "false", (size_t) length) == 0)) {
+	newBool = 0;
+    } else if ((c == 'o') && (length >= 2)) {
+	if (strncmp(lowerCase, "on", (size_t) length) == 0) {
+	    newBool = 1;
+	} else if (strncmp(lowerCase, "off", (size_t) length) == 0) {
+	    newBool = 0;
+	} else {
+	    goto badBoolean;
+	}
+    } else {
+        /*
+         * Still might be a string containing the characters representing an
+         * int or double that wasn't handled above. This would be a string
+         * like "27" or "1.0" that is non-zero and not "1". Such a string
+         * whould result in the boolean value true. We try converting to
+         * double. If that succeeds and the resulting double is non-zero, we
+         * have a "true". Note that numbers can't have embedded NULLs.
+	 */
+
+	dbl = strtod(string, &end);
+	if (end == string) {
+	    goto badBoolean;
+	}
+
+	/*
+	 * Make sure the string has no garbage after the end of the double.
+	 */
+	
+	while ((end < (string+length)) && isspace(UCHAR(*end))) {
+	    end++;
+	}
+	if (end != (string+length)) {
+	    goto badBoolean;
+	}
+	newBool = (dbl != 0.0);
+    }
+
+    /*
+     * Free the old internalRep before setting the new one. We do this as
+     * late as possible to allow the conversion code, in particular
+     * Tcl_GetStringFromObj, to use that old internalRep.
+     */
+
+    if ((oldTypePtr != NULL) &&	(oldTypePtr->freeIntRepProc != NULL)) {
+	oldTypePtr->freeIntRepProc(objPtr);
+    }
+
+    objPtr->internalRep.longValue = newBool;
+    objPtr->typePtr = &tclBooleanType;
+    return TCL_OK;
+
+    badBoolean:
+    if (interp != NULL) {
+	/*
+	 * Must copy string before resetting the result in case a caller
+	 * is trying to convert the interpreter's result to a boolean.
+	 */
+	
+	char buf[100];
+	sprintf(buf, "expected boolean value but got \"%.50s\"", string);
+	Tcl_ResetResult(interp);
+	Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
+    }
+    return TCL_ERROR;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateStringOfBoolean --
+ *
+ *	Update the string representation for a boolean object.
+ *	Note: This procedure does not free an existing old string rep
+ *	so storage will be lost if this has not already been done. 
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The object's string is set to a valid string that results from
+ *	the boolean-to-string conversion.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateStringOfBoolean(objPtr)
+    register Tcl_Obj *objPtr;	/* Int object whose string rep to update. */
+{
+    char *s = ckalloc((unsigned) 2);
+    
+    s[0] = (char) (objPtr->internalRep.longValue? '1' : '0');
+    s[1] = '\0';
+    objPtr->bytes = s;
+    objPtr->length = 1;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_NewDoubleObj --
+ *
+ *	This procedure is normally called when not debugging: i.e., when
+ *	TCL_MEM_DEBUG is not defined. It creates a new double object and
+ *	initializes it from the argument double value.
+ *
+ *	When TCL_MEM_DEBUG is defined, this procedure just returns the
+ *	result of calling the debugging version Tcl_DbNewDoubleObj.
+ *
+ * Results:
+ *	The newly created object is returned. This object will have an
+ *	invalid string representation. The returned object has ref count 0.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_MEM_DEBUG
+#undef Tcl_NewDoubleObj
+
+Tcl_Obj *
+Tcl_NewDoubleObj(dblValue)
+    register double dblValue;	/* Double used to initialize the object. */
+{
+    return Tcl_DbNewDoubleObj(dblValue, "unknown", 0);
+}
+
+#else /* if not TCL_MEM_DEBUG */
+
+Tcl_Obj *
+Tcl_NewDoubleObj(dblValue)
+    register double dblValue;	/* Double used to initialize the object. */
+{
+    register Tcl_Obj *objPtr;
+
+    TclNewObj(objPtr);
+    objPtr->bytes = NULL;
+    
+    objPtr->internalRep.doubleValue = dblValue;
+    objPtr->typePtr = &tclDoubleType;
+    return objPtr;
+}
+#endif /* if TCL_MEM_DEBUG */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DbNewDoubleObj --
+ *
+ *	This procedure is normally called when debugging: i.e., when
+ *	TCL_MEM_DEBUG is defined. It creates new double objects. It is the
+ *	same as the Tcl_NewDoubleObj procedure above except that it calls
+ *	Tcl_DbCkalloc directly with the file name and line number from its
+ *	caller. This simplifies debugging since then the checkmem command
+ *	will report the correct file name and line number when reporting
+ *	objects that haven't been freed.
+ *
+ *	When TCL_MEM_DEBUG is not defined, this procedure just returns the
+ *	result of calling Tcl_NewDoubleObj.
+ *
+ * Results:
+ *	The newly created object is returned. This object will have an
+ *	invalid string representation. The returned object has ref count 0.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_MEM_DEBUG
+
+Tcl_Obj *
+Tcl_DbNewDoubleObj(dblValue, file, line)
+    register double dblValue;	/* Double used to initialize the object. */
+    char *file;			/* The name of the source file calling this
+				 * procedure; used for debugging. */
+    int line;			/* Line number in the source file; used
+				 * for debugging. */
+{
+    register Tcl_Obj *objPtr;
+
+    TclDbNewObj(objPtr, file, line);
+    objPtr->bytes = NULL;
+    
+    objPtr->internalRep.doubleValue = dblValue;
+    objPtr->typePtr = &tclDoubleType;
+    return objPtr;
+}
+
+#else /* if not TCL_MEM_DEBUG */
+
+Tcl_Obj *
+Tcl_DbNewDoubleObj(dblValue, file, line)
+    register double dblValue;	/* Double used to initialize the object. */
+    char *file;			/* The name of the source file calling this
+				 * procedure; used for debugging. */
+    int line;			/* Line number in the source file; used
+				 * for debugging. */
+{
+    return Tcl_NewDoubleObj(dblValue);
+}
+#endif /* TCL_MEM_DEBUG */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetDoubleObj --
+ *
+ *	Modify an object to be a double object and to have the specified
+ *	double value.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The object's old string rep, if any, is freed. Also, any old
+ *	internal rep is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetDoubleObj(objPtr, dblValue)
+    register Tcl_Obj *objPtr;	/* Object whose internal rep to init. */
+    register double dblValue;	/* Double used to set the object's value. */
+{
+    register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
+
+    if (Tcl_IsShared(objPtr)) {
+	panic("Tcl_SetDoubleObj called with shared object");
+    }
+
+    Tcl_InvalidateStringRep(objPtr);
+    if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
+	oldTypePtr->freeIntRepProc(objPtr);
+    }
+    
+    objPtr->internalRep.doubleValue = dblValue;
+    objPtr->typePtr = &tclDoubleType;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetDoubleFromObj --
+ *
+ *	Attempt to return a double from the Tcl object "objPtr". If the
+ *	object is not already a double, an attempt will be made to convert
+ *	it to one.
+ *
+ * Results:
+ *	The return value is a standard Tcl object result. If an error occurs
+ *	during conversion, an error message is left in the interpreter's
+ *	result unless "interp" is NULL.
+ *
+ * Side effects:
+ *	If the object is not already a double, the conversion will free
+ *	any old internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetDoubleFromObj(interp, objPtr, dblPtr)
+    Tcl_Interp *interp; 	/* Used for error reporting if not NULL. */
+    register Tcl_Obj *objPtr;	/* The object from which to get a double. */
+    register double *dblPtr;	/* Place to store resulting double. */
+{
+    register int result;
+    
+    if (objPtr->typePtr == &tclDoubleType) {
+	*dblPtr = objPtr->internalRep.doubleValue;
+	return TCL_OK;
+    }
+
+    result = SetDoubleFromAny(interp, objPtr);
+    if (result == TCL_OK) {
+	*dblPtr = objPtr->internalRep.doubleValue;
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupDoubleInternalRep --
+ *
+ *	Initialize the internal representation of a double Tcl_Obj to a
+ *	copy of the internal representation of an existing double object. 
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	"copyPtr"s internal rep is set to the double precision floating 
+ *	point number corresponding to "srcPtr"s internal rep.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DupDoubleInternalRep(srcPtr, copyPtr)
+    register Tcl_Obj *srcPtr;	/* Object with internal rep to copy. */
+    register Tcl_Obj *copyPtr;	/* Object with internal rep to set. */
+{
+    copyPtr->internalRep.doubleValue = srcPtr->internalRep.doubleValue;
+    copyPtr->typePtr = &tclDoubleType;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetDoubleFromAny --
+ *
+ *	Attempt to generate an double-precision floating point internal form
+ *	for the Tcl object "objPtr".
+ *
+ * Results:
+ *	The return value is a standard Tcl object result. If an error occurs
+ *	during conversion, an error message is left in the interpreter's
+ *	result unless "interp" is NULL.
+ *
+ * Side effects:
+ *	If no error occurs, a double is stored as "objPtr"s internal
+ *	representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetDoubleFromAny(interp, objPtr)
+    Tcl_Interp *interp;		/* Used for error reporting if not NULL. */
+    register Tcl_Obj *objPtr;	/* The object to convert. */
+{
+    Tcl_ObjType *oldTypePtr = objPtr->typePtr;
+    char *string, *end;
+    double newDouble;
+    int length;
+
+    /*
+     * Get the string representation. Make it up-to-date if necessary.
+     */
+
+    string = TclGetStringFromObj(objPtr, &length);
+
+    /*
+     * Now parse "objPtr"s string as an double. Numbers can't have embedded
+     * NULLs. We use an implementation here that doesn't report errors in
+     * interp if interp is NULL.
+     */
+
+    errno = 0;
+    newDouble = strtod(string, &end);
+    if (end == string) {
+	badDouble:
+	if (interp != NULL) {
+	    /*
+	     * Must copy string before resetting the result in case a caller
+	     * is trying to convert the interpreter's result to an int.
+	     */
+	    
+	    char buf[100];
+	    sprintf(buf, "expected floating-point number but got \"%.50s\"",
+	            string);
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
+	}
+	return TCL_ERROR;
+    }
+    if (errno != 0) {
+	if (interp != NULL) {
+	    TclExprFloatError(interp, newDouble);
+	}
+	return TCL_ERROR;
+    }
+
+    /*
+     * Make sure that the string has no garbage after the end of the double.
+     */
+    
+    while ((end < (string+length)) && isspace(UCHAR(*end))) {
+	end++;
+    }
+    if (end != (string+length)) {
+	goto badDouble;
+    }
+    
+    /*
+     * The conversion to double succeeded. Free the old internalRep before
+     * setting the new one. We do this as late as possible to allow the
+     * conversion code, in particular Tcl_GetStringFromObj, to use that old
+     * internalRep.
+     */
+    
+    if ((oldTypePtr != NULL) &&	(oldTypePtr->freeIntRepProc != NULL)) {
+	oldTypePtr->freeIntRepProc(objPtr);
+    }
+
+    objPtr->internalRep.doubleValue = newDouble;
+    objPtr->typePtr = &tclDoubleType;
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateStringOfDouble --
+ *
+ *	Update the string representation for a double-precision floating
+ *	point object. This must obey the current tcl_precision value for
+ *	double-to-string conversions. Note: This procedure does not free an
+ *	existing old string rep so storage will be lost if this has not
+ *	already been done.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The object's string is set to a valid string that results from
+ *	the double-to-string conversion.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateStringOfDouble(objPtr)
+    register Tcl_Obj *objPtr;	/* Double obj with string rep to update. */
+{
+    char buffer[TCL_DOUBLE_SPACE];
+    register int len;
+    
+    Tcl_PrintDouble((Tcl_Interp *) NULL, objPtr->internalRep.doubleValue,
+	    buffer);
+    len = strlen(buffer);
+    
+    objPtr->bytes = (char *) ckalloc((unsigned) len + 1);
+    strcpy(objPtr->bytes, buffer);
+    objPtr->length = len;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_NewIntObj --
+ *
+ *	If a client is compiled with TCL_MEM_DEBUG defined, calls to
+ *	Tcl_NewIntObj to create a new integer object end up calling the
+ *	debugging procedure Tcl_DbNewLongObj instead.
+ *
+ *	Otherwise, if the client is compiled without TCL_MEM_DEBUG defined,
+ *	calls to Tcl_NewIntObj result in a call to one of the two
+ *	Tcl_NewIntObj implementations below. We provide two implementations
+ *	so that the Tcl core can be compiled to do memory debugging of the 
+ *	core even if a client does not request it for itself.
+ *
+ *	Integer and long integer objects share the same "integer" type
+ *	implementation. We store all integers as longs and Tcl_GetIntFromObj
+ *	checks whether the current value of the long can be represented by
+ *	an int.
+ *
+ * Results:
+ *	The newly created object is returned. This object will have an
+ *	invalid string representation. The returned object has ref count 0.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_MEM_DEBUG
+#undef Tcl_NewIntObj
+
+Tcl_Obj *
+Tcl_NewIntObj(intValue)
+    register int intValue;	/* Int used to initialize the new object. */
+{
+    return Tcl_DbNewLongObj((long)intValue, "unknown", 0);
+}
+
+#else /* if not TCL_MEM_DEBUG */
+
+Tcl_Obj *
+Tcl_NewIntObj(intValue)
+    register int intValue;	/* Int used to initialize the new object. */
+{
+    register Tcl_Obj *objPtr;
+
+    TclNewObj(objPtr);
+    objPtr->bytes = NULL;
+    
+    objPtr->internalRep.longValue = (long)intValue;
+    objPtr->typePtr = &tclIntType;
+    return objPtr;
+}
+#endif /* if TCL_MEM_DEBUG */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetIntObj --
+ *
+ *	Modify an object to be an integer and to have the specified integer
+ *	value.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The object's old string rep, if any, is freed. Also, any old
+ *	internal rep is freed. 
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetIntObj(objPtr, intValue)
+    register Tcl_Obj *objPtr;	/* Object whose internal rep to init. */
+    register int intValue;	/* Integer used to set object's value. */
+{
+    register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
+
+    if (Tcl_IsShared(objPtr)) {
+	panic("Tcl_SetIntObj called with shared object");
+    }
+    
+    Tcl_InvalidateStringRep(objPtr);
+    if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
+	oldTypePtr->freeIntRepProc(objPtr);
+    }
+    
+    objPtr->internalRep.longValue = (long) intValue;
+    objPtr->typePtr = &tclIntType;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetIntFromObj --
+ *
+ *	Attempt to return an int from the Tcl object "objPtr". If the object
+ *	is not already an int, an attempt will be made to convert it to one.
+ *
+ *	Integer and long integer objects share the same "integer" type
+ *	implementation. We store all integers as longs and Tcl_GetIntFromObj
+ *	checks whether the current value of the long can be represented by
+ *	an int.
+ *
+ * Results:
+ *	The return value is a standard Tcl object result. If an error occurs
+ *	during conversion or if the long integer held by the object
+ *	can not be represented by an int, an error message is left in
+ *	the interpreter's result unless "interp" is NULL.
+ *
+ * Side effects:
+ *	If the object is not already an int, the conversion will free
+ *	any old internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetIntFromObj(interp, objPtr, intPtr)
+    Tcl_Interp *interp; 	/* Used for error reporting if not NULL. */
+    register Tcl_Obj *objPtr;	/* The object from which to get a int. */
+    register int *intPtr;	/* Place to store resulting int. */
+{
+    register long l;
+    int result;
+    
+    if (objPtr->typePtr != &tclIntType) {
+	result = SetIntFromAny(interp, objPtr);
+	if (result != TCL_OK) {
+	    return result;
+	}
+    }
+    l = objPtr->internalRep.longValue;
+    if (((long)((int)l)) == l) {
+	*intPtr = (int)objPtr->internalRep.longValue;
+	return TCL_OK;
+    }
+    if (interp != NULL) {
+	Tcl_ResetResult(interp);
+	Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		"integer value too large to represent as non-long integer", -1);
+    }
+    return TCL_ERROR;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupIntInternalRep --
+ *
+ *	Initialize the internal representation of an int Tcl_Obj to a
+ *	copy of the internal representation of an existing int object. 
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	"copyPtr"s internal rep is set to the integer corresponding to
+ *	"srcPtr"s internal rep.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DupIntInternalRep(srcPtr, copyPtr)
+    register Tcl_Obj *srcPtr;	/* Object with internal rep to copy. */
+    register Tcl_Obj *copyPtr;	/* Object with internal rep to set. */
+{
+    copyPtr->internalRep.longValue = srcPtr->internalRep.longValue;
+    copyPtr->typePtr = &tclIntType;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetIntFromAny --
+ *
+ *	Attempt to generate an integer internal form for the Tcl object
+ *	"objPtr".
+ *
+ * Results:
+ *	The return value is a standard object Tcl result. If an error occurs
+ *	during conversion, an error message is left in the interpreter's
+ *	result unless "interp" is NULL.
+ *
+ * Side effects:
+ *	If no error occurs, an int is stored as "objPtr"s internal
+ *	representation. 
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetIntFromAny(interp, objPtr)
+    Tcl_Interp *interp;		/* Used for error reporting if not NULL. */
+    register Tcl_Obj *objPtr;	/* The object to convert. */
+{
+    Tcl_ObjType *oldTypePtr = objPtr->typePtr;
+    char *string, *end;
+    int length;
+    register char *p;
+    long newLong;
+
+    /*
+     * Get the string representation. Make it up-to-date if necessary.
+     */
+
+    string = TclGetStringFromObj(objPtr, &length);
+
+    /*
+     * Now parse "objPtr"s string as an int. We use an implementation here
+     * that doesn't report errors in interp if interp is NULL. Note: use
+     * strtoul instead of strtol for integer conversions to allow full-size
+     * unsigned numbers, but don't depend on strtoul to handle sign
+     * characters; it won't in some implementations.
+     */
+
+    errno = 0;
+    for (p = string;  isspace(UCHAR(*p));  p++) {
+	/* Empty loop body. */
+    }
+    if (*p == '-') {
+	p++;
+	newLong = -((long)strtoul(p, &end, 0));
+    } else if (*p == '+') {
+	p++;
+	newLong = strtoul(p, &end, 0);
+    } else {
+	newLong = strtoul(p, &end, 0);
+    }
+    if (end == p) {
+	badInteger:
+	if (interp != NULL) {
+	    /*
+	     * Must copy string before resetting the result in case a caller
+	     * is trying to convert the interpreter's result to an int.
+	     */
+	    
+	    char buf[100];
+	    sprintf(buf, "expected integer but got \"%.50s\"", string);
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
+	}
+	return TCL_ERROR;
+    }
+    if (errno == ERANGE) {
+	if (interp != NULL) {
+	    char *s = "integer value too large to represent";
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
+	    Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *) NULL);
+	}
+	return TCL_ERROR;
+    }
+
+    /*
+     * Make sure that the string has no garbage after the end of the int.
+     */
+    
+    while ((end < (string+length)) && isspace(UCHAR(*end))) {
+	end++;
+    }
+    if (end != (string+length)) {
+	goto badInteger;
+    }
+
+    /*
+     * The conversion to int succeeded. Free the old internalRep before
+     * setting the new one. We do this as late as possible to allow the
+     * conversion code, in particular Tcl_GetStringFromObj, to use that old
+     * internalRep.
+     */
+
+    if ((oldTypePtr != NULL) &&	(oldTypePtr->freeIntRepProc != NULL)) {
+	oldTypePtr->freeIntRepProc(objPtr);
+    }
+    
+    objPtr->internalRep.longValue = newLong;
+    objPtr->typePtr = &tclIntType;
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateStringOfInt --
+ *
+ *	Update the string representation for an integer object.
+ *	Note: This procedure does not free an existing old string rep
+ *	so storage will be lost if this has not already been done. 
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The object's string is set to a valid string that results from
+ *	the int-to-string conversion.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateStringOfInt(objPtr)
+    register Tcl_Obj *objPtr;	/* Int object whose string rep to update. */
+{
+    char buffer[TCL_DOUBLE_SPACE];
+    register int len;
+    
+    len = TclFormatInt(buffer, objPtr->internalRep.longValue);
+    
+    objPtr->bytes = ckalloc((unsigned) len + 1);
+    strcpy(objPtr->bytes, buffer);
+    objPtr->length = len;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_NewLongObj --
+ *
+ *	If a client is compiled with TCL_MEM_DEBUG defined, calls to
+ *	Tcl_NewLongObj to create a new long integer object end up calling
+ *	the debugging procedure Tcl_DbNewLongObj instead.
+ *
+ *	Otherwise, if the client is compiled without TCL_MEM_DEBUG defined,
+ *	calls to Tcl_NewLongObj result in a call to one of the two
+ *	Tcl_NewLongObj implementations below. We provide two implementations
+ *	so that the Tcl core can be compiled to do memory debugging of the 
+ *	core even if a client does not request it for itself.
+ *
+ *	Integer and long integer objects share the same "integer" type
+ *	implementation. We store all integers as longs and Tcl_GetIntFromObj
+ *	checks whether the current value of the long can be represented by
+ *	an int.
+ *
+ * Results:
+ *	The newly created object is returned. This object will have an
+ *	invalid string representation. The returned object has ref count 0.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_MEM_DEBUG
+#undef Tcl_NewLongObj
+
+Tcl_Obj *
+Tcl_NewLongObj(longValue)
+    register long longValue;	/* Long integer used to initialize the
+				 * new object. */
+{
+    return Tcl_DbNewLongObj(longValue, "unknown", 0);
+}
+
+#else /* if not TCL_MEM_DEBUG */
+
+Tcl_Obj *
+Tcl_NewLongObj(longValue)
+    register long longValue;	/* Long integer used to initialize the
+				 * new object. */
+{
+    register Tcl_Obj *objPtr;
+
+    TclNewObj(objPtr);
+    objPtr->bytes = NULL;
+    
+    objPtr->internalRep.longValue = longValue;
+    objPtr->typePtr = &tclIntType;
+    return objPtr;
+}
+#endif /* if TCL_MEM_DEBUG */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DbNewLongObj --
+ *
+ *	If a client is compiled with TCL_MEM_DEBUG defined, calls to
+ *	Tcl_NewIntObj and Tcl_NewLongObj to create new integer or
+ *	long integer objects end up calling the debugging procedure
+ *	Tcl_DbNewLongObj instead. We provide two implementations of
+ *	Tcl_DbNewLongObj so that whether the Tcl core is compiled to do
+ *	memory debugging of the core is independent of whether a client
+ *	requests debugging for itself.
+ *
+ *	When the core is compiled with TCL_MEM_DEBUG defined,
+ *	Tcl_DbNewLongObj calls Tcl_DbCkalloc directly with the file name and
+ *	line number from its caller. This simplifies debugging since then
+ *	the checkmem command will report the caller's file name and line
+ *	number when reporting objects that haven't been freed.
+ *
+ *	Otherwise, when the core is compiled without TCL_MEM_DEBUG defined,
+ *	this procedure just returns the result of calling Tcl_NewLongObj.
+ *
+ * Results:
+ *	The newly created long integer object is returned. This object
+ *	will have an invalid string representation. The returned object has
+ *	ref count 0.
+ *
+ * Side effects:
+ *	Allocates memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_MEM_DEBUG
+
+Tcl_Obj *
+Tcl_DbNewLongObj(longValue, file, line)
+    register long longValue;	/* Long integer used to initialize the
+				 * new object. */
+    char *file;			/* The name of the source file calling this
+				 * procedure; used for debugging. */
+    int line;			/* Line number in the source file; used
+				 * for debugging. */
+{
+    register Tcl_Obj *objPtr;
+
+    TclDbNewObj(objPtr, file, line);
+    objPtr->bytes = NULL;
+    
+    objPtr->internalRep.longValue = longValue;
+    objPtr->typePtr = &tclIntType;
+    return objPtr;
+}
+
+#else /* if not TCL_MEM_DEBUG */
+
+Tcl_Obj *
+Tcl_DbNewLongObj(longValue, file, line)
+    register long longValue;	/* Long integer used to initialize the
+				 * new object. */
+    char *file;			/* The name of the source file calling this
+				 * procedure; used for debugging. */
+    int line;			/* Line number in the source file; used
+				 * for debugging. */
+{
+    return Tcl_NewLongObj(longValue);
+}
+#endif /* TCL_MEM_DEBUG */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetLongObj --
+ *
+ *	Modify an object to be an integer object and to have the specified
+ *	long integer value.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The object's old string rep, if any, is freed. Also, any old
+ *	internal rep is freed. 
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetLongObj(objPtr, longValue)
+    register Tcl_Obj *objPtr;	/* Object whose internal rep to init. */
+    register long longValue;	/* Long integer used to initialize the
+				 * object's value. */
+{
+    register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
+
+    if (Tcl_IsShared(objPtr)) {
+	panic("Tcl_SetLongObj called with shared object");
+    }
+
+    Tcl_InvalidateStringRep(objPtr);
+    if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
+	oldTypePtr->freeIntRepProc(objPtr);
+    }
+    
+    objPtr->internalRep.longValue = longValue;
+    objPtr->typePtr = &tclIntType;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetLongFromObj --
+ *
+ *	Attempt to return an long integer from the Tcl object "objPtr". If
+ *	the object is not already an int object, an attempt will be made to
+ *	convert it to one.
+ *
+ * Results:
+ *	The return value is a standard Tcl object result. If an error occurs
+ *	during conversion, an error message is left in the interpreter's
+ *	result unless "interp" is NULL.
+ *
+ * Side effects:
+ *	If the object is not already an int object, the conversion will free
+ *	any old internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetLongFromObj(interp, objPtr, longPtr)
+    Tcl_Interp *interp; 	/* Used for error reporting if not NULL. */
+    register Tcl_Obj *objPtr;	/* The object from which to get a long. */
+    register long *longPtr;	/* Place to store resulting long. */
+{
+    register int result;
+    
+    if (objPtr->typePtr == &tclIntType) {
+	*longPtr = objPtr->internalRep.longValue;
+	return TCL_OK;
+    }
+    result = SetIntFromAny(interp, objPtr);
+    if (result == TCL_OK) {
+	*longPtr = objPtr->internalRep.longValue;
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DbIncrRefCount --
+ *
+ *	This procedure is normally called when debugging: i.e., when
+ *	TCL_MEM_DEBUG is defined. This checks to see whether or not
+ *	the memory has been freed before incrementing the ref count.
+ *
+ *	When TCL_MEM_DEBUG is not defined, this procedure just increments
+ *	the reference count of the object.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The object's ref count is incremented.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DbIncrRefCount(objPtr, file, line)
+    register Tcl_Obj *objPtr;	/* The object we are adding a reference to. */
+    char *file;			/* The name of the source file calling this
+				 * procedure; used for debugging. */
+    int line;			/* Line number in the source file; used
+				 * for debugging. */
+{
+#ifdef TCL_MEM_DEBUG
+    if (objPtr->refCount == 0x61616161) {
+	fprintf(stderr, "file = %s, line = %d\n", file, line);
+	fflush(stderr);
+	panic("Trying to increment refCount of previously disposed object.");
+    }
+#endif
+    ++(objPtr)->refCount;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DbDecrRefCount --
+ *
+ *	This procedure is normally called when debugging: i.e., when
+ *	TCL_MEM_DEBUG is defined. This checks to see whether or not
+ *	the memory has been freed before incrementing the ref count.
+ *
+ *	When TCL_MEM_DEBUG is not defined, this procedure just increments
+ *	the reference count of the object.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The object's ref count is incremented.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DbDecrRefCount(objPtr, file, line)
+    register Tcl_Obj *objPtr;	/* The object we are adding a reference to. */
+    char *file;			/* The name of the source file calling this
+				 * procedure; used for debugging. */
+    int line;			/* Line number in the source file; used
+				 * for debugging. */
+{
+#ifdef TCL_MEM_DEBUG
+    if (objPtr->refCount == 0x61616161) {
+	fprintf(stderr, "file = %s, line = %d\n", file, line);
+	fflush(stderr);
+	panic("Trying to decrement refCount of previously disposed object.");
+    }
+#endif
+    if (--(objPtr)->refCount <= 0) {
+	TclFreeObj(objPtr);
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DbIsShared --
+ *
+ *	This procedure is normally called when debugging: i.e., when
+ *	TCL_MEM_DEBUG is defined. This checks to see whether or not
+ *	the memory has been freed before incrementing the ref count.
+ *
+ *	When TCL_MEM_DEBUG is not defined, this procedure just decrements
+ *	the reference count of the object and throws it away if the count
+ *	is 0 or less.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The object's ref count is incremented.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_DbIsShared(objPtr, file, line)
+    register Tcl_Obj *objPtr;	/* The object we are adding a reference to. */
+    char *file;			/* The name of the source file calling this
+				 * procedure; used for debugging. */
+    int line;			/* Line number in the source file; used
+				 * for debugging. */
+{
+#ifdef TCL_MEM_DEBUG
+    if (objPtr->refCount == 0x61616161) {
+	fprintf(stderr, "file = %s, line = %d\n", file, line);
+	fflush(stderr);
+	panic("Trying to check whether previously disposed object is shared.");
+    }
+#endif
+    return ((objPtr)->refCount > 1);
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclParse.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclParse.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclParse.c	(revision 5)
@@ -0,0 +1,949 @@
+/* 
+ * tclParse.c --
+ *
+ *	This file contains a collection of procedures that are used
+ *	to parse Tcl commands or parts of commands (like quoted
+ *	strings or nested sub-commands).
+ *
+ * Copyright (c) 1987-1993 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclParse.c,v 1.1 2008-06-04 13:58:09 demin Exp $
+ */
+
+#include "tclInt.h"
+#include "tclPort.h"
+
+/*
+ * Function prototypes for procedures local to this file:
+ */
+
+static char *	QuoteEnd _ANSI_ARGS_((char *string, char *lastChar,
+		    int term));
+static char *	ScriptEnd _ANSI_ARGS_((char *p, char *lastChar,
+		    int nested));
+static char *	VarNameEnd _ANSI_ARGS_((char *string,  char *lastChar));
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TclParseQuotes --
+ *
+ *	This procedure parses a double-quoted string such as a
+ *	quoted Tcl command argument or a quoted value in a Tcl
+ *	expression.  This procedure is also used to parse array
+ *	element names within parentheses, or anything else that
+ *	needs all the substitutions that happen in quotes.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is
+ *	TCL_OK unless there was an error while parsing the
+ *	quoted string.  If an error occurs then interp->result
+ *	contains a standard error message.  *TermPtr is filled
+ *	in with the address of the character just after the
+ *	last one successfully processed;  this is usually the
+ *	character just after the matching close-quote.  The
+ *	fully-substituted contents of the quotes are stored in
+ *	standard fashion in *pvPtr, null-terminated with
+ *	pvPtr->next pointing to the terminating null character.
+ *
+ * Side effects:
+ *	The buffer space in pvPtr may be enlarged by calling its
+ *	expandProc.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TclParseQuotes(interp, string, termChar, flags, termPtr, pvPtr)
+    Tcl_Interp *interp;		/* Interpreter to use for nested command
+				 * evaluations and error messages. */
+    char *string;		/* Character just after opening double-
+				 * quote. */
+    int termChar;		/* Character that terminates "quoted" string
+				 * (usually double-quote, but sometimes
+				 * right-paren or something else). */
+    int flags;			/* Flags to pass to nested Tcl_Eval calls. */
+    char **termPtr;		/* Store address of terminating character
+				 * here. */
+    ParseValue *pvPtr;		/* Information about where to place
+				 * fully-substituted result of parse. */
+{
+    register char *src, *dst, c;
+    char *lastChar = string + strlen(string);
+
+    src = string;
+    dst = pvPtr->next;
+
+    while (1) {
+	if (dst == pvPtr->end) {
+	    /*
+	     * Target buffer space is about to run out.  Make more space.
+	     */
+
+	    pvPtr->next = dst;
+	    (*pvPtr->expandProc)(pvPtr, 1);
+	    dst = pvPtr->next;
+	}
+
+	c = *src;
+	src++;
+	if (c == termChar) {
+	    *dst = '\0';
+	    pvPtr->next = dst;
+	    *termPtr = src;
+	    return TCL_OK;
+	} else if (CHAR_TYPE(src-1, lastChar) == TCL_NORMAL) {
+	    copy:
+	    *dst = c;
+	    dst++;
+	    continue;
+	} else if (c == '$') {
+	    int length;
+	    char *value;
+
+	    value = Tcl_ParseVar(interp, src-1, termPtr);
+	    if (value == NULL) {
+		return TCL_ERROR;
+	    }
+	    src = *termPtr;
+	    length = strlen(value);
+	    if ((pvPtr->end - dst) <= length) {
+		pvPtr->next = dst;
+		(*pvPtr->expandProc)(pvPtr, length);
+		dst = pvPtr->next;
+	    }
+	    strcpy(dst, value);
+	    dst += length;
+	    continue;
+	} else if (c == '[') {
+	    int result;
+
+	    pvPtr->next = dst;
+	    result = TclParseNestedCmd(interp, src, flags, termPtr, pvPtr);
+	    if (result != TCL_OK) {
+		return result;
+	    }
+	    src = *termPtr;
+	    dst = pvPtr->next;
+	    continue;
+	} else if (c == '\\') {
+	    int numRead;
+
+	    src--;
+	    *dst = Tcl_Backslash(src, &numRead);
+	    dst++;
+	    src += numRead;
+	    continue;
+	} else if (c == '\0') {
+	    char buf[30];
+	    
+	    Tcl_ResetResult(interp);
+	    sprintf(buf, "missing %c", termChar);
+	    Tcl_SetResult(interp, buf, TCL_VOLATILE);
+	    *termPtr = string-1;
+	    return TCL_ERROR;
+	} else {
+	    goto copy;
+	}
+    }
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TclParseNestedCmd --
+ *
+ *	This procedure parses a nested Tcl command between
+ *	brackets, returning the result of the command.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is
+ *	TCL_OK unless there was an error while executing the
+ *	nested command.  If an error occurs then interp->result
+ *	contains a standard error message.  *TermPtr is filled
+ *	in with the address of the character just after the
+ *	last one processed;  this is usually the character just
+ *	after the matching close-bracket, or the null character
+ *	at the end of the string if the close-bracket was missing
+ *	(a missing close bracket is an error).  The result returned
+ *	by the command is stored in standard fashion in *pvPtr,
+ *	null-terminated, with pvPtr->next pointing to the null
+ *	character.
+ *
+ * Side effects:
+ *	The storage space at *pvPtr may be expanded.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TclParseNestedCmd(interp, string, flags, termPtr, pvPtr)
+    Tcl_Interp *interp;		/* Interpreter to use for nested command
+				 * evaluations and error messages. */
+    char *string;		/* Character just after opening bracket. */
+    int flags;			/* Flags to pass to nested Tcl_Eval. */
+    char **termPtr;		/* Store address of terminating character
+				 * here. */
+    register ParseValue *pvPtr;	/* Information about where to place
+				 * result of command. */
+{
+    int result, length, shortfall;
+    Interp *iPtr = (Interp *) interp;
+
+    iPtr->evalFlags = flags | TCL_BRACKET_TERM;
+    result = Tcl_Eval(interp, string);
+    *termPtr = (string + iPtr->termOffset);
+    if (result != TCL_OK) {
+	/*
+	 * The increment below results in slightly cleaner message in
+	 * the errorInfo variable (the close-bracket will appear).
+	 */
+
+	if (**termPtr == ']') {
+	    *termPtr += 1;
+	}
+	return result;
+    }
+    (*termPtr) += 1;
+    length = strlen(iPtr->result);
+    shortfall = length + 1 - (pvPtr->end - pvPtr->next);
+    if (shortfall > 0) {
+	(*pvPtr->expandProc)(pvPtr, shortfall);
+    }
+    strcpy(pvPtr->next, iPtr->result);
+    pvPtr->next += length;
+    
+    Tcl_FreeResult(interp);
+    iPtr->result = iPtr->resultSpace;
+    iPtr->resultSpace[0] = '\0';
+    return TCL_OK;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TclParseBraces --
+ *
+ *	This procedure scans the information between matching
+ *	curly braces.
+ *
+ * Results:
+ *	The return value is a standard Tcl result, which is
+ *	TCL_OK unless there was an error while parsing string.
+ *	If an error occurs then interp->result contains a
+ *	standard error message.  *TermPtr is filled
+ *	in with the address of the character just after the
+ *	last one successfully processed;  this is usually the
+ *	character just after the matching close-brace.  The
+ *	information between curly braces is stored in standard
+ *	fashion in *pvPtr, null-terminated with pvPtr->next
+ *	pointing to the terminating null character.
+ *
+ * Side effects:
+ *	The storage space at *pvPtr may be expanded.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TclParseBraces(interp, string, termPtr, pvPtr)
+    Tcl_Interp *interp;		/* Interpreter to use for nested command
+				 * evaluations and error messages. */
+    char *string;		/* Character just after opening bracket. */
+    char **termPtr;		/* Store address of terminating character
+				 * here. */
+    register ParseValue *pvPtr;	/* Information about where to place
+				 * result of command. */
+{
+    int level;
+    register char *src, *dst, *end;
+    register char c;
+    char *lastChar = string + strlen(string);
+
+    src = string;
+    dst = pvPtr->next;
+    end = pvPtr->end;
+    level = 1;
+
+    /*
+     * Copy the characters one at a time to the result area, stopping
+     * when the matching close-brace is found.
+     */
+
+    while (1) {
+	c = *src;
+	src++;
+	if (dst == end) {
+	    pvPtr->next = dst;
+	    (*pvPtr->expandProc)(pvPtr, 20);
+	    dst = pvPtr->next;
+	    end = pvPtr->end;
+	}
+	*dst = c;
+	dst++;
+	if (CHAR_TYPE(src-1, lastChar) == TCL_NORMAL) {
+	    continue;
+	} else if (c == '{') {
+	    level++;
+	} else if (c == '}') {
+	    level--;
+	    if (level == 0) {
+		dst--;			/* Don't copy the last close brace. */
+		break;
+	    }
+	} else if (c == '\\') {
+	    int count;
+
+	    /*
+	     * Must always squish out backslash-newlines, even when in
+	     * braces.  This is needed so that this sequence can appear
+	     * anywhere in a command, such as the middle of an expression.
+	     */
+
+	    if (*src == '\n') {
+		dst[-1] = Tcl_Backslash(src-1, &count);
+		src += count - 1;
+	    } else {
+		(void) Tcl_Backslash(src-1, &count);
+		while (count > 1) {
+                    if (dst == end) {
+                        pvPtr->next = dst;
+                        (*pvPtr->expandProc)(pvPtr, 20);
+                        dst = pvPtr->next;
+                        end = pvPtr->end;
+                    }
+		    *dst = *src;
+		    dst++;
+		    src++;
+		    count--;
+		}
+	    }
+	} else if (c == '\0') {
+	    Tcl_SetResult(interp, "missing close-brace", TCL_STATIC);
+	    *termPtr = string-1;
+	    return TCL_ERROR;
+	}
+    }
+
+    *dst = '\0';
+    pvPtr->next = dst;
+    *termPtr = src;
+    return TCL_OK;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TclExpandParseValue --
+ *
+ *	This procedure is commonly used as the value of the
+ *	expandProc in a ParseValue.  It uses malloc to allocate
+ *	more space for the result of a parse.
+ *
+ * Results:
+ *	The buffer space in *pvPtr is reallocated to something
+ *	larger, and if pvPtr->clientData is non-zero the old
+ *	buffer is freed.  Information is copied from the old
+ *	buffer to the new one.
+ *
+ * Side effects:
+ *	None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TclExpandParseValue(pvPtr, needed)
+    register ParseValue *pvPtr;		/* Information about buffer that
+					 * must be expanded.  If the clientData
+					 * in the structure is non-zero, it
+					 * means that the current buffer is
+					 * dynamically allocated. */
+    int needed;				/* Minimum amount of additional space
+					 * to allocate. */
+{
+    int newSpace;
+    char *new;
+
+    /*
+     * Either double the size of the buffer or add enough new space
+     * to meet the demand, whichever produces a larger new buffer.
+     */
+
+    newSpace = (pvPtr->end - pvPtr->buffer) + 1;
+    if (newSpace < needed) {
+	newSpace += needed;
+    } else {
+	newSpace += newSpace;
+    }
+    new = (char *) ckalloc((unsigned) newSpace);
+
+    /*
+     * Copy from old buffer to new, free old buffer if needed, and
+     * mark new buffer as malloc-ed.
+     */
+
+    memcpy((VOID *) new, (VOID *) pvPtr->buffer,
+	    (size_t) (pvPtr->next - pvPtr->buffer));
+    pvPtr->next = new + (pvPtr->next - pvPtr->buffer);
+    if (pvPtr->clientData != 0) {
+	ckfree(pvPtr->buffer);
+    }
+    pvPtr->buffer = new;
+    pvPtr->end = new + newSpace - 1;
+    pvPtr->clientData = (ClientData) 1;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclWordEnd --
+ *
+ *	Given a pointer into a Tcl command, find the end of the next
+ *	word of the command.
+ *
+ * Results:
+ *	The return value is a pointer to the last character that's part
+ *	of the word pointed to by "start".  If the word doesn't end
+ *	properly within the string then the return value is the address
+ *	of the null character at the end of the string.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+TclWordEnd(start, lastChar, nested, semiPtr)
+    char *start;		/* Beginning of a word of a Tcl command. */
+    char *lastChar;		/* Terminating character in string. */
+    int nested;			/* Zero means this is a top-level command.
+				 * One means this is a nested command (close
+				 * bracket is a word terminator). */
+    int *semiPtr;		/* Set to 1 if word ends with a command-
+				 * terminating semi-colon, zero otherwise.
+				 * If NULL then ignored. */
+{
+    register char *p;
+    int count;
+
+    if (semiPtr != NULL) {
+	*semiPtr = 0;
+    }
+
+    /*
+     * Skip leading white space (backslash-newline must be treated like
+     * white-space, except that it better not be the last thing in the
+     * command).
+     */
+
+    for (p = start; ; p++) {
+	if (isspace(UCHAR(*p))) {
+	    continue;
+	}
+	if ((p[0] == '\\') && (p[1] == '\n')) {
+	    if (p+2 == lastChar) {
+		return p+2;
+	    }
+	    continue;
+	}
+	break;
+    }
+
+    /*
+     * Handle words beginning with a double-quote or a brace.
+     */
+
+    if (*p == '"') {
+	p = QuoteEnd(p+1, lastChar, '"');
+	if (p == lastChar) {
+	    return p;
+	}
+	p++;
+    } else if (*p == '{') {
+	int braces = 1;
+	while (braces != 0) {
+	    p++;
+	    while (*p == '\\') {
+		(void) Tcl_Backslash(p, &count);
+		p += count;
+	    }
+	    if (*p == '}') {
+		braces--;
+	    } else if (*p == '{') {
+		braces++;
+	    } else if (p == lastChar) {
+		return p;
+	    }
+	}
+	p++;
+    }
+
+    /*
+     * Handle words that don't start with a brace or double-quote.
+     * This code is also invoked if the word starts with a brace or
+     * double-quote and there is garbage after the closing brace or
+     * quote.  This is an error as far as Tcl_Eval is concerned, but
+     * for here the garbage is treated as part of the word.
+     */
+
+    while (1) {
+	if (*p == '[') {
+	    p = ScriptEnd(p+1, lastChar, 1);
+	    if (p == lastChar) {
+		return p;
+	    }
+	    p++;
+	} else if (*p == '\\') {
+	    if (p[1] == '\n') {
+		/*
+		 * Backslash-newline:  it maps to a space character
+		 * that is a word separator, so the word ends just before
+		 * the backslash.
+		 */
+
+		return p-1;
+	    }
+	    (void) Tcl_Backslash(p, &count);
+	    p += count;
+	} else if (*p == '$') {
+	    p = VarNameEnd(p, lastChar);
+	    if (p == lastChar) {
+		return p;
+	    }
+	    p++;
+	} else if (*p == ';') {
+	    /*
+	     * Include the semi-colon in the word that is returned.
+	     */
+
+	    if (semiPtr != NULL) {
+		*semiPtr = 1;
+	    }
+	    return p;
+	} else if (isspace(UCHAR(*p))) {
+	    return p-1;
+	} else if ((*p == ']') && nested) {
+	    return p-1;
+	} else if (p == lastChar) {
+	    if (nested) {
+		/*
+		 * Nested commands can't end because of the end of the
+		 * string.
+		 */
+		return p;
+	    }
+	    return p-1;
+	} else {
+	    p++;
+	}
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * QuoteEnd --
+ *
+ *	Given a pointer to a string that obeys the parsing conventions
+ *	for quoted things in Tcl, find the end of that quoted thing.
+ *	The actual thing may be a quoted argument or a parenthesized
+ *	index name.
+ *
+ * Results:
+ *	The return value is a pointer to the last character that is
+ *	part of the quoted string (i.e the character that's equal to
+ *	term).  If the quoted string doesn't terminate properly then
+ *	the return value is a pointer to the null character at the
+ *	end of the string.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+QuoteEnd(string, lastChar, term)
+    char *string;		/* Pointer to character just after opening
+				 * "quote". */
+    char *lastChar;		/* Terminating character in string. */
+    int term;			/* This character will terminate the
+				 * quoted string (e.g. '"' or ')'). */
+{
+    register char *p = string;
+    int count;
+
+    while (*p != term) {
+	if (*p == '\\') {
+	    (void) Tcl_Backslash(p, &count);
+	    p += count;
+	} else if (*p == '[') {
+	    for (p++; *p != ']'; p++) {
+		p = TclWordEnd(p, lastChar, 1, (int *) NULL);
+		if (*p == 0) {
+		    return p;
+		}
+	    }
+	    p++;
+	} else if (*p == '$') {
+	    p = VarNameEnd(p, lastChar);
+	    if (*p == 0) {
+		return p;
+	    }
+	    p++;
+	} else if (p == lastChar) {
+	    return p;
+	} else {
+	    p++;
+	}
+    }
+    return p-1;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VarNameEnd --
+ *
+ *	Given a pointer to a variable reference using $-notation, find
+ *	the end of the variable name spec.
+ *
+ * Results:
+ *	The return value is a pointer to the last character that
+ *	is part of the variable name.  If the variable name doesn't
+ *	terminate properly then the return value is a pointer to the
+ *	null character at the end of the string.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+VarNameEnd(string, lastChar)
+    char *string;		/* Pointer to dollar-sign character. */
+    char *lastChar;		/* Terminating character in string. */
+{
+    register char *p = string+1;
+
+    if (*p == '{') {
+	for (p++; (*p != '}') && (p != lastChar); p++) {
+	    /* Empty loop body. */
+	}
+	return p;
+    }
+    while (isalnum(UCHAR(*p)) || (*p == '_')) {
+	p++;
+    }
+    if ((*p == '(') && (p != string+1)) {
+	return QuoteEnd(p+1, lastChar, ')');
+    }
+    return p-1;
+}
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ScriptEnd --
+ *
+ *	Given a pointer to the beginning of a Tcl script, find the end of
+ *	the script.
+ *
+ * Results:
+ *	The return value is a pointer to the last character that's part
+ *	of the script pointed to by "p".  If the command doesn't end
+ *	properly within the string then the return value is the address
+ *	of the null character at the end of the string.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+ScriptEnd(p, lastChar, nested)
+    char *p;			/* Script to check. */
+    char *lastChar;		/* Terminating character in string. */
+    int nested;			/* Zero means this is a top-level command.
+				 * One means this is a nested command (the
+				 * last character of the script must be
+				 * an unquoted ]). */
+{
+    int commentOK = 1;
+    int length;
+
+    while (1) {
+	while (isspace(UCHAR(*p))) {
+	    if (*p == '\n') {
+		commentOK = 1;
+	    }
+	    p++;
+	}
+	if ((*p == '#') && commentOK) {
+	    do {
+		if (*p == '\\') {
+		    /*
+		     * If the script ends with backslash-newline, then
+		     * this command isn't complete.
+		     */
+
+		    if ((p[1] == '\n') && (p+2 == lastChar)) {
+			return p+2;
+		    }
+		    Tcl_Backslash(p, &length);
+		    p += length;
+		} else {
+		    p++;
+		}
+	    } while ((p != lastChar) && (*p != '\n'));
+	    continue;
+	}
+	p = TclWordEnd(p, lastChar, nested, &commentOK);
+	if (p == lastChar) {
+	    return p;
+	}
+	p++;
+	if (nested) {
+	    if (*p == ']') {
+		return p;
+	    }
+	} else {
+	    if (p == lastChar) {
+		return p-1;
+	    }
+	}
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ParseVar --
+ *
+ *	Given a string starting with a $ sign, parse off a variable
+ *	name and return its value.
+ *
+ * Results:
+ *	The return value is the contents of the variable given by
+ *	the leading characters of string.  If termPtr isn't NULL,
+ *	*termPtr gets filled in with the address of the character
+ *	just after the last one in the variable specifier.  If the
+ *	variable doesn't exist, then the return value is NULL and
+ *	an error message will be left in interp->result.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_ParseVar(interp, string, termPtr)
+    Tcl_Interp *interp;			/* Context for looking up variable. */
+    register char *string;		/* String containing variable name.
+					 * First character must be "$". */
+    char **termPtr;			/* If non-NULL, points to word to fill
+					 * in with character just after last
+					 * one in the variable specifier. */
+
+{
+    char *name1, *name1End, c, *result;
+    register char *name2;
+#define NUM_CHARS 200
+    char copyStorage[NUM_CHARS];
+    ParseValue pv;
+
+    /*
+     * There are three cases:
+     * 1. The $ sign is followed by an open curly brace.  Then the variable
+     *    name is everything up to the next close curly brace, and the
+     *    variable is a scalar variable.
+     * 2. The $ sign is not followed by an open curly brace.  Then the
+     *    variable name is everything up to the next character that isn't
+     *    a letter, digit, or underscore, or a "::" namespace separator.
+     *    If the following character is an open parenthesis, then the
+     *    information between parentheses is the array element name, which
+     *    can include any of the substitutions permissible between quotes.
+     * 3. The $ sign is followed by something that isn't a letter, digit,
+     *    underscore, or a "::" namespace separator: in this case,
+     *    there is no variable name, and "$" is returned.
+     */
+
+    name2 = NULL;
+    string++;
+    if (*string == '{') {
+	string++;
+	name1 = string;
+	while (*string != '}') {
+	    if (*string == 0) {
+		Tcl_SetResult(interp, "missing close-brace for variable name",
+			TCL_STATIC);
+		if (termPtr != 0) {
+		    *termPtr = string;
+		}
+		return NULL;
+	    }
+	    string++;
+	}
+	name1End = string;
+	string++;
+    } else {
+	name1 = string;
+	while (isalnum(UCHAR(*string)) || (*string == '_')
+	        || (*string == ':')) {
+	    if (*string == ':') {
+		if (*(string+1) == ':') {
+                    string += 2;  /* skip over the initial :: */
+		    while (*string == ':') {
+			string++; /* skip over a subsequent : */
+		    }
+		} else {
+		    break;	  /* : by itself */
+                }
+	    } else {
+		string++;
+	    }
+	}
+	if (string == name1) {
+	    if (termPtr != 0) {
+		*termPtr = string;
+	    }
+	    return "$";
+	}
+	name1End = string;
+	if (*string == '(') {
+	    char *end;
+
+	    /*
+	     * Perform substitutions on the array element name, just as
+	     * is done for quotes.
+	     */
+
+	    pv.buffer = pv.next = copyStorage;
+	    pv.end = copyStorage + NUM_CHARS - 1;
+	    pv.expandProc = TclExpandParseValue;
+	    pv.clientData = (ClientData) NULL;
+	    if (TclParseQuotes(interp, string+1, ')', 0, &end, &pv)
+		    != TCL_OK) {
+		char msg[200];
+		int length;
+
+		length = string-name1;
+		if (length > 100) {
+		    length = 100;
+		}
+		sprintf(msg, "\n    (parsing index for array \"%.*s\")",
+			length, name1);
+		Tcl_AddErrorInfo(interp, msg);
+		result = NULL;
+		name2 = pv.buffer;
+		if (termPtr != 0) {
+		    *termPtr = end;
+		}
+		goto done;
+	    }
+	    Tcl_ResetResult(interp);
+	    string = end;
+	    name2 = pv.buffer;
+	}
+    }
+    if (termPtr != 0) {
+	*termPtr = string;
+    }
+
+    c = *name1End;
+    *name1End = 0;
+    result = Tcl_GetVar2(interp, name1, name2, TCL_LEAVE_ERR_MSG);
+    *name1End = c;
+
+    done:
+    if ((name2 != NULL) && (pv.buffer != copyStorage)) {
+	ckfree(pv.buffer);
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CommandComplete --
+ *
+ *	Given a partial or complete Tcl command, this procedure
+ *	determines whether the command is complete in the sense
+ *	of having matched braces and quotes and brackets.
+ *
+ * Results:
+ *	1 is returned if the command is complete, 0 otherwise.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_CommandComplete(cmd)
+    char *cmd;			/* Command to check. */
+{
+    char *p;
+
+    if (*cmd == 0) {
+	return 1;
+    }
+    p = ScriptEnd(cmd, cmd+strlen(cmd), 0);
+    return (*p != 0);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclObjCommandComplete --
+ *
+ *	Given a partial or complete Tcl command in a Tcl object, this
+ *	procedure determines whether the command is complete in the sense of
+ *	having matched braces and quotes and brackets.
+ *
+ * Results:
+ *	1 is returned if the command is complete, 0 otherwise.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclObjCommandComplete(cmdPtr)
+    Tcl_Obj *cmdPtr;			/* Points to object holding command
+					 * to check. */
+{
+    char *cmd, *p;
+    int length;
+
+    cmd = Tcl_GetStringFromObj(cmdPtr, &length);
+    if (length == 0) {
+	return 1;
+    }
+    p = ScriptEnd(cmd, cmd+length, /*nested*/ 0);
+    return (*p != 0);
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclPort.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclPort.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclPort.h	(revision 5)
@@ -0,0 +1,21 @@
+/*
+ * tclPort.h --
+ *
+ *	This header file handles porting issues that occur because
+ *	of differences between systems.  It reads in platform specific
+ *	portability files.
+ *
+ * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclPort.h,v 1.1 2008-06-04 13:58:09 demin Exp $
+ */
+
+#ifndef _TCLPORT
+#define _TCLPORT
+
+#include "tclUnixPort.h"
+
+#endif /* _TCLPORT */
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclPosixStr.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclPosixStr.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclPosixStr.c	(revision 5)
@@ -0,0 +1,1178 @@
+/* 
+ * tclPosixStr.c --
+ *
+ *	This file contains procedures that generate strings
+ *	corresponding to various POSIX-related codes, such
+ *	as errno and signals.
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclPosixStr.c,v 1.1 2008-06-04 13:58:09 demin Exp $
+ */
+
+#include "tclInt.h"
+#include "tclPort.h"
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ErrnoId --
+ *
+ *	Return a textual identifier for the current errno value.
+ *
+ * Results:
+ *	This procedure returns a machine-readable textual identifier
+ *	that corresponds to the current errno value (e.g. "EPERM").
+ *	The identifier is the same as the #define name in errno.h.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_ErrnoId()
+{
+    switch (errno) {
+#ifdef E2BIG
+	case E2BIG: return "E2BIG";
+#endif
+#ifdef EACCES
+	case EACCES: return "EACCES";
+#endif
+#ifdef EADDRINUSE
+	case EADDRINUSE: return "EADDRINUSE";
+#endif
+#ifdef EADDRNOTAVAIL
+	case EADDRNOTAVAIL: return "EADDRNOTAVAIL";
+#endif
+#ifdef EADV
+	case EADV: return "EADV";
+#endif
+#ifdef EAFNOSUPPORT
+	case EAFNOSUPPORT: return "EAFNOSUPPORT";
+#endif
+#ifdef EAGAIN
+	case EAGAIN: return "EAGAIN";
+#endif
+#ifdef EALIGN
+	case EALIGN: return "EALIGN";
+#endif
+#if defined(EALREADY) && (!defined(EBUSY) || (EALREADY != EBUSY ))
+	case EALREADY: return "EALREADY";
+#endif
+#ifdef EBADE
+	case EBADE: return "EBADE";
+#endif
+#ifdef EBADF
+	case EBADF: return "EBADF";
+#endif
+#ifdef EBADFD
+	case EBADFD: return "EBADFD";
+#endif
+#ifdef EBADMSG
+	case EBADMSG: return "EBADMSG";
+#endif
+#ifdef EBADR
+	case EBADR: return "EBADR";
+#endif
+#ifdef EBADRPC
+	case EBADRPC: return "EBADRPC";
+#endif
+#ifdef EBADRQC
+	case EBADRQC: return "EBADRQC";
+#endif
+#ifdef EBADSLT
+	case EBADSLT: return "EBADSLT";
+#endif
+#ifdef EBFONT
+	case EBFONT: return "EBFONT";
+#endif
+#ifdef EBUSY
+	case EBUSY: return "EBUSY";
+#endif
+#ifdef ECHILD
+	case ECHILD: return "ECHILD";
+#endif
+#ifdef ECHRNG
+	case ECHRNG: return "ECHRNG";
+#endif
+#ifdef ECOMM
+	case ECOMM: return "ECOMM";
+#endif
+#ifdef ECONNABORTED
+	case ECONNABORTED: return "ECONNABORTED";
+#endif
+#ifdef ECONNREFUSED
+	case ECONNREFUSED: return "ECONNREFUSED";
+#endif
+#ifdef ECONNRESET
+	case ECONNRESET: return "ECONNRESET";
+#endif
+#if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK))
+	case EDEADLK: return "EDEADLK";
+#endif
+#if defined(EDEADLOCK) && (!defined(EDEADLK) || (EDEADLOCK != EDEADLK))
+	case EDEADLOCK: return "EDEADLOCK";
+#endif
+#ifdef EDESTADDRREQ
+	case EDESTADDRREQ: return "EDESTADDRREQ";
+#endif
+#ifdef EDIRTY
+	case EDIRTY: return "EDIRTY";
+#endif
+#ifdef EDOM
+	case EDOM: return "EDOM";
+#endif
+#ifdef EDOTDOT
+	case EDOTDOT: return "EDOTDOT";
+#endif
+#ifdef EDQUOT
+	case EDQUOT: return "EDQUOT";
+#endif
+#ifdef EDUPPKG
+	case EDUPPKG: return "EDUPPKG";
+#endif
+#ifdef EEXIST
+	case EEXIST: return "EEXIST";
+#endif
+#ifdef EFAULT
+	case EFAULT: return "EFAULT";
+#endif
+#ifdef EFBIG
+	case EFBIG: return "EFBIG";
+#endif
+#ifdef EHOSTDOWN
+	case EHOSTDOWN: return "EHOSTDOWN";
+#endif
+#ifdef EHOSTUNREACH
+	case EHOSTUNREACH: return "EHOSTUNREACH";
+#endif
+#if defined(EIDRM) && (!defined(EINPROGRESS) || (EIDRM != EINPROGRESS))
+	case EIDRM: return "EIDRM";
+#endif
+#ifdef EINIT
+	case EINIT: return "EINIT";
+#endif
+#ifdef EINPROGRESS
+	case EINPROGRESS: return "EINPROGRESS";
+#endif
+#ifdef EINTR
+	case EINTR: return "EINTR";
+#endif
+#ifdef EINVAL
+	case EINVAL: return "EINVAL";
+#endif
+#ifdef EIO
+	case EIO: return "EIO";
+#endif
+#ifdef EISCONN
+	case EISCONN: return "EISCONN";
+#endif
+#ifdef EISDIR
+	case EISDIR: return "EISDIR";
+#endif
+#ifdef EISNAME
+	case EISNAM: return "EISNAM";
+#endif
+#ifdef ELBIN
+	case ELBIN: return "ELBIN";
+#endif
+#ifdef EL2HLT
+	case EL2HLT: return "EL2HLT";
+#endif
+#ifdef EL2NSYNC
+	case EL2NSYNC: return "EL2NSYNC";
+#endif
+#ifdef EL3HLT
+	case EL3HLT: return "EL3HLT";
+#endif
+#ifdef EL3RST
+	case EL3RST: return "EL3RST";
+#endif
+#ifdef ELIBACC
+	case ELIBACC: return "ELIBACC";
+#endif
+#ifdef ELIBBAD
+	case ELIBBAD: return "ELIBBAD";
+#endif
+#ifdef ELIBEXEC
+	case ELIBEXEC: return "ELIBEXEC";
+#endif
+#ifdef ELIBMAX
+	case ELIBMAX: return "ELIBMAX";
+#endif
+#ifdef ELIBSCN
+	case ELIBSCN: return "ELIBSCN";
+#endif
+#ifdef ELNRNG
+	case ELNRNG: return "ELNRNG";
+#endif
+#if defined(ELOOP) && (!defined(ENOENT) || (ELOOP != ENOENT))
+	case ELOOP: return "ELOOP";
+#endif
+#ifdef EMFILE
+	case EMFILE: return "EMFILE";
+#endif
+#ifdef EMLINK
+	case EMLINK: return "EMLINK";
+#endif
+#ifdef EMSGSIZE
+	case EMSGSIZE: return "EMSGSIZE";
+#endif
+#ifdef EMULTIHOP
+	case EMULTIHOP: return "EMULTIHOP";
+#endif
+#ifdef ENAMETOOLONG
+	case ENAMETOOLONG: return "ENAMETOOLONG";
+#endif
+#ifdef ENAVAIL
+	case ENAVAIL: return "ENAVAIL";
+#endif
+#ifdef ENET
+	case ENET: return "ENET";
+#endif
+#ifdef ENETDOWN
+	case ENETDOWN: return "ENETDOWN";
+#endif
+#ifdef ENETRESET
+	case ENETRESET: return "ENETRESET";
+#endif
+#ifdef ENETUNREACH
+	case ENETUNREACH: return "ENETUNREACH";
+#endif
+#ifdef ENFILE
+	case ENFILE: return "ENFILE";
+#endif
+#ifdef ENOANO
+	case ENOANO: return "ENOANO";
+#endif
+#if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR))
+	case ENOBUFS: return "ENOBUFS";
+#endif
+#ifdef ENOCSI
+	case ENOCSI: return "ENOCSI";
+#endif
+#if defined(ENODATA) && (!defined(ECONNREFUSED) || (ENODATA != ECONNREFUSED))
+	case ENODATA: return "ENODATA";
+#endif
+#ifdef ENODEV
+	case ENODEV: return "ENODEV";
+#endif
+#ifdef ENOENT
+	case ENOENT: return "ENOENT";
+#endif
+#ifdef ENOEXEC
+	case ENOEXEC: return "ENOEXEC";
+#endif
+#ifdef ENOLCK
+	case ENOLCK: return "ENOLCK";
+#endif
+#ifdef ENOLINK
+	case ENOLINK: return "ENOLINK";
+#endif
+#ifdef ENOMEM
+	case ENOMEM: return "ENOMEM";
+#endif
+#ifdef ENOMSG
+	case ENOMSG: return "ENOMSG";
+#endif
+#ifdef ENONET
+	case ENONET: return "ENONET";
+#endif
+#ifdef ENOPKG
+	case ENOPKG: return "ENOPKG";
+#endif
+#ifdef ENOPROTOOPT
+	case ENOPROTOOPT: return "ENOPROTOOPT";
+#endif
+#ifdef ENOSPC
+	case ENOSPC: return "ENOSPC";
+#endif
+#if defined(ENOSR) && (!defined(ENAMETOOLONG) || (ENAMETOOLONG != ENOSR))
+	case ENOSR: return "ENOSR";
+#endif
+#if defined(ENOSTR) && (!defined(ENOTTY) || (ENOTTY != ENOSTR))
+	case ENOSTR: return "ENOSTR";
+#endif
+#ifdef ENOSYM
+	case ENOSYM: return "ENOSYM";
+#endif
+#ifdef ENOSYS
+	case ENOSYS: return "ENOSYS";
+#endif
+#ifdef ENOTBLK
+	case ENOTBLK: return "ENOTBLK";
+#endif
+#ifdef ENOTCONN
+	case ENOTCONN: return "ENOTCONN";
+#endif
+#ifdef ENOTDIR
+	case ENOTDIR: return "ENOTDIR";
+#endif
+#if defined(ENOTEMPTY) && (!defined(EEXIST) || (ENOTEMPTY != EEXIST))
+	case ENOTEMPTY: return "ENOTEMPTY";
+#endif
+#ifdef ENOTNAM
+	case ENOTNAM: return "ENOTNAM";
+#endif
+#ifdef ENOTSOCK
+	case ENOTSOCK: return "ENOTSOCK";
+#endif
+#ifdef ENOTSUP
+	case ENOTSUP: return "ENOTSUP";
+#endif
+#ifdef ENOTTY
+	case ENOTTY: return "ENOTTY";
+#endif
+#ifdef ENOTUNIQ
+	case ENOTUNIQ: return "ENOTUNIQ";
+#endif
+#ifdef ENXIO
+	case ENXIO: return "ENXIO";
+#endif
+#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP))
+	case EOPNOTSUPP: return "EOPNOTSUPP";
+#endif
+#ifdef EPERM
+	case EPERM: return "EPERM";
+#endif
+#if defined(EPFNOSUPPORT) && (!defined(ENOLCK) || (ENOLCK != EPFNOSUPPORT))
+	case EPFNOSUPPORT: return "EPFNOSUPPORT";
+#endif
+#ifdef EPIPE
+	case EPIPE: return "EPIPE";
+#endif
+#ifdef EPROCLIM
+	case EPROCLIM: return "EPROCLIM";
+#endif
+#ifdef EPROCUNAVAIL
+	case EPROCUNAVAIL: return "EPROCUNAVAIL";
+#endif
+#ifdef EPROGMISMATCH
+	case EPROGMISMATCH: return "EPROGMISMATCH";
+#endif
+#ifdef EPROGUNAVAIL
+	case EPROGUNAVAIL: return "EPROGUNAVAIL";
+#endif
+#ifdef EPROTO
+	case EPROTO: return "EPROTO";
+#endif
+#ifdef EPROTONOSUPPORT
+	case EPROTONOSUPPORT: return "EPROTONOSUPPORT";
+#endif
+#ifdef EPROTOTYPE
+	case EPROTOTYPE: return "EPROTOTYPE";
+#endif
+#ifdef ERANGE
+	case ERANGE: return "ERANGE";
+#endif
+#if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED))
+	case EREFUSED: return "EREFUSED";
+#endif
+#ifdef EREMCHG
+	case EREMCHG: return "EREMCHG";
+#endif
+#ifdef EREMDEV
+	case EREMDEV: return "EREMDEV";
+#endif
+#ifdef EREMOTE
+	case EREMOTE: return "EREMOTE";
+#endif
+#ifdef EREMOTEIO
+	case EREMOTEIO: return "EREMOTEIO";
+#endif
+#ifdef EREMOTERELEASE
+	case EREMOTERELEASE: return "EREMOTERELEASE";
+#endif
+#ifdef EROFS
+	case EROFS: return "EROFS";
+#endif
+#ifdef ERPCMISMATCH
+	case ERPCMISMATCH: return "ERPCMISMATCH";
+#endif
+#ifdef ERREMOTE
+	case ERREMOTE: return "ERREMOTE";
+#endif
+#ifdef ESHUTDOWN
+	case ESHUTDOWN: return "ESHUTDOWN";
+#endif
+#ifdef ESOCKTNOSUPPORT
+	case ESOCKTNOSUPPORT: return "ESOCKTNOSUPPORT";
+#endif
+#ifdef ESPIPE
+	case ESPIPE: return "ESPIPE";
+#endif
+#ifdef ESRCH
+	case ESRCH: return "ESRCH";
+#endif
+#ifdef ESRMNT
+	case ESRMNT: return "ESRMNT";
+#endif
+#ifdef ESTALE
+	case ESTALE: return "ESTALE";
+#endif
+#ifdef ESUCCESS
+	case ESUCCESS: return "ESUCCESS";
+#endif
+#if defined(ETIME) && (!defined(ELOOP) || (ETIME != ELOOP))
+	case ETIME: return "ETIME";
+#endif
+#if defined(ETIMEDOUT) && (!defined(ENOSTR) || (ETIMEDOUT != ENOSTR))
+	case ETIMEDOUT: return "ETIMEDOUT";
+#endif
+#ifdef ETOOMANYREFS
+	case ETOOMANYREFS: return "ETOOMANYREFS";
+#endif
+#ifdef ETXTBSY
+	case ETXTBSY: return "ETXTBSY";
+#endif
+#ifdef EUCLEAN
+	case EUCLEAN: return "EUCLEAN";
+#endif
+#ifdef EUNATCH
+	case EUNATCH: return "EUNATCH";
+#endif
+#ifdef EUSERS
+	case EUSERS: return "EUSERS";
+#endif
+#ifdef EVERSION
+	case EVERSION: return "EVERSION";
+#endif
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+	case EWOULDBLOCK: return "EWOULDBLOCK";
+#endif
+#ifdef EXDEV
+	case EXDEV: return "EXDEV";
+#endif
+#ifdef EXFULL
+	case EXFULL: return "EXFULL";
+#endif
+    }
+    return "unknown error";
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ErrnoMsg --
+ *
+ *	Return a human-readable message corresponding to a given
+ *	errno value.
+ *
+ * Results:
+ *	The return value is the standard POSIX error message for
+ *	errno.  This procedure is used instead of strerror because
+ *	strerror returns slightly different values on different
+ *	machines (e.g. different capitalizations), which cause
+ *	problems for things such as regression tests.  This procedure
+ *	provides messages for most standard errors, then it calls
+ *	strerror for things it doesn't understand.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_ErrnoMsg(err)
+    int err;			/* Error number (such as in errno variable). */
+{
+    switch (err) {
+#ifdef E2BIG
+	case E2BIG: return "argument list too long";
+#endif
+#ifdef EACCES
+	case EACCES: return "permission denied";
+#endif
+#ifdef EADDRINUSE
+	case EADDRINUSE: return "address already in use";
+#endif
+#ifdef EADDRNOTAVAIL
+	case EADDRNOTAVAIL: return "can't assign requested address";
+#endif
+#ifdef EADV
+	case EADV: return "advertise error";
+#endif
+#ifdef EAFNOSUPPORT
+	case EAFNOSUPPORT: return "address family not supported by protocol family";
+#endif
+#ifdef EAGAIN
+	case EAGAIN: return "resource temporarily unavailable";
+#endif
+#ifdef EALIGN
+	case EALIGN: return "EALIGN";
+#endif
+#if defined(EALREADY) && (!defined(EBUSY) || (EALREADY != EBUSY ))
+	case EALREADY: return "operation already in progress";
+#endif
+#ifdef EBADE
+	case EBADE: return "bad exchange descriptor";
+#endif
+#ifdef EBADF
+	case EBADF: return "bad file number";
+#endif
+#ifdef EBADFD
+	case EBADFD: return "file descriptor in bad state";
+#endif
+#ifdef EBADMSG
+	case EBADMSG: return "not a data message";
+#endif
+#ifdef EBADR
+	case EBADR: return "bad request descriptor";
+#endif
+#ifdef EBADRPC
+	case EBADRPC: return "RPC structure is bad";
+#endif
+#ifdef EBADRQC
+	case EBADRQC: return "bad request code";
+#endif
+#ifdef EBADSLT
+	case EBADSLT: return "invalid slot";
+#endif
+#ifdef EBFONT
+	case EBFONT: return "bad font file format";
+#endif
+#ifdef EBUSY
+	case EBUSY: return "file busy";
+#endif
+#ifdef ECHILD
+	case ECHILD: return "no children";
+#endif
+#ifdef ECHRNG
+	case ECHRNG: return "channel number out of range";
+#endif
+#ifdef ECOMM
+	case ECOMM: return "communication error on send";
+#endif
+#ifdef ECONNABORTED
+	case ECONNABORTED: return "software caused connection abort";
+#endif
+#ifdef ECONNREFUSED
+	case ECONNREFUSED: return "connection refused";
+#endif
+#ifdef ECONNRESET
+	case ECONNRESET: return "connection reset by peer";
+#endif
+#if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK))
+	case EDEADLK: return "resource deadlock avoided";
+#endif
+#if defined(EDEADLOCK) && (!defined(EDEADLK) || (EDEADLOCK != EDEADLK))
+	case EDEADLOCK: return "resource deadlock avoided";
+#endif
+#ifdef EDESTADDRREQ
+	case EDESTADDRREQ: return "destination address required";
+#endif
+#ifdef EDIRTY
+	case EDIRTY: return "mounting a dirty fs w/o force";
+#endif
+#ifdef EDOM
+	case EDOM: return "math argument out of range";
+#endif
+#ifdef EDOTDOT
+	case EDOTDOT: return "cross mount point";
+#endif
+#ifdef EDQUOT
+	case EDQUOT: return "disk quota exceeded";
+#endif
+#ifdef EDUPPKG
+	case EDUPPKG: return "duplicate package name";
+#endif
+#ifdef EEXIST
+	case EEXIST: return "file already exists";
+#endif
+#ifdef EFAULT
+	case EFAULT: return "bad address in system call argument";
+#endif
+#ifdef EFBIG
+	case EFBIG: return "file too large";
+#endif
+#ifdef EHOSTDOWN
+	case EHOSTDOWN: return "host is down";
+#endif
+#ifdef EHOSTUNREACH
+	case EHOSTUNREACH: return "host is unreachable";
+#endif
+#if defined(EIDRM) && (!defined(EINPROGRESS) || (EIDRM != EINPROGRESS))
+	case EIDRM: return "identifier removed";
+#endif
+#ifdef EINIT
+	case EINIT: return "initialization error";
+#endif
+#ifdef EINPROGRESS
+	case EINPROGRESS: return "operation now in progress";
+#endif
+#ifdef EINTR
+	case EINTR: return "interrupted system call";
+#endif
+#ifdef EINVAL
+	case EINVAL: return "invalid argument";
+#endif
+#ifdef EIO
+	case EIO: return "I/O error";
+#endif
+#ifdef EISCONN
+	case EISCONN: return "socket is already connected";
+#endif
+#ifdef EISDIR
+	case EISDIR: return "illegal operation on a directory";
+#endif
+#ifdef EISNAME
+	case EISNAM: return "is a name file";
+#endif
+#ifdef ELBIN
+	case ELBIN: return "ELBIN";
+#endif
+#ifdef EL2HLT
+	case EL2HLT: return "level 2 halted";
+#endif
+#ifdef EL2NSYNC
+	case EL2NSYNC: return "level 2 not synchronized";
+#endif
+#ifdef EL3HLT
+	case EL3HLT: return "level 3 halted";
+#endif
+#ifdef EL3RST
+	case EL3RST: return "level 3 reset";
+#endif
+#ifdef ELIBACC
+	case ELIBACC: return "can not access a needed shared library";
+#endif
+#ifdef ELIBBAD
+	case ELIBBAD: return "accessing a corrupted shared library";
+#endif
+#ifdef ELIBEXEC
+	case ELIBEXEC: return "can not exec a shared library directly";
+#endif
+#ifdef ELIBMAX
+	case ELIBMAX: return
+		"attempting to link in more shared libraries than system limit";
+#endif
+#ifdef ELIBSCN
+	case ELIBSCN: return ".lib section in a.out corrupted";
+#endif
+#ifdef ELNRNG
+	case ELNRNG: return "link number out of range";
+#endif
+#if defined(ELOOP) && (!defined(ENOENT) || (ELOOP != ENOENT))
+	case ELOOP: return "too many levels of symbolic links";
+#endif
+#ifdef EMFILE
+	case EMFILE: return "too many open files";
+#endif
+#ifdef EMLINK
+	case EMLINK: return "too many links";
+#endif
+#ifdef EMSGSIZE
+	case EMSGSIZE: return "message too long";
+#endif
+#ifdef EMULTIHOP
+	case EMULTIHOP: return "multihop attempted";
+#endif
+#ifdef ENAMETOOLONG
+	case ENAMETOOLONG: return "file name too long";
+#endif
+#ifdef ENAVAIL
+	case ENAVAIL: return "not available";
+#endif
+#ifdef ENET
+	case ENET: return "ENET";
+#endif
+#ifdef ENETDOWN
+	case ENETDOWN: return "network is down";
+#endif
+#ifdef ENETRESET
+	case ENETRESET: return "network dropped connection on reset";
+#endif
+#ifdef ENETUNREACH
+	case ENETUNREACH: return "network is unreachable";
+#endif
+#ifdef ENFILE
+	case ENFILE: return "file table overflow";
+#endif
+#ifdef ENOANO
+	case ENOANO: return "anode table overflow";
+#endif
+#if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR))
+	case ENOBUFS: return "no buffer space available";
+#endif
+#ifdef ENOCSI
+	case ENOCSI: return "no CSI structure available";
+#endif
+#if defined(ENODATA) && (!defined(ECONNREFUSED) || (ENODATA != ECONNREFUSED))
+	case ENODATA: return "no data available";
+#endif
+#ifdef ENODEV
+	case ENODEV: return "no such device";
+#endif
+#ifdef ENOENT
+	case ENOENT: return "no such file or directory";
+#endif
+#ifdef ENOEXEC
+	case ENOEXEC: return "exec format error";
+#endif
+#ifdef ENOLCK
+	case ENOLCK: return "no locks available";
+#endif
+#ifdef ENOLINK
+	case ENOLINK: return "link has be severed";
+#endif
+#ifdef ENOMEM
+	case ENOMEM: return "not enough memory";
+#endif
+#ifdef ENOMSG
+	case ENOMSG: return "no message of desired type";
+#endif
+#ifdef ENONET
+	case ENONET: return "machine is not on the network";
+#endif
+#ifdef ENOPKG
+	case ENOPKG: return "package not installed";
+#endif
+#ifdef ENOPROTOOPT
+	case ENOPROTOOPT: return "bad proocol option";
+#endif
+#ifdef ENOSPC
+	case ENOSPC: return "no space left on device";
+#endif
+#if defined(ENOSR) && (!defined(ENAMETOOLONG) || (ENAMETOOLONG != ENOSR))
+	case ENOSR: return "out of stream resources";
+#endif
+#if defined(ENOSTR) && (!defined(ENOTTY) || (ENOTTY != ENOSTR))
+	case ENOSTR: return "not a stream device";
+#endif
+#ifdef ENOSYM
+	case ENOSYM: return "unresolved symbol name";
+#endif
+#ifdef ENOSYS
+	case ENOSYS: return "function not implemented";
+#endif
+#ifdef ENOTBLK
+	case ENOTBLK: return "block device required";
+#endif
+#ifdef ENOTCONN
+	case ENOTCONN: return "socket is not connected";
+#endif
+#ifdef ENOTDIR
+	case ENOTDIR: return "not a directory";
+#endif
+#if defined(ENOTEMPTY) && (!defined(EEXIST) || (ENOTEMPTY != EEXIST))
+	case ENOTEMPTY: return "directory not empty";
+#endif
+#ifdef ENOTNAM
+	case ENOTNAM: return "not a name file";
+#endif
+#ifdef ENOTSOCK
+	case ENOTSOCK: return "socket operation on non-socket";
+#endif
+#ifdef ENOTSUP
+	case ENOTSUP: return "operation not supported";
+#endif
+#ifdef ENOTTY
+	case ENOTTY: return "inappropriate device for ioctl";
+#endif
+#ifdef ENOTUNIQ
+	case ENOTUNIQ: return "name not unique on network";
+#endif
+#ifdef ENXIO
+	case ENXIO: return "no such device or address";
+#endif
+#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP))
+	case EOPNOTSUPP: return "operation not supported on socket";
+#endif
+#ifdef EPERM
+	case EPERM: return "not owner";
+#endif
+#if defined(EPFNOSUPPORT) && (!defined(ENOLCK) || (ENOLCK != EPFNOSUPPORT))
+	case EPFNOSUPPORT: return "protocol family not supported";
+#endif
+#ifdef EPIPE
+	case EPIPE: return "broken pipe";
+#endif
+#ifdef EPROCLIM
+	case EPROCLIM: return "too many processes";
+#endif
+#ifdef EPROCUNAVAIL
+	case EPROCUNAVAIL: return "bad procedure for program";
+#endif
+#ifdef EPROGMISMATCH
+	case EPROGMISMATCH: return "program version wrong";
+#endif
+#ifdef EPROGUNAVAIL
+	case EPROGUNAVAIL: return "RPC program not available";
+#endif
+#ifdef EPROTO
+	case EPROTO: return "protocol error";
+#endif
+#ifdef EPROTONOSUPPORT
+	case EPROTONOSUPPORT: return "protocol not suppored";
+#endif
+#ifdef EPROTOTYPE
+	case EPROTOTYPE: return "protocol wrong type for socket";
+#endif
+#ifdef ERANGE
+	case ERANGE: return "math result unrepresentable";
+#endif
+#if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED))
+	case EREFUSED: return "EREFUSED";
+#endif
+#ifdef EREMCHG
+	case EREMCHG: return "remote address changed";
+#endif
+#ifdef EREMDEV
+	case EREMDEV: return "remote device";
+#endif
+#ifdef EREMOTE
+	case EREMOTE: return "pathname hit remote file system";
+#endif
+#ifdef EREMOTEIO
+	case EREMOTEIO: return "remote i/o error";
+#endif
+#ifdef EREMOTERELEASE
+	case EREMOTERELEASE: return "EREMOTERELEASE";
+#endif
+#ifdef EROFS
+	case EROFS: return "read-only file system";
+#endif
+#ifdef ERPCMISMATCH
+	case ERPCMISMATCH: return "RPC version is wrong";
+#endif
+#ifdef ERREMOTE
+	case ERREMOTE: return "object is remote";
+#endif
+#ifdef ESHUTDOWN
+	case ESHUTDOWN: return "can't send afer socket shutdown";
+#endif
+#ifdef ESOCKTNOSUPPORT
+	case ESOCKTNOSUPPORT: return "socket type not supported";
+#endif
+#ifdef ESPIPE
+	case ESPIPE: return "invalid seek";
+#endif
+#ifdef ESRCH
+	case ESRCH: return "no such process";
+#endif
+#ifdef ESRMNT
+	case ESRMNT: return "srmount error";
+#endif
+#ifdef ESTALE
+	case ESTALE: return "stale remote file handle";
+#endif
+#ifdef ESUCCESS
+	case ESUCCESS: return "Error 0";
+#endif
+#if defined(ETIME) && (!defined(ELOOP) || (ETIME != ELOOP))
+	case ETIME: return "timer expired";
+#endif
+#if defined(ETIMEDOUT) && (!defined(ENOSTR) || (ETIMEDOUT != ENOSTR))
+	case ETIMEDOUT: return "connection timed out";
+#endif
+#ifdef ETOOMANYREFS
+	case ETOOMANYREFS: return "too many references: can't splice";
+#endif
+#ifdef ETXTBSY
+	case ETXTBSY: return "text file or pseudo-device busy";
+#endif
+#ifdef EUCLEAN
+	case EUCLEAN: return "structure needs cleaning";
+#endif
+#ifdef EUNATCH
+	case EUNATCH: return "protocol driver not attached";
+#endif
+#ifdef EUSERS
+	case EUSERS: return "too many users";
+#endif
+#ifdef EVERSION
+	case EVERSION: return "version mismatch";
+#endif
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+	case EWOULDBLOCK: return "operation would block";
+#endif
+#ifdef EXDEV
+	case EXDEV: return "cross-domain link";
+#endif
+#ifdef EXFULL
+	case EXFULL: return "message tables full";
+#endif
+	default:
+#ifdef NO_STRERROR
+	    return "unknown POSIX error";
+#else
+	    return strerror(errno);
+#endif
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SignalId --
+ *
+ *	Return a textual identifier for a signal number.
+ *
+ * Results:
+ *	This procedure returns a machine-readable textual identifier
+ *	that corresponds to sig.  The identifier is the same as the
+ *	#define name in signal.h.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_SignalId(sig)
+    int sig;			/* Number of signal. */
+{
+    switch (sig) {
+#ifdef SIGABRT
+	case SIGABRT: return "SIGABRT";
+#endif
+#ifdef SIGALRM
+	case SIGALRM: return "SIGALRM";
+#endif
+#ifdef SIGBUS
+	case SIGBUS: return "SIGBUS";
+#endif
+#ifdef SIGCHLD
+	case SIGCHLD: return "SIGCHLD";
+#endif
+#if defined(SIGCLD) && (!defined(SIGCHLD) || (SIGCLD != SIGCHLD))
+	case SIGCLD: return "SIGCLD";
+#endif
+#ifdef SIGCONT
+	case SIGCONT: return "SIGCONT";
+#endif
+#if defined(SIGEMT) && (!defined(SIGXCPU) || (SIGEMT != SIGXCPU))
+	case SIGEMT: return "SIGEMT";
+#endif
+#ifdef SIGFPE
+	case SIGFPE: return "SIGFPE";
+#endif
+#ifdef SIGHUP
+	case SIGHUP: return "SIGHUP";
+#endif
+#ifdef SIGILL
+	case SIGILL: return "SIGILL";
+#endif
+#ifdef SIGINT
+	case SIGINT: return "SIGINT";
+#endif
+#ifdef SIGIO
+	case SIGIO: return "SIGIO";
+#endif
+#if defined(SIGIOT) && (!defined(SIGABRT) || (SIGIOT != SIGABRT))
+	case SIGIOT: return "SIGIOT";
+#endif
+#ifdef SIGKILL
+	case SIGKILL: return "SIGKILL";
+#endif
+#if defined(SIGLOST) && (!defined(SIGIOT) || (SIGLOST != SIGIOT)) && (!defined(SIGURG) || (SIGLOST != SIGURG)) && (!defined(SIGPROF) || (SIGLOST != SIGPROF)) && (!defined(SIGIO) || (SIGLOST != SIGIO))
+	case SIGLOST: return "SIGLOST";
+#endif
+#ifdef SIGPIPE
+	case SIGPIPE: return "SIGPIPE";
+#endif
+#if defined(SIGPOLL) && (!defined(SIGIO) || (SIGPOLL != SIGIO))
+	case SIGPOLL: return "SIGPOLL";
+#endif
+#ifdef SIGPROF
+	case SIGPROF: return "SIGPROF";
+#endif
+#if defined(SIGPWR) && (!defined(SIGXFSZ) || (SIGPWR != SIGXFSZ))
+	case SIGPWR: return "SIGPWR";
+#endif
+#ifdef SIGQUIT
+	case SIGQUIT: return "SIGQUIT";
+#endif
+#ifdef SIGSEGV
+	case SIGSEGV: return "SIGSEGV";
+#endif
+#ifdef SIGSTOP
+	case SIGSTOP: return "SIGSTOP";
+#endif
+#ifdef SIGSYS
+	case SIGSYS: return "SIGSYS";
+#endif
+#ifdef SIGTERM
+	case SIGTERM: return "SIGTERM";
+#endif
+#ifdef SIGTRAP
+	case SIGTRAP: return "SIGTRAP";
+#endif
+#ifdef SIGTSTP
+	case SIGTSTP: return "SIGTSTP";
+#endif
+#ifdef SIGTTIN
+	case SIGTTIN: return "SIGTTIN";
+#endif
+#ifdef SIGTTOU
+	case SIGTTOU: return "SIGTTOU";
+#endif
+#if defined(SIGURG) && (!defined(SIGIO) || (SIGURG != SIGIO))
+	case SIGURG: return "SIGURG";
+#endif
+#if defined(SIGUSR1) && (!defined(SIGIO) || (SIGUSR1 != SIGIO))
+	case SIGUSR1: return "SIGUSR1";
+#endif
+#if defined(SIGUSR2) && (!defined(SIGURG) || (SIGUSR2 != SIGURG))
+	case SIGUSR2: return "SIGUSR2";
+#endif
+#ifdef SIGVTALRM
+	case SIGVTALRM: return "SIGVTALRM";
+#endif
+#ifdef SIGWINCH
+	case SIGWINCH: return "SIGWINCH";
+#endif
+#ifdef SIGXCPU
+	case SIGXCPU: return "SIGXCPU";
+#endif
+#ifdef SIGXFSZ
+	case SIGXFSZ: return "SIGXFSZ";
+#endif
+    }
+    return "unknown signal";
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SignalMsg --
+ *
+ *	Return a human-readable message describing a signal.
+ *
+ * Results:
+ *	This procedure returns a string describing sig that should
+ *	make sense to a human.  It may not be easy for a machine
+ *	to parse.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_SignalMsg(sig)
+    int sig;			/* Number of signal. */
+{
+    switch (sig) {
+#ifdef SIGABRT
+	case SIGABRT: return "SIGABRT";
+#endif
+#ifdef SIGALRM
+	case SIGALRM: return "alarm clock";
+#endif
+#ifdef SIGBUS
+	case SIGBUS: return "bus error";
+#endif
+#ifdef SIGCHLD
+	case SIGCHLD: return "child status changed";
+#endif
+#if defined(SIGCLD) && (!defined(SIGCHLD) || (SIGCLD != SIGCHLD))
+	case SIGCLD: return "child status changed";
+#endif
+#ifdef SIGCONT
+	case SIGCONT: return "continue after stop";
+#endif
+#if defined(SIGEMT) && (!defined(SIGXCPU) || (SIGEMT != SIGXCPU))
+	case SIGEMT: return "EMT instruction";
+#endif
+#ifdef SIGFPE
+	case SIGFPE: return "floating-point exception";
+#endif
+#ifdef SIGHUP
+	case SIGHUP: return "hangup";
+#endif
+#ifdef SIGILL
+	case SIGILL: return "illegal instruction";
+#endif
+#ifdef SIGINT
+	case SIGINT: return "interrupt";
+#endif
+#ifdef SIGIO
+	case SIGIO: return "input/output possible on file";
+#endif
+#if defined(SIGIOT) && (!defined(SIGABRT) || (SIGABRT != SIGIOT))
+	case SIGIOT: return "IOT instruction";
+#endif
+#ifdef SIGKILL
+	case SIGKILL: return "kill signal";
+#endif
+#if defined(SIGLOST) && (!defined(SIGIOT) || (SIGLOST != SIGIOT)) && (!defined(SIGURG) || (SIGLOST != SIGURG)) && (!defined(SIGPROF) || (SIGLOST != SIGPROF)) && (!defined(SIGIO) || (SIGLOST != SIGIO))
+	case SIGLOST: return "resource lost";
+#endif
+#ifdef SIGPIPE
+	case SIGPIPE: return "write on pipe with no readers";
+#endif
+#if defined(SIGPOLL) && (!defined(SIGIO) || (SIGPOLL != SIGIO))
+	case SIGPOLL: return "input/output possible on file";
+#endif
+#ifdef SIGPROF
+	case SIGPROF: return "profiling alarm";
+#endif
+#if defined(SIGPWR) && (!defined(SIGXFSZ) || (SIGPWR != SIGXFSZ))
+	case SIGPWR: return "power-fail restart";
+#endif
+#ifdef SIGQUIT
+	case SIGQUIT: return "quit signal";
+#endif
+#ifdef SIGSEGV
+	case SIGSEGV: return "segmentation violation";
+#endif
+#ifdef SIGSTOP
+	case SIGSTOP: return "stop";
+#endif
+#ifdef SIGSYS
+	case SIGSYS: return "bad argument to system call";
+#endif
+#ifdef SIGTERM
+	case SIGTERM: return "software termination signal";
+#endif
+#ifdef SIGTRAP
+	case SIGTRAP: return "trace trap";
+#endif
+#ifdef SIGTSTP
+	case SIGTSTP: return "stop signal from tty";
+#endif
+#ifdef SIGTTIN
+	case SIGTTIN: return "background tty read";
+#endif
+#ifdef SIGTTOU
+	case SIGTTOU: return "background tty write";
+#endif
+#if defined(SIGURG) && (!defined(SIGIO) || (SIGURG != SIGIO))
+	case SIGURG: return "urgent I/O condition";
+#endif
+#if defined(SIGUSR1) && (!defined(SIGIO) || (SIGUSR1 != SIGIO))
+	case SIGUSR1: return "user-defined signal 1";
+#endif
+#if defined(SIGUSR2) && (!defined(SIGURG) || (SIGUSR2 != SIGURG))
+	case SIGUSR2: return "user-defined signal 2";
+#endif
+#ifdef SIGVTALRM
+	case SIGVTALRM: return "virtual time alarm";
+#endif
+#ifdef SIGWINCH
+	case SIGWINCH: return "window changed";
+#endif
+#ifdef SIGXCPU
+	case SIGXCPU: return "exceeded CPU time limit";
+#endif
+#ifdef SIGXFSZ
+	case SIGXFSZ: return "exceeded file size limit";
+#endif
+    }
+    return "unknown signal";
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclPreserve.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclPreserve.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclPreserve.c	(revision 5)
@@ -0,0 +1,96 @@
+/* 
+ * tclPreserve.c --
+ *
+ *	This file contains a collection of procedures that are used
+ *	to make sure that widget records and other data structures
+ *	aren't reallocated when there are nested procedures that
+ *	depend on their existence.
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclPreserve.c,v 1.1 2008-06-04 13:58:10 demin Exp $
+ */
+
+#include "tclInt.h"
+
+/*
+ * The following data structure is used to keep track of all the
+ * Tcl_Preserve calls that are still in effect.  It grows as needed
+ * to accommodate any number of calls in effect.
+ */
+
+typedef struct {
+    ClientData clientData;	/* Address of preserved block. */
+    int refCount;		/* Number of Tcl_Preserve calls in effect
+				 * for block. */
+    int mustFree;		/* Non-zero means Tcl_EventuallyFree was
+				 * called while a Tcl_Preserve call was in
+				 * effect, so the structure must be freed
+				 * when refCount becomes zero. */
+    Tcl_FreeProc *freeProc;	/* Procedure to call to free. */
+} Reference;
+
+static Reference *refArray;	/* First in array of references. */
+static int inUse = 0;		/* Count of structures currently in use
+				 * in refArray. */
+#define INITIAL_SIZE 2
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_EventuallyFree --
+ *
+ *	Free up a block of memory, unless a call to Tcl_Preserve is in
+ *	effect for that block.  In this case, defer the free until all
+ *	calls to Tcl_Preserve have been undone by matching calls to
+ *	Tcl_Release.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Ptr may be released by calling free().
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_EventuallyFree(clientData, freeProc)
+    ClientData clientData;	/* Pointer to malloc'ed block of memory. */
+    Tcl_FreeProc *freeProc;	/* Procedure to actually do free. */
+{
+    Reference *refPtr;
+    int i;
+
+    /*
+     * See if there is a reference for this pointer.  If so, set its
+     * "mustFree" flag (the flag had better not be set already!).
+     */
+
+    for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) {
+	if (refPtr->clientData != clientData) {
+	    continue;
+	}
+	if (refPtr->mustFree) {
+	    panic("Tcl_EventuallyFree called twice for 0x%x\n", clientData);
+        }
+        refPtr->mustFree = 1;
+	refPtr->freeProc = freeProc;
+        return;
+    }
+
+    /*
+     * No reference for this block.  Free it now.
+     */
+
+    if ((freeProc == TCL_DYNAMIC)
+	    || (freeProc == (Tcl_FreeProc *) free)) {
+	ckfree((char *) clientData);
+    } else {
+	(*freeProc)((char *)clientData);
+    }
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclProc.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclProc.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclProc.c	(revision 5)
@@ -0,0 +1,1543 @@
+/* 
+ * tclProc.c --
+ *
+ *	This file contains routines that implement Tcl procedures,
+ *	including the "proc" and "uplevel" commands.
+ *
+ * Copyright (c) 1987-1993 The Regents of the University of California.
+ * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclProc.c,v 1.1 2008-06-04 13:58:10 demin Exp $
+ */
+
+#include "tclInt.h"
+#include "tclCompile.h"
+
+/*
+ * Prototypes for static functions in this file
+ */
+
+static void	ProcBodyDup _ANSI_ARGS_((Tcl_Obj *srcPtr, Tcl_Obj *dupPtr));
+static void	ProcBodyFree _ANSI_ARGS_((Tcl_Obj *objPtr));
+static int	ProcBodySetFromAny _ANSI_ARGS_((Tcl_Interp *interp,
+		Tcl_Obj *objPtr));
+static void	ProcBodyUpdateString _ANSI_ARGS_((Tcl_Obj *objPtr));
+
+/*
+ * The ProcBodyObjType type
+ */
+
+Tcl_ObjType tclProcBodyType = {
+    "procbody",			/* name for this type */
+    ProcBodyFree,		/* FreeInternalRep procedure */
+    ProcBodyDup,		/* DupInternalRep procedure */
+    ProcBodyUpdateString,	/* UpdateString procedure */
+    ProcBodySetFromAny		/* SetFromAny procedure */
+};
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ProcObjCmd --
+ *
+ *	This object-based procedure is invoked to process the "proc" Tcl 
+ *	command. See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result value.
+ *
+ * Side effects:
+ *	A new procedure gets created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_ProcObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    register Interp *iPtr = (Interp *) interp;
+    Proc *procPtr;
+    char *fullName, *procName;
+    Namespace *nsPtr, *altNsPtr, *cxtNsPtr;
+    Tcl_Command cmd;
+    Tcl_DString ds;
+
+    if (objc != 4) {
+	Tcl_WrongNumArgs(interp, 1, objv, "name args body");
+	return TCL_ERROR;
+    }
+
+    /*
+     * Determine the namespace where the procedure should reside. Unless
+     * the command name includes namespace qualifiers, this will be the
+     * current namespace.
+     */
+    
+    fullName = Tcl_GetStringFromObj(objv[1], (int *) NULL);
+    TclGetNamespaceForQualName(interp, fullName, (Namespace *) NULL,
+       /*flags*/ 0, &nsPtr, &altNsPtr, &cxtNsPtr, &procName);
+
+    if (nsPtr == NULL) {
+        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		"can't create procedure \"", fullName,
+		"\": unknown namespace", (char *) NULL);
+        return TCL_ERROR;
+    }
+    if (procName == NULL) {
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		"can't create procedure \"", fullName,
+		"\": bad procedure name", (char *) NULL);
+        return TCL_ERROR;
+    }
+    if ((nsPtr != iPtr->globalNsPtr)
+	    && (procName != NULL) && (procName[0] == ':')) {
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		"can't create procedure \"", procName,
+		"\" in non-global namespace with name starting with \":\"",
+	        (char *) NULL);
+        return TCL_ERROR;
+    }
+
+    /*
+     *  Create the data structure to represent the procedure.
+     */
+    if (TclCreateProc(interp, nsPtr, procName, objv[2], objv[3],
+        &procPtr) != TCL_OK) {
+        return TCL_ERROR;
+    }
+
+    /*
+     * Now create a command for the procedure. This will initially be in
+     * the current namespace unless the procedure's name included namespace
+     * qualifiers. To create the new command in the right namespace, we
+     * generate a fully qualified name for it.
+     */
+
+    Tcl_DStringInit(&ds);
+    if (nsPtr != iPtr->globalNsPtr) {
+	Tcl_DStringAppend(&ds, nsPtr->fullName, -1);
+	Tcl_DStringAppend(&ds, "::", 2);
+    }
+    Tcl_DStringAppend(&ds, procName, -1);
+    
+    Tcl_CreateCommand(interp, Tcl_DStringValue(&ds), TclProcInterpProc,
+	    (ClientData) procPtr, TclProcDeleteProc);
+    cmd = Tcl_CreateObjCommand(interp, Tcl_DStringValue(&ds),
+	    TclObjInterpProc, (ClientData) procPtr, TclProcDeleteProc);
+
+    /*
+     * Now initialize the new procedure's cmdPtr field. This will be used
+     * later when the procedure is called to determine what namespace the
+     * procedure will run in. This will be different than the current
+     * namespace if the proc was renamed into a different namespace.
+     */
+    
+    procPtr->cmdPtr = (Command *) cmd;
+
+    return TCL_OK;
+}
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCreateProc --
+ *
+ *	Creates the data associated with a Tcl procedure definition.
+ *	This procedure knows how to handle two types of body objects:
+ *	strings and procbody. Strings are the traditional (and common) value
+ *	for bodies, procbody are values created by extensions that have
+ *	loaded a previously compiled script.
+ *
+ * Results:
+ *	Returns TCL_OK on success, along with a pointer to a Tcl
+ *	procedure definition in procPtrPtr.  This definition should
+ *	be freed by calling TclCleanupProc() when it is no longer
+ *	needed.  Returns TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ *	If anything goes wrong, this procedure returns an error
+ *	message in the interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+int
+TclCreateProc(interp, nsPtr, procName, argsPtr, bodyPtr, procPtrPtr)
+    Tcl_Interp *interp;         /* interpreter containing proc */
+    Namespace *nsPtr;           /* namespace containing this proc */
+    char *procName;             /* unqualified name of this proc */
+    Tcl_Obj *argsPtr;           /* description of arguments */
+    Tcl_Obj *bodyPtr;           /* command body */
+    Proc **procPtrPtr;          /* returns:  pointer to proc data */
+{
+    Interp *iPtr = (Interp*)interp;
+    char **argArray = NULL;
+
+    register Proc *procPtr;
+    int i, length, result, numArgs;
+    char *args, *bytes, *p;
+    register CompiledLocal *localPtr;
+    Tcl_Obj *defPtr;
+    int precompiled = 0;
+    
+    if (bodyPtr->typePtr == &tclProcBodyType) {
+        /*
+         * Because the body is a TclProProcBody, the actual body is already
+         * compiled, and it is not shared with anyone else, so it's OK not to
+         * unshare it (as a matter of fact, it is bad to unshare it, because
+         * there may be no source code).
+         *
+         * We don't create and initialize a Proc structure for the procedure;
+         * rather, we use what is in the body object. Note that
+         * we initialize its cmdPtr field below after we've created the command
+         * for the procedure. We increment the ref count of the Proc struct
+         * since the command (soon to be created) will be holding a reference
+         * to it.
+         */
+    
+        procPtr = (Proc *) bodyPtr->internalRep.otherValuePtr;
+        procPtr->iPtr = iPtr;
+        procPtr->refCount++;
+        precompiled = 1;
+    } else {
+        /*
+         * If the procedure's body object is shared because its string value is
+         * identical to, e.g., the body of another procedure, we must create a
+         * private copy for this procedure to use. Such sharing of procedure
+         * bodies is rare but can cause problems. A procedure body is compiled
+         * in a context that includes the number of compiler-allocated "slots"
+         * for local variables. Each formal parameter is given a local variable
+         * slot (the "procPtr->numCompiledLocals = numArgs" assignment
+         * below). This means that the same code can not be shared by two
+         * procedures that have a different number of arguments, even if their
+         * bodies are identical. Note that we don't use Tcl_DuplicateObj since
+         * we would not want any bytecode internal representation.
+         */
+
+        if (Tcl_IsShared(bodyPtr)) {
+            bytes = Tcl_GetStringFromObj(bodyPtr, &length);
+            bodyPtr = Tcl_NewStringObj(bytes, length);
+        }
+
+        /*
+         * Create and initialize a Proc structure for the procedure. Note that
+         * we initialize its cmdPtr field below after we've created the command
+         * for the procedure. We increment the ref count of the procedure's
+         * body object since there will be a reference to it in the Proc
+         * structure.
+         */
+    
+        Tcl_IncrRefCount(bodyPtr);
+
+        procPtr = (Proc *) ckalloc(sizeof(Proc));
+        procPtr->iPtr = iPtr;
+        procPtr->refCount = 1;
+        procPtr->bodyPtr = bodyPtr;
+        procPtr->numArgs  = 0;	/* actual argument count is set below. */
+        procPtr->numCompiledLocals = 0;
+        procPtr->firstLocalPtr = NULL;
+        procPtr->lastLocalPtr = NULL;
+    }
+    
+    /*
+     * Break up the argument list into argument specifiers, then process
+     * each argument specifier.
+     * If the body is precompiled, processing is limited to checking that
+     * the the parsed argument is consistent with the one stored in the
+     * Proc.
+     * THIS FAILS IF THE ARG LIST OBJECT'S STRING REP CONTAINS NULLS.
+     */
+
+    args = Tcl_GetStringFromObj(argsPtr, &length);
+    result = Tcl_SplitList(interp, args, &numArgs, &argArray);
+    if (result != TCL_OK) {
+        goto procError;
+    }
+
+    if (precompiled) {
+        if (numArgs > procPtr->numArgs) {
+            char buf[128];
+            sprintf(buf, "\": arg list contains %d entries, precompiled header expects %d",
+                    numArgs, procPtr->numArgs);
+            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                    "procedure \"", procName,
+                    buf, (char *) NULL);
+            goto procError;
+        }
+        localPtr = procPtr->firstLocalPtr;
+    } else {
+        procPtr->numArgs = numArgs;
+        procPtr->numCompiledLocals = numArgs;
+    }
+    for (i = 0;  i < numArgs;  i++) {
+        int fieldCount, nameLength, valueLength;
+        char **fieldValues;
+
+        /*
+         * Now divide the specifier up into name and default.
+         */
+
+        result = Tcl_SplitList(interp, argArray[i], &fieldCount,
+                &fieldValues);
+        if (result != TCL_OK) {
+            goto procError;
+        }
+        if (fieldCount > 2) {
+            ckfree((char *) fieldValues);
+            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                    "too many fields in argument specifier \"",
+                    argArray[i], "\"", (char *) NULL);
+            goto procError;
+        }
+        if ((fieldCount == 0) || (*fieldValues[0] == 0)) {
+            ckfree((char *) fieldValues);
+            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                    "procedure \"", procName,
+                    "\" has argument with no name", (char *) NULL);
+            goto procError;
+        }
+	
+        nameLength = strlen(fieldValues[0]);
+        if (fieldCount == 2) {
+            valueLength = strlen(fieldValues[1]);
+        } else {
+            valueLength = 0;
+        }
+
+        /*
+         * Check that the formal parameter name is a scalar.
+         */
+
+        p = fieldValues[0];
+        while (*p != '\0') {
+            if (*p == '(') {
+                char *q = p;
+                do {
+		    q++;
+		} while (*q != '\0');
+		q--;
+		if (*q == ')') { /* we have an array element */
+		    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		            "procedure \"", procName,
+		            "\" has formal parameter \"", fieldValues[0],
+			    "\" that is an array element",
+			    (char *) NULL);
+		    ckfree((char *) fieldValues);
+		    goto procError;
+		}
+	    }
+	    p++;
+	}
+
+        if (precompiled) {
+            /*
+             * compare the parsed argument with the stored one
+             */
+
+            if ((localPtr->nameLength != nameLength)
+                    || (strcmp(localPtr->name, fieldValues[0]))
+                    || (localPtr->frameIndex != i)
+                    || (localPtr->flags != (VAR_SCALAR | VAR_ARGUMENT))
+                    || ((localPtr->defValuePtr == NULL)
+                            && (fieldCount == 2))
+                    || ((localPtr->defValuePtr != NULL)
+                            && (fieldCount != 2))) {
+                char buf[128];
+                sprintf(buf, "\": formal parameter %d is inconsistent with precompiled body",
+                        i);
+                Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                        "procedure \"", procName,
+                        buf, (char *) NULL);
+                ckfree((char *) fieldValues);
+                goto procError;
+            }
+
+            /*
+             * compare the default value if any
+             */
+
+            if (localPtr->defValuePtr != NULL) {
+                int tmpLength;
+                char *tmpPtr = Tcl_GetStringFromObj(localPtr->defValuePtr,
+                        &tmpLength);
+                if ((valueLength != tmpLength)
+                        || (strncmp(fieldValues[1], tmpPtr,
+                                (size_t) tmpLength))) {
+                    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                            "procedure \"", procName,
+                            "\": formal parameter \"",
+                            fieldValues[0],
+                            "\" has default value inconsistent with precompiled body",
+                            (char *) NULL);
+                    ckfree((char *) fieldValues);
+                    goto procError;
+                }
+            }
+
+            localPtr = localPtr->nextPtr;
+        } else {
+            /*
+             * Allocate an entry in the runtime procedure frame's array of
+             * local variables for the argument. 
+             */
+
+            localPtr = (CompiledLocal *) ckalloc((unsigned) 
+                    (sizeof(CompiledLocal) - sizeof(localPtr->name)
+                            + nameLength+1));
+            if (procPtr->firstLocalPtr == NULL) {
+                procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr;
+            } else {
+                procPtr->lastLocalPtr->nextPtr = localPtr;
+                procPtr->lastLocalPtr = localPtr;
+            }
+            localPtr->nextPtr = NULL;
+            localPtr->nameLength = nameLength;
+            localPtr->frameIndex = i;
+            localPtr->flags = VAR_SCALAR | VAR_ARGUMENT;
+            localPtr->resolveInfo = NULL;
+	
+            if (fieldCount == 2) {
+                localPtr->defValuePtr =
+		    Tcl_NewStringObj(fieldValues[1], valueLength);
+                Tcl_IncrRefCount(localPtr->defValuePtr);
+            } else {
+                localPtr->defValuePtr = NULL;
+            }
+            strcpy(localPtr->name, fieldValues[0]);
+	}
+
+        ckfree((char *) fieldValues);
+    }
+
+    /*
+     * Now initialize the new procedure's cmdPtr field. This will be used
+     * later when the procedure is called to determine what namespace the
+     * procedure will run in. This will be different than the current
+     * namespace if the proc was renamed into a different namespace.
+     */
+    
+    *procPtrPtr = procPtr;
+    ckfree((char *) argArray);
+    return TCL_OK;
+
+procError:
+    if (precompiled) {
+        procPtr->refCount--;
+    } else {
+        Tcl_DecrRefCount(bodyPtr);
+        while (procPtr->firstLocalPtr != NULL) {
+            localPtr = procPtr->firstLocalPtr;
+            procPtr->firstLocalPtr = localPtr->nextPtr;
+	
+            defPtr = localPtr->defValuePtr;
+            if (defPtr != NULL) {
+                Tcl_DecrRefCount(defPtr);
+            }
+	
+            ckfree((char *) localPtr);
+        }
+        ckfree((char *) procPtr);
+    }
+    if (argArray != NULL) {
+	ckfree((char *) argArray);
+    }
+    return TCL_ERROR;
+}
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetFrame --
+ *
+ *	Given a description of a procedure frame, such as the first
+ *	argument to an "uplevel" or "upvar" command, locate the
+ *	call frame for the appropriate level of procedure.
+ *
+ * Results:
+ *	The return value is -1 if an error occurred in finding the
+ *	frame (in this case an error message is left in interp->result).
+ *	1 is returned if string was either a number or a number preceded
+ *	by "#" and it specified a valid frame.  0 is returned if string
+ *	isn't one of the two things above (in this case, the lookup
+ *	acts as if string were "1").  The variable pointed to by
+ *	framePtrPtr is filled in with the address of the desired frame
+ *	(unless an error occurs, in which case it isn't modified).
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclGetFrame(interp, string, framePtrPtr)
+    Tcl_Interp *interp;		/* Interpreter in which to find frame. */
+    char *string;		/* String describing frame. */
+    CallFrame **framePtrPtr;	/* Store pointer to frame here (or NULL
+				 * if global frame indicated). */
+{
+    register Interp *iPtr = (Interp *) interp;
+    int curLevel, level, result;
+    CallFrame *framePtr;
+
+    /*
+     * Parse string to figure out which level number to go to.
+     */
+
+    result = 1;
+    curLevel = (iPtr->varFramePtr == NULL) ? 0 : iPtr->varFramePtr->level;
+    if (*string == '#') {
+	if (Tcl_GetInt(interp, string+1, &level) != TCL_OK) {
+	    return -1;
+	}
+	if (level < 0) {
+	    levelError:
+	    Tcl_AppendResult(interp, "bad level \"", string, "\"",
+		    (char *) NULL);
+	    return -1;
+	}
+    } else if (isdigit(UCHAR(*string))) {
+	if (Tcl_GetInt(interp, string, &level) != TCL_OK) {
+	    return -1;
+	}
+	level = curLevel - level;
+    } else {
+	level = curLevel - 1;
+	result = 0;
+    }
+
+    /*
+     * Figure out which frame to use, and modify the interpreter so
+     * its variables come from that frame.
+     */
+
+    if (level == 0) {
+	framePtr = NULL;
+    } else {
+	for (framePtr = iPtr->varFramePtr; framePtr != NULL;
+		framePtr = framePtr->callerVarPtr) {
+	    if (framePtr->level == level) {
+		break;
+	    }
+	}
+	if (framePtr == NULL) {
+	    goto levelError;
+	}
+    }
+    *framePtrPtr = framePtr;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_UplevelObjCmd --
+ *
+ *	This object procedure is invoked to process the "uplevel" Tcl
+ *	command. See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result value.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_UplevelObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    register Interp *iPtr = (Interp *) interp;
+    char *optLevel;
+    int length, result;
+    CallFrame *savedVarFramePtr, *framePtr;
+
+    if (objc < 2) {
+	uplevelSyntax:
+	Tcl_WrongNumArgs(interp, 1, objv, "?level? command ?arg ...?");
+	return TCL_ERROR;
+    }
+
+    /*
+     * Find the level to use for executing the command.
+     * THIS FAILS IF THE OBJECT RESULT'S STRING REP CONTAINS A NULL.
+     */
+
+    optLevel = Tcl_GetStringFromObj(objv[1], &length);
+    result = TclGetFrame(interp, optLevel, &framePtr);
+    if (result == -1) {
+	return TCL_ERROR;
+    }
+    objc -= (result+1);
+    if (objc == 0) {
+	goto uplevelSyntax;
+    }
+    objv += (result+1);
+
+    /*
+     * Modify the interpreter state to execute in the given frame.
+     */
+
+    savedVarFramePtr = iPtr->varFramePtr;
+    iPtr->varFramePtr = framePtr;
+
+    /*
+     * Execute the residual arguments as a command.
+     */
+
+    if (objc == 1) {
+	result = Tcl_EvalObj(interp, objv[0]);
+    } else {
+	Tcl_Obj *cmdObjPtr = Tcl_ConcatObj(objc, objv);
+	result = Tcl_EvalObj(interp, cmdObjPtr);
+	Tcl_DecrRefCount(cmdObjPtr); /* done with object */
+    }
+    if (result == TCL_ERROR) {
+	char msg[60];
+	sprintf(msg, "\n    (\"uplevel\" body line %d)", interp->errorLine);
+	Tcl_AddObjErrorInfo(interp, msg, -1);
+    }
+
+    /*
+     * Restore the variable frame, and return.
+     */
+
+    iPtr->varFramePtr = savedVarFramePtr;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFindProc --
+ *
+ *	Given the name of a procedure, return a pointer to the
+ *	record describing the procedure.
+ *
+ * Results:
+ *	NULL is returned if the name doesn't correspond to any
+ *	procedure.  Otherwise the return value is a pointer to
+ *	the procedure's record.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Proc *
+TclFindProc(iPtr, procName)
+    Interp *iPtr;		/* Interpreter in which to look. */
+    char *procName;		/* Name of desired procedure. */
+{
+    Tcl_Command cmd;
+    Tcl_Command origCmd;
+    Command *cmdPtr;
+    
+    cmd = Tcl_FindCommand((Tcl_Interp *) iPtr, procName,
+            (Tcl_Namespace *) NULL, /*flags*/ 0);
+    if (cmd == (Tcl_Command) NULL) {
+        return NULL;
+    }
+    cmdPtr = (Command *) cmd;
+
+    origCmd = TclGetOriginalCommand(cmd);
+    if (origCmd != NULL) {
+	cmdPtr = (Command *) origCmd;
+    }
+    if (cmdPtr->proc != TclProcInterpProc) {
+	return NULL;
+    }
+    return (Proc *) cmdPtr->clientData;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclIsProc --
+ *
+ *	Tells whether a command is a Tcl procedure or not.
+ *
+ * Results:
+ *	If the given command is actually a Tcl procedure, the
+ *	return value is the address of the record describing
+ *	the procedure.  Otherwise the return value is 0.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Proc *
+TclIsProc(cmdPtr)
+    Command *cmdPtr;		/* Command to test. */
+{
+    Tcl_Command origCmd;
+
+    origCmd = TclGetOriginalCommand((Tcl_Command) cmdPtr);
+    if (origCmd != NULL) {
+	cmdPtr = (Command *) origCmd;
+    }
+    if (cmdPtr->proc == TclProcInterpProc) {
+	return (Proc *) cmdPtr->clientData;
+    }
+    return (Proc *) 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclProcInterpProc --
+ *
+ *	When a Tcl procedure gets invoked with an argc/argv array of
+ *	strings, this routine gets invoked to interpret the procedure.
+ *
+ * Results:
+ *	A standard Tcl result value, usually TCL_OK.
+ *
+ * Side effects:
+ *	Depends on the commands in the procedure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclProcInterpProc(clientData, interp, argc, argv)
+    ClientData clientData;	/* Record describing procedure to be
+				 * interpreted. */
+    Tcl_Interp *interp;		/* Interpreter in which procedure was
+				 * invoked. */
+    int argc;			/* Count of number of arguments to this
+				 * procedure. */
+    register char **argv;	/* Argument values. */
+{
+    register Tcl_Obj *objPtr;
+    register int i;
+    int result;
+
+    /*
+     * This procedure generates an objv array for object arguments that hold
+     * the argv strings. It starts out with stack-allocated space but uses
+     * dynamically-allocated storage if needed.
+     */
+
+#define NUM_ARGS 20
+    Tcl_Obj *(objStorage[NUM_ARGS]);
+    register Tcl_Obj **objv = objStorage;
+
+    /*
+     * Create the object argument array "objv". Make sure objv is large
+     * enough to hold the objc arguments plus 1 extra for the zero
+     * end-of-objv word.
+     */
+
+    if ((argc + 1) > NUM_ARGS) {
+	objv = (Tcl_Obj **)
+	    ckalloc((unsigned)(argc + 1) * sizeof(Tcl_Obj *));
+    }
+
+    for (i = 0;  i < argc;  i++) {
+	objv[i] = Tcl_NewStringObj(argv[i], -1);
+	Tcl_IncrRefCount(objv[i]);
+    }
+    objv[argc] = 0;
+
+    /*
+     * Use TclObjInterpProc to actually interpret the procedure.
+     */
+
+    result = TclObjInterpProc(clientData, interp, argc, objv);
+
+    /*
+     * Move the interpreter's object result to the string result, 
+     * then reset the object result.
+     * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS.
+     */
+    
+    Tcl_SetResult(interp,
+	    TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL),
+	    TCL_VOLATILE);
+
+    /*
+     * Decrement the ref counts on the objv elements since we are done
+     * with them.
+     */
+
+    for (i = 0;  i < argc;  i++) {
+	objPtr = objv[i];
+	TclDecrRefCount(objPtr);
+    }
+    
+    /*
+     * Free the objv array if malloc'ed storage was used.
+     */
+
+    if (objv != objStorage) {
+	ckfree((char *) objv);
+    }
+    return result;
+#undef NUM_ARGS
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclObjInterpProc --
+ *
+ *	When a Tcl procedure gets invoked during bytecode evaluation, this 
+ *	object-based routine gets invoked to interpret the procedure.
+ *
+ * Results:
+ *	A standard Tcl object result value.
+ *
+ * Side effects:
+ *	Depends on the commands in the procedure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclObjInterpProc(clientData, interp, objc, objv)
+    ClientData clientData;	/* Record describing procedure to be
+				 * interpreted. */
+    Tcl_Interp *interp;		/* Interpreter in which procedure was
+				 * invoked. */
+    int objc;			/* Count of number of arguments to this
+				 * procedure. */
+    Tcl_Obj *CONST objv[];	/* Argument value objects. */
+{
+    Interp *iPtr = (Interp *) interp;
+    Proc *procPtr = (Proc *) clientData;
+    Namespace *nsPtr = procPtr->cmdPtr->nsPtr;
+    CallFrame frame;
+    register CallFrame *framePtr = &frame;
+    register CompiledLocal *localPtr;
+    char *procName, *bytes;
+    int nameLen, localCt, numArgs, argCt, length, i, result;
+    Var *varPtr;
+
+    /*
+     * This procedure generates an array "compiledLocals" that holds the
+     * storage for local variables. It starts out with stack-allocated space
+     * but uses dynamically-allocated storage if needed.
+     */
+
+#define NUM_LOCALS 20
+    Var localStorage[NUM_LOCALS];
+    Var *compiledLocals = localStorage;
+
+    /*
+     * Get the procedure's name.
+     * THIS FAILS IF THE PROC NAME'S STRING REP HAS A NULL.
+     */
+    
+    procName = Tcl_GetStringFromObj(objv[0], &nameLen);
+
+    /*
+     * If necessary, compile the procedure's body. The compiler will
+     * allocate frame slots for the procedure's non-argument local
+     * variables.  Note that compiling the body might increase
+     * procPtr->numCompiledLocals if new local variables are found
+     * while compiling.
+     */
+    
+    result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr, nsPtr,
+	    "body of proc", procName);
+    
+    if (result != TCL_OK) {
+        return result;
+    }
+
+    /*
+     * Create the "compiledLocals" array. Make sure it is large enough to
+     * hold all the procedure's compiled local variables, including its
+     * formal parameters.
+     */
+
+    localCt = procPtr->numCompiledLocals;
+    if (localCt > NUM_LOCALS) {
+	compiledLocals = (Var *) ckalloc((unsigned) localCt * sizeof(Var));
+    }
+    
+    /*
+     * Set up and push a new call frame for the new procedure invocation.
+     * This call frame will execute in the proc's namespace, which might
+     * be different than the current namespace. The proc's namespace is
+     * that of its command, which can change if the command is renamed
+     * from one namespace to another.
+     */
+
+    result = Tcl_PushCallFrame(interp, (Tcl_CallFrame *) framePtr,
+            (Tcl_Namespace *) nsPtr, /*isProcCallFrame*/ 1);
+
+    if (result != TCL_OK) {
+        return result;
+    }
+
+    framePtr->objc = objc;
+    framePtr->objv = objv;  /* ref counts for args are incremented below */
+
+    /*
+     * Initialize and resolve compiled variable references.
+     */
+
+    framePtr->procPtr = procPtr;
+    framePtr->numCompiledLocals = localCt;
+    framePtr->compiledLocals = compiledLocals;
+
+    TclInitCompiledLocals(interp, framePtr, nsPtr);
+    
+    /*
+     * Match and assign the call's actual parameters to the procedure's
+     * formal arguments. The formal arguments are described by the first
+     * numArgs entries in both the Proc structure's local variable list and
+     * the call frame's local variable array.
+     */
+
+    numArgs = procPtr->numArgs;
+    varPtr = framePtr->compiledLocals;
+    localPtr = procPtr->firstLocalPtr;
+    argCt = objc;
+    for (i = 1, argCt -= 1;  i <= numArgs;  i++, argCt--) {
+	if (!TclIsVarArgument(localPtr)) {
+	    panic("TclObjInterpProc: local variable %s is not argument but should be",
+		  localPtr->name);
+	    return TCL_ERROR;
+	}
+	if (TclIsVarTemporary(localPtr)) {
+	    panic("TclObjInterpProc: local variable %d is temporary but should be an argument", i);
+	    return TCL_ERROR;
+	}
+
+	/*
+	 * Handle the special case of the last formal being "args".  When
+	 * it occurs, assign it a list consisting of all the remaining
+	 * actual arguments.
+	 */
+
+	if ((i == numArgs) && ((localPtr->name[0] == 'a')
+	        && (strcmp(localPtr->name, "args") == 0))) {
+	    Tcl_Obj *listPtr = Tcl_NewListObj(argCt, &(objv[i]));
+	    varPtr->value.objPtr = listPtr;
+	    Tcl_IncrRefCount(listPtr); /* local var is a reference */
+	    varPtr->flags &= ~VAR_UNDEFINED;
+	    argCt = 0;
+	    break;		/* done processing args */
+	} else if (argCt > 0) {
+	    Tcl_Obj *objPtr = objv[i];
+	    varPtr->value.objPtr = objPtr;
+	    varPtr->flags &= ~VAR_UNDEFINED;
+	    Tcl_IncrRefCount(objPtr);  /* since the local variable now has
+					* another reference to object. */
+	} else if (localPtr->defValuePtr != NULL) {
+	    Tcl_Obj *objPtr = localPtr->defValuePtr;
+	    varPtr->value.objPtr = objPtr;
+	    varPtr->flags &= ~VAR_UNDEFINED;
+	    Tcl_IncrRefCount(objPtr);  /* since the local variable now has
+					* another reference to object. */
+	} else {
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		    "no value given for parameter \"", localPtr->name,
+		    "\" to \"", Tcl_GetStringFromObj(objv[0], (int *) NULL),
+		    "\"", (char *) NULL);
+	    result = TCL_ERROR;
+	    goto procDone;
+	}
+	varPtr++;
+	localPtr = localPtr->nextPtr;
+    }
+    if (argCt > 0) {
+	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+		"called \"", Tcl_GetStringFromObj(objv[0], (int *) NULL),
+		"\" with too many arguments", (char *) NULL);
+	result = TCL_ERROR;
+	goto procDone;
+    }
+
+    /*
+     * Invoke the commands in the procedure's body.
+     */
+
+    if (tclTraceExec >= 1) {
+	fprintf(stdout, "Calling proc ");
+	for (i = 0;  i < objc;  i++) {
+	    bytes = Tcl_GetStringFromObj(objv[i], &length);
+	    TclPrintSource(stdout, bytes, TclMin(length, 15));
+	    fprintf(stdout, " ");
+	}
+	fprintf(stdout, "\n");
+	fflush(stdout);
+    }
+
+    iPtr->returnCode = TCL_OK;
+    procPtr->refCount++;
+    result = Tcl_EvalObj(interp, procPtr->bodyPtr);
+    procPtr->refCount--;
+    if (procPtr->refCount <= 0) {
+	TclProcCleanupProc(procPtr);
+    }
+
+    if (result != TCL_OK) {
+	if (result == TCL_RETURN) {
+	    result = TclUpdateReturnInfo(iPtr);
+	} else if (result == TCL_ERROR) {
+	    char msg[100];
+	    sprintf(msg, "\n    (procedure \"%.50s\" line %d)",
+		    procName, iPtr->errorLine);
+	    Tcl_AddObjErrorInfo(interp, msg, -1);
+	} else if (result == TCL_BREAK) {
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+	            "invoked \"break\" outside of a loop", -1);
+	    result = TCL_ERROR;
+	} else if (result == TCL_CONTINUE) {
+	    Tcl_ResetResult(interp);
+	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
+		    "invoked \"continue\" outside of a loop", -1);
+	    result = TCL_ERROR;
+	}
+    }
+    
+    procDone:
+
+    /*
+     * Pop and free the call frame for this procedure invocation.
+     */
+    
+    Tcl_PopCallFrame(interp);
+    
+    /*
+     * Free the compiledLocals array if malloc'ed storage was used.
+     */
+
+    if (compiledLocals != localStorage) {
+	ckfree((char *) compiledLocals);
+    }
+    return result;
+#undef NUM_LOCALS
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclProcCompileProc --
+ *
+ *	Called just before a procedure is executed to compile the
+ *	body to byte codes.  If the type of the body is not
+ *	"byte code" or if the compile conditions have changed
+ *	(namespace context, epoch counters, etc.) then the body
+ *	is recompiled.  Otherwise, this procedure does nothing.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	May change the internal representation of the body object
+ *	to compiled code.
+ *
+ *----------------------------------------------------------------------
+ */
+ 
+int
+TclProcCompileProc(interp, procPtr, bodyPtr, nsPtr, description, procName)
+    Tcl_Interp *interp;		/* Interpreter containing procedure. */
+    Proc *procPtr;		/* Data associated with procedure. */
+    Tcl_Obj *bodyPtr;		/* Body of proc. (Usually procPtr->bodyPtr,
+ 				 * but could be any code fragment compiled
+ 				 * in the context of this procedure.) */
+    Namespace *nsPtr;		/* Namespace containing procedure. */
+    CONST char *description;	/* string describing this body of code. */
+    CONST char *procName;	/* Name of this procedure. */
+{
+    Interp *iPtr = (Interp*)interp;
+    int result;
+    Tcl_CallFrame frame;
+    Proc *saveProcPtr;
+    ByteCode *codePtr = (ByteCode *) bodyPtr->internalRep.otherValuePtr;
+ 
+    /*
+     * If necessary, compile the procedure's body. The compiler will
+     * allocate frame slots for the procedure's non-argument local
+     * variables. If the ByteCode already exists, make sure it hasn't been
+     * invalidated by someone redefining a core command (this might make the
+     * compiled code wrong). Also, if the code was compiled in/for a
+     * different interpreter, we recompile it. Note that compiling the body
+     * might increase procPtr->numCompiledLocals if new local variables are
+     * found while compiling.
+     *
+     * Precompiled procedure bodies, however, are immutable and therefore
+     * they are not recompiled, even if things have changed.
+     */
+ 
+    if (bodyPtr->typePtr == &tclByteCodeType) {
+ 	if ((codePtr->iPtr != iPtr)
+ 	        || (codePtr->compileEpoch != iPtr->compileEpoch)
+ 	        || (codePtr->nsPtr != nsPtr)) {
+            if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
+                if (codePtr->iPtr != iPtr) {
+                    Tcl_AppendResult(interp,
+                            "a precompiled script jumped interps", NULL);
+                    return TCL_ERROR;
+                }
+	        codePtr->compileEpoch = iPtr->compileEpoch;
+                codePtr->nsPtr = nsPtr;
+            } else {
+                tclByteCodeType.freeIntRepProc(bodyPtr);
+                bodyPtr->typePtr = (Tcl_ObjType *) NULL;
+            }
+ 	}
+    }
+    if (bodyPtr->typePtr != &tclByteCodeType) {
+ 	char buf[100];
+ 	int numChars;
+ 	char *ellipsis;
+ 	
+ 	if (tclTraceCompile >= 1) {
+ 	    /*
+ 	     * Display a line summarizing the top level command we
+ 	     * are about to compile.
+ 	     */
+ 
+ 	    numChars = strlen(procName);
+ 	    ellipsis = "";
+ 	    if (numChars > 50) {
+ 		numChars = 50;
+ 		ellipsis = "...";
+ 	    }
+ 	    fprintf(stdout, "Compiling %s \"%.*s%s\"\n",
+ 		    description, numChars, procName, ellipsis);
+ 	}
+ 	
+ 	/*
+ 	 * Plug the current procPtr into the interpreter and coerce
+ 	 * the code body to byte codes.  The interpreter needs to
+ 	 * know which proc it's compiling so that it can access its
+ 	 * list of compiled locals.
+ 	 *
+ 	 * TRICKY NOTE:  Be careful to push a call frame with the
+ 	 *   proper namespace context, so that the byte codes are
+ 	 *   compiled in the appropriate class context.
+ 	 */
+ 
+ 	saveProcPtr = iPtr->compiledProcPtr;
+ 	iPtr->compiledProcPtr = procPtr;
+ 
+ 	result = Tcl_PushCallFrame(interp, &frame,
+		(Tcl_Namespace*)nsPtr, /* isProcCallFrame */ 0);
+ 
+ 	if (result == TCL_OK) {
+	    result = tclByteCodeType.setFromAnyProc(interp, bodyPtr);
+	    Tcl_PopCallFrame(interp);
+	}
+ 
+ 	iPtr->compiledProcPtr = saveProcPtr;
+ 	
+ 	if (result != TCL_OK) {
+ 	    if (result == TCL_ERROR) {
+ 		numChars = strlen(procName);
+ 		ellipsis = "";
+ 		if (numChars > 50) {
+ 		    numChars = 50;
+ 		    ellipsis = "...";
+ 		}
+ 		sprintf(buf, "\n    (compiling %s \"%.*s%s\", line %d)",
+ 			description, numChars, procName, ellipsis,
+ 			interp->errorLine);
+ 		Tcl_AddObjErrorInfo(interp, buf, -1);
+ 	    }
+ 	    return result;
+ 	}
+    } else if (codePtr->nsEpoch != nsPtr->resolverEpoch) {
+	register CompiledLocal *localPtr;
+ 	
+	/*
+	 * The resolver epoch has changed, but we only need to invalidate
+	 * the resolver cache.
+	 */
+
+	for (localPtr = procPtr->firstLocalPtr;  localPtr != NULL;
+	    localPtr = localPtr->nextPtr) {
+	    localPtr->flags &= ~(VAR_RESOLVED);
+	    if (localPtr->resolveInfo) {
+		if (localPtr->resolveInfo->deleteProc) {
+		    localPtr->resolveInfo->deleteProc(localPtr->resolveInfo);
+		} else {
+		    ckfree((char*)localPtr->resolveInfo);
+		}
+		localPtr->resolveInfo = NULL;
+	    }
+	}
+    }
+    return TCL_OK;
+}
+ 
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclProcDeleteProc --
+ *
+ *	This procedure is invoked just before a command procedure is
+ *	removed from an interpreter.  Its job is to release all the
+ *	resources allocated to the procedure.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Memory gets freed, unless the procedure is actively being
+ *	executed.  In this case the cleanup is delayed until the
+ *	last call to the current procedure completes.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclProcDeleteProc(clientData)
+    ClientData clientData;		/* Procedure to be deleted. */
+{
+    Proc *procPtr = (Proc *) clientData;
+
+    procPtr->refCount--;
+    if (procPtr->refCount <= 0) {
+	TclProcCleanupProc(procPtr);
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclProcCleanupProc --
+ *
+ *	This procedure does all the real work of freeing up a Proc
+ *	structure.  It's called only when the structure's reference
+ *	count becomes zero.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Memory gets freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclProcCleanupProc(procPtr)
+    register Proc *procPtr;		/* Procedure to be deleted. */
+{
+    register CompiledLocal *localPtr;
+    Tcl_Obj *bodyPtr = procPtr->bodyPtr;
+    Tcl_Obj *defPtr;
+    Tcl_ResolvedVarInfo *resVarInfo;
+
+    if (bodyPtr != NULL) {
+	Tcl_DecrRefCount(bodyPtr);
+    }
+    for (localPtr = procPtr->firstLocalPtr;  localPtr != NULL;  ) {
+	CompiledLocal *nextPtr = localPtr->nextPtr;
+
+        resVarInfo = localPtr->resolveInfo;
+	if (resVarInfo) {
+	    if (resVarInfo->deleteProc) {
+		(*resVarInfo->deleteProc)(resVarInfo);
+	    } else {
+		ckfree((char *) resVarInfo);
+	    }
+        }
+
+	if (localPtr->defValuePtr != NULL) {
+	    defPtr = localPtr->defValuePtr;
+	    Tcl_DecrRefCount(defPtr);
+	}
+	ckfree((char *) localPtr);
+	localPtr = nextPtr;
+    }
+    ckfree((char *) procPtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclUpdateReturnInfo --
+ *
+ *	This procedure is called when procedures return, and at other
+ *	points where the TCL_RETURN code is used.  It examines fields
+ *	such as iPtr->returnCode and iPtr->errorCode and modifies
+ *	the real return status accordingly.
+ *
+ * Results:
+ *	The return value is the true completion code to use for
+ *	the procedure, instead of TCL_RETURN.
+ *
+ * Side effects:
+ *	The errorInfo and errorCode variables may get modified.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclUpdateReturnInfo(iPtr)
+    Interp *iPtr;		/* Interpreter for which TCL_RETURN
+				 * exception is being processed. */
+{
+    int code;
+
+    code = iPtr->returnCode;
+    iPtr->returnCode = TCL_OK;
+    if (code == TCL_ERROR) {
+	Tcl_SetVar2((Tcl_Interp *) iPtr, "errorCode", (char *) NULL,
+		(iPtr->errorCode != NULL) ? iPtr->errorCode : "NONE",
+		TCL_GLOBAL_ONLY);
+	iPtr->flags |= ERROR_CODE_SET;
+	if (iPtr->errorInfo != NULL) {
+	    Tcl_SetVar2((Tcl_Interp *) iPtr, "errorInfo", (char *) NULL,
+		    iPtr->errorInfo, TCL_GLOBAL_ONLY);
+	    iPtr->flags |= ERR_IN_PROGRESS;
+	}
+    }
+    return code;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetInterpProc --
+ *
+ *  Returns a pointer to the TclProcInterpProc procedure; this is different
+ *  from the value obtained from the TclProcInterpProc reference on systems
+ *  like Windows where import and export versions of a procedure exported
+ *  by a DLL exist.
+ *
+ * Results:
+ *  Returns the internal address of the TclProcInterpProc procedure.
+ *
+ * Side effects:
+ *  None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TclCmdProcType
+TclGetInterpProc()
+{
+    return TclProcInterpProc;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetObjInterpProc --
+ *
+ *  Returns a pointer to the TclObjInterpProc procedure; this is different
+ *  from the value obtained from the TclObjInterpProc reference on systems
+ *  like Windows where import and export versions of a procedure exported
+ *  by a DLL exist.
+ *
+ * Results:
+ *  Returns the internal address of the TclObjInterpProc procedure.
+ *
+ * Side effects:
+ *  None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TclObjCmdProcType
+TclGetObjInterpProc()
+{
+    return TclObjInterpProc;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclNewProcBodyObj --
+ *
+ *  Creates a new object, of type "procbody", whose internal
+ *  representation is the given Proc struct.
+ *  The newly created object's reference count is 0.
+ *
+ * Results:
+ *  Returns a pointer to a newly allocated Tcl_Obj, 0 on error.
+ *
+ * Side effects:
+ *  The reference count in the ByteCode attached to the Proc is bumped up
+ *  by one, since the internal rep stores a pointer to it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclNewProcBodyObj(procPtr)
+    Proc *procPtr;	/* the Proc struct to store as the internal
+                         * representation. */
+{
+    Tcl_Obj *objPtr;
+
+    if (!procPtr) {
+        return (Tcl_Obj *) NULL;
+    }
+    
+    objPtr = Tcl_NewStringObj("", 0);
+
+    if (objPtr) {
+        objPtr->typePtr = &tclProcBodyType;
+        objPtr->internalRep.otherValuePtr = (VOID *) procPtr;
+
+        procPtr->refCount++;
+    }
+
+    return objPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ProcBodyDup --
+ *
+ *  Tcl_ObjType's Dup function for the proc body object.
+ *  Bumps the reference count on the Proc stored in the internal
+ *  representation.
+ *
+ * Results:
+ *  None.
+ *
+ * Side effects:
+ *  Sets up the object in dupPtr to be a duplicate of the one in srcPtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void ProcBodyDup(srcPtr, dupPtr)
+    Tcl_Obj *srcPtr;		/* object to copy */
+    Tcl_Obj *dupPtr;		/* target object for the duplication */
+{
+    Proc *procPtr = (Proc *) srcPtr->internalRep.otherValuePtr;
+    
+    dupPtr->typePtr = &tclProcBodyType;
+    dupPtr->internalRep.otherValuePtr = (VOID *) procPtr;
+    procPtr->refCount++;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ProcBodyFree --
+ *
+ *  Tcl_ObjType's Free function for the proc body object.
+ *  The reference count on its Proc struct is decreased by 1; if the count
+ *  reaches 0, the proc is freed.
+ *
+ * Results:
+ *  None.
+ *
+ * Side effects:
+ *  If the reference count on the Proc struct reaches 0, the struct is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ProcBodyFree(objPtr)
+    Tcl_Obj *objPtr;		/* the object to clean up */
+{
+    Proc *procPtr = (Proc *) objPtr->internalRep.otherValuePtr;
+    procPtr->refCount--;
+    if (procPtr->refCount <= 0) {
+        TclProcCleanupProc(procPtr);
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ProcBodySetFromAny --
+ *
+ *  Tcl_ObjType's SetFromAny function for the proc body object.
+ *  Calls panic.
+ *
+ * Results:
+ *  Theoretically returns a TCL result code.
+ *
+ * Side effects:
+ *  Calls panic, since we can't set the value of the object from a string
+ *  representation (or any other internal ones).
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ProcBodySetFromAny(interp, objPtr)
+    Tcl_Interp *interp;			/* current interpreter */
+    Tcl_Obj *objPtr;			/* object pointer */
+{
+    panic("called ProcBodySetFromAny");
+
+    /*
+     * this to keep compilers happy.
+     */
+    
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ProcBodyUpdateString --
+ *
+ *  Tcl_ObjType's UpdateString function for the proc body object.
+ *  Calls panic.
+ *
+ * Results:
+ *  None.
+ *
+ * Side effects:
+ *  Calls panic, since we this type has no string representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ProcBodyUpdateString(objPtr)
+    Tcl_Obj *objPtr;		/* the object to update */
+{
+    panic("called ProcBodyUpdateString");
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclResolve.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclResolve.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclResolve.c	(revision 5)
@@ -0,0 +1,424 @@
+/*
+ * tclResolve.c --
+ *
+ *      Contains hooks for customized command/variable name resolution
+ *      schemes.  These hooks allow extensions like [incr Tcl] to add
+ *      their own name resolution rules to the Tcl language.  Rules can
+ *      be applied to a particular namespace, to the interpreter as a
+ *      whole, or both.
+ *
+ * Copyright (c) 1998 Lucent Technologies, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclResolve.c,v 1.1 2008-06-04 13:58:10 demin Exp $
+ */
+
+#include "tclInt.h"
+
+/*
+ * Declarations for procedures local to this file:
+ */
+
+static void		BumpCmdRefEpochs _ANSI_ARGS_((Namespace *nsPtr));
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AddInterpResolvers --
+ *
+ *	Adds a set of command/variable resolution procedures to an
+ *	interpreter.  These procedures are consulted when commands
+ *	are resolved in Tcl_FindCommand, and when variables are
+ *	resolved in TclLookupVar and LookupCompiledLocal.  Each
+ *	namespace may also have its own set of resolution procedures
+ *	which take precedence over those for the interpreter.
+ *
+ *	When a name is resolved, it is handled as follows.  First,
+ *	the name is passed to the resolution procedures for the
+ *	namespace.  If not resolved, the name is passed to each of
+ *	the resolution procedures added to the interpreter.  Finally,
+ *	if still not resolved, the name is handled using the default
+ *	Tcl rules for name resolution.
+ *
+ * Results:
+ *	Returns pointers to the current name resolution procedures
+ *	in the cmdProcPtr, varProcPtr and compiledVarProcPtr
+ *	arguments.
+ *
+ * Side effects:
+ *	If a compiledVarProc is specified, this procedure bumps the
+ *	compileEpoch for the interpreter, forcing all code to be
+ *	recompiled.  If a cmdProc is specified, this procedure bumps
+ *	the cmdRefEpoch in all namespaces, forcing commands to be
+ *	resolved again using the new rules.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_AddInterpResolvers(interp, name, cmdProc, varProc, compiledVarProc)
+
+    Tcl_Interp *interp;			/* Interpreter whose name resolution
+					 * rules are being modified. */
+    char *name;				/* Name of this resolution scheme. */
+    Tcl_ResolveCmdProc *cmdProc;	/* New procedure for command
+					 * resolution */
+    Tcl_ResolveVarProc *varProc;	/* Procedure for variable resolution
+					 * at runtime */
+    Tcl_ResolveCompiledVarProc *compiledVarProc;
+					/* Procedure for variable resolution
+					 * at compile time. */
+{
+    Interp *iPtr = (Interp*)interp;
+    ResolverScheme *resPtr;
+
+    /*
+     *  Since we're adding a new name resolution scheme, we must force
+     *  all code to be recompiled to use the new scheme.  If there
+     *  are new compiled variable resolution rules, bump the compiler
+     *  epoch to invalidate compiled code.  If there are new command
+     *  resolution rules, bump the cmdRefEpoch in all namespaces.
+     */
+    if (compiledVarProc) {
+        iPtr->compileEpoch++;
+    }
+    if (cmdProc) {
+        BumpCmdRefEpochs(iPtr->globalNsPtr);
+    }
+
+    /*
+     *  Look for an existing scheme with the given name.  If found,
+     *  then replace its rules.
+     */
+    for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) {
+        if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) {
+            resPtr->cmdResProc = cmdProc;
+            resPtr->varResProc = varProc;
+            resPtr->compiledVarResProc = compiledVarProc;
+            return;
+        }
+    }
+
+    /*
+     *  Otherwise, this is a new scheme.  Add it to the FRONT
+     *  of the linked list, so that it overrides existing schemes.
+     */
+    resPtr = (ResolverScheme *) ckalloc(sizeof(ResolverScheme));
+    resPtr->name = (char*)ckalloc((unsigned)(strlen(name)+1));
+    strcpy(resPtr->name, name);
+    resPtr->cmdResProc = cmdProc;
+    resPtr->varResProc = varProc;
+    resPtr->compiledVarResProc = compiledVarProc;
+    resPtr->nextPtr = iPtr->resolverPtr;
+    iPtr->resolverPtr = resPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetInterpResolvers --
+ *
+ *	Looks for a set of command/variable resolution procedures with
+ *	the given name in an interpreter.  These procedures are
+ *	registered by calling Tcl_AddInterpResolvers.
+ *
+ * Results:
+ *	If the name is recognized, this procedure returns non-zero,
+ *	along with pointers to the name resolution procedures in
+ *	the Tcl_ResolverInfo structure.  If the name is not recognized,
+ *	this procedure returns zero.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetInterpResolvers(interp, name, resInfoPtr)
+
+    Tcl_Interp *interp;			/* Interpreter whose name resolution
+					 * rules are being queried. */
+    char *name;                         /* Look for a scheme with this name. */
+    Tcl_ResolverInfo *resInfoPtr;	/* Returns pointers to the procedures,
+					 * if found */
+{
+    Interp *iPtr = (Interp*)interp;
+    ResolverScheme *resPtr;
+
+    /*
+     *  Look for an existing scheme with the given name.  If found,
+     *  then return pointers to its procedures.
+     */
+    for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) {
+        if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) {
+	    resInfoPtr->cmdResProc = resPtr->cmdResProc;
+	    resInfoPtr->varResProc = resPtr->varResProc;
+	    resInfoPtr->compiledVarResProc = resPtr->compiledVarResProc;
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_RemoveInterpResolvers --
+ *
+ *	Removes a set of command/variable resolution procedures
+ *	previously added by Tcl_AddInterpResolvers.  The next time
+ *	a command/variable name is resolved, these procedures
+ *	won't be consulted.
+ *
+ * Results:
+ *	Returns non-zero if the name was recognized and the
+ *	resolution scheme was deleted.  Returns zero otherwise.
+ *
+ * Side effects:
+ *	If a scheme with a compiledVarProc was deleted, this procedure
+ *	bumps the compileEpoch for the interpreter, forcing all code
+ *	to be recompiled.  If a scheme with a cmdProc was deleted,
+ *	this procedure bumps the cmdRefEpoch in all namespaces,
+ *	forcing commands to be resolved again using the new rules.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_RemoveInterpResolvers(interp, name)
+
+    Tcl_Interp *interp;			/* Interpreter whose name resolution
+					 * rules are being modified. */
+    char *name;                         /* Name of the scheme to be removed. */
+{
+    Interp *iPtr = (Interp*)interp;
+    ResolverScheme **prevPtrPtr, *resPtr;
+
+    /*
+     *  Look for an existing scheme with the given name.
+     */
+    prevPtrPtr = &iPtr->resolverPtr;
+    for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) {
+        if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) {
+            break;
+        }
+        prevPtrPtr = &resPtr->nextPtr;
+    }
+
+    /*
+     *  If we found the scheme, delete it.
+     */
+    if (resPtr) {
+        /*
+         *  If we're deleting a scheme with compiled variable resolution
+         *  rules, bump the compiler epoch to invalidate compiled code.
+         *  If we're deleting a scheme with command resolution rules,
+         *  bump the cmdRefEpoch in all namespaces.
+         */
+        if (resPtr->compiledVarResProc) {
+            iPtr->compileEpoch++;
+        }
+        if (resPtr->cmdResProc) {
+            BumpCmdRefEpochs(iPtr->globalNsPtr);
+        }
+
+        *prevPtrPtr = resPtr->nextPtr;
+        ckfree(resPtr->name);
+        ckfree((char *) resPtr);
+
+        return 1;
+    }
+    return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BumpCmdRefEpochs --
+ *
+ *	This procedure is used to bump the cmdRefEpoch counters in
+ *	the specified namespace and all of its child namespaces.
+ *	It is used whenever name resolution schemes are added/removed
+ *	from an interpreter, to invalidate all command references.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Bumps the cmdRefEpoch in the specified namespace and its
+ *	children, recursively.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+BumpCmdRefEpochs(nsPtr)
+    Namespace *nsPtr;			/* Namespace being modified. */
+{
+    Tcl_HashEntry *entry;
+    Tcl_HashSearch search;
+    Namespace *childNsPtr;
+
+    nsPtr->cmdRefEpoch++;
+
+    for (entry = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
+	    entry != NULL;
+	    entry = Tcl_NextHashEntry(&search)) {
+
+        childNsPtr = (Namespace *) Tcl_GetHashValue(entry);
+        BumpCmdRefEpochs(childNsPtr);
+    }
+}
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetNamespaceResolvers --
+ *
+ *	Sets the command/variable resolution procedures for a namespace,
+ *	thereby changing the way that command/variable names are
+ *	interpreted.  This allows extension writers to support different
+ *	name resolution schemes, such as those for object-oriented
+ *	packages.
+ *
+ *	Command resolution is handled by a procedure of the following
+ *	type:
+ *
+ *	  typedef int (Tcl_ResolveCmdProc) _ANSI_ARGS_((
+ *		Tcl_Interp* interp, char* name, Tcl_Namespace *context,
+ *              int flags, Tcl_Command *rPtr));
+ *          
+ *	Whenever a command is executed or Tcl_FindCommand is invoked
+ *	within the namespace, this procedure is called to resolve the
+ *	command name.  If this procedure is able to resolve the name,
+ *	it should return the status code TCL_OK, along with the
+ *	corresponding Tcl_Command in the rPtr argument.  Otherwise,
+ *	the procedure can return TCL_CONTINUE, and the command will
+ *	be treated under the usual name resolution rules.  Or, it can
+ *	return TCL_ERROR, and the command will be considered invalid.
+ *
+ *	Variable resolution is handled by two procedures.  The first
+ *	is called whenever a variable needs to be resolved at compile
+ *	time:
+ *
+ *        typedef int (Tcl_ResolveCompiledVarProc) _ANSI_ARGS_((
+ *	        Tcl_Interp* interp, char* name, Tcl_Namespace *context,
+ *	        Tcl_ResolvedVarInfo *rPtr));
+ *
+ *      If this procedure is able to resolve the name, it should return
+ *      the status code TCL_OK, along with variable resolution info in
+ *      the rPtr argument; this info will be used to set up compiled
+ *	locals in the call frame at runtime.  The procedure may also
+ *	return TCL_CONTINUE, and the variable will be treated under
+ *	the usual name resolution rules.  Or, it can return TCL_ERROR,
+ *	and the variable will be considered invalid.
+ *
+ *	Another procedure is used whenever a variable needs to be
+ *	resolved at runtime but it is not recognized as a compiled local.
+ *	(For example, the variable may be requested via
+ *	Tcl_FindNamespaceVar.) This procedure has the following type:
+ *
+ *	  typedef int (Tcl_ResolveVarProc) _ANSI_ARGS_((
+ *	        Tcl_Interp* interp, char* name, Tcl_Namespace *context,
+ *	        int flags, Tcl_Var *rPtr));
+ *
+ *	This procedure is quite similar to the compile-time version.
+ *	It returns the same status codes, but if variable resolution
+ *	succeeds, this procedure returns a Tcl_Var directly via the
+ *	rPtr argument.
+ *
+ * Results:
+ *	Nothing.
+ *
+ * Side effects:
+ *	Bumps the command epoch counter for the namespace, invalidating
+ *	all command references in that namespace.  Also bumps the
+ *	resolver epoch counter for the namespace, forcing all code
+ *	in the namespace to be recompiled.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetNamespaceResolvers(namespacePtr, cmdProc, varProc, compiledVarProc)
+    Tcl_Namespace *namespacePtr;	/* Namespace whose resolution rules
+					 * are being modified. */
+    Tcl_ResolveCmdProc *cmdProc;	/* Procedure for command resolution */
+    Tcl_ResolveVarProc *varProc;	/* Procedure for variable resolution
+					 * at runtime */
+    Tcl_ResolveCompiledVarProc *compiledVarProc;
+					/* Procedure for variable resolution
+					 * at compile time. */
+{
+    Namespace *nsPtr = (Namespace*)namespacePtr;
+
+    /*
+     *  Plug in the new command resolver, and bump the epoch counters
+     *  so that all code will have to be recompiled and all commands
+     *  will have to be resolved again using the new policy.
+     */
+    nsPtr->cmdResProc = cmdProc;
+    nsPtr->varResProc = varProc;
+    nsPtr->compiledVarResProc = compiledVarProc;
+
+    nsPtr->cmdRefEpoch++;
+    nsPtr->resolverEpoch++;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetNamespaceResolvers --
+ *
+ *	Returns the current command/variable resolution procedures
+ *	for a namespace.  By default, these procedures are NULL.
+ *	New procedures can be installed by calling
+ *	Tcl_SetNamespaceResolvers, to provide new name resolution
+ *	rules.
+ *
+ * Results:
+ *	Returns non-zero if any name resolution procedures have been
+ *	assigned to this namespace; also returns pointers to the
+ *	procedures in the Tcl_ResolverInfo structure.  Returns zero
+ *	otherwise.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetNamespaceResolvers(namespacePtr, resInfoPtr)
+
+    Tcl_Namespace *namespacePtr;	/* Namespace whose resolution rules
+					 * are being modified. */
+    Tcl_ResolverInfo *resInfoPtr;	/* Returns: pointers for all
+					 * name resolution procedures
+					 * assigned to this namespace. */
+{
+    Namespace *nsPtr = (Namespace*)namespacePtr;
+
+    resInfoPtr->cmdResProc = nsPtr->cmdResProc;
+    resInfoPtr->varResProc = nsPtr->varResProc;
+    resInfoPtr->compiledVarResProc = nsPtr->compiledVarResProc;
+
+    if (nsPtr->cmdResProc != NULL ||
+        nsPtr->varResProc != NULL ||
+        nsPtr->compiledVarResProc != NULL) {
+	return 1;
+    }
+    return 0;
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclStringObj.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclStringObj.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclStringObj.c	(revision 5)
@@ -0,0 +1,608 @@
+/* 
+ * tclStringObj.c --
+ *
+ *	This file contains procedures that implement string operations
+ *	on Tcl objects.  To do this efficiently (i.e. to allow many
+ *	appends to be done to an object without constantly reallocating
+ *	the space for the string representation) we overallocate the
+ *	space for the string and use the internal representation to keep
+ *	track of the extra space.  Objects with this internal
+ *	representation are called "expandable string objects".
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclStringObj.c,v 1.1 2008-06-04 13:58:10 demin Exp $
+ */
+
+#include "tclInt.h"
+
+/*
+ * Prototypes for procedures defined later in this file:
+ */
+
+static void		ConvertToStringType _ANSI_ARGS_((Tcl_Obj *objPtr));
+static void		DupStringInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr,
+			    Tcl_Obj *copyPtr));
+static int		SetStringFromAny _ANSI_ARGS_((Tcl_Interp *interp,
+			    Tcl_Obj *objPtr));
+static void		UpdateStringOfString _ANSI_ARGS_((Tcl_Obj *objPtr));
+
+/*
+ * The structure below defines the string Tcl object type by means of
+ * procedures that can be invoked by generic object code.
+ */
+
+Tcl_ObjType tclStringType = {
+    "string",				/* name */
+    (Tcl_FreeInternalRepProc *) NULL,	/* freeIntRepProc */
+    DupStringInternalRep,		/* dupIntRepProc */
+    UpdateStringOfString,		/* updateStringProc */
+    SetStringFromAny			/* setFromAnyProc */
+};
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_NewStringObj --
+ *
+ *	This procedure is normally called when not debugging: i.e., when
+ *	TCL_MEM_DEBUG is not defined. It creates a new string object and
+ *	initializes it from the byte pointer and length arguments.
+ *
+ *	When TCL_MEM_DEBUG is defined, this procedure just returns the
+ *	result of calling the debugging version Tcl_DbNewStringObj.
+ *
+ * Results:
+ *	A newly created string object is returned that has ref count zero.
+ *
+ * Side effects:
+ *	The new object's internal string representation will be set to a
+ *	copy of the length bytes starting at "bytes". If "length" is
+ *	negative, use bytes up to the first NULL byte; i.e., assume "bytes"
+ *	points to a C-style NULL-terminated string. The object's type is set
+ *	to NULL. An extra NULL is added to the end of the new object's byte
+ *	array.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_MEM_DEBUG
+#undef Tcl_NewStringObj
+
+Tcl_Obj *
+Tcl_NewStringObj(bytes, length)
+    register char *bytes;	/* Points to the first of the length bytes
+				 * used to initialize the new object. */
+    register int length;	/* The number of bytes to copy from "bytes"
+				 * when initializing the new object. If 
+				 * negative, use bytes up to the first
+				 * NULL byte. */
+{
+    return Tcl_DbNewStringObj(bytes, length, "unknown", 0);
+}
+
+#else /* if not TCL_MEM_DEBUG */
+
+Tcl_Obj *
+Tcl_NewStringObj(bytes, length)
+    register char *bytes;	/* Points to the first of the length bytes
+				 * used to initialize the new object. */
+    register int length;	/* The number of bytes to copy from "bytes"
+				 * when initializing the new object. If 
+				 * negative, use bytes up to the first
+				 * NULL byte. */
+{
+    register Tcl_Obj *objPtr;
+
+    if (length < 0) {
+	length = (bytes? strlen(bytes) : 0);
+    }
+    TclNewObj(objPtr);
+    TclInitStringRep(objPtr, bytes, length);
+    return objPtr;
+}
+#endif /* TCL_MEM_DEBUG */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DbNewStringObj --
+ *
+ *	This procedure is normally called when debugging: i.e., when
+ *	TCL_MEM_DEBUG is defined. It creates new string objects. It is the
+ *	same as the Tcl_NewStringObj procedure above except that it calls
+ *	Tcl_DbCkalloc directly with the file name and line number from its
+ *	caller. This simplifies debugging since then the checkmem command
+ *	will report the correct file name and line number when reporting
+ *	objects that haven't been freed.
+ *
+ *	When TCL_MEM_DEBUG is not defined, this procedure just returns the
+ *	result of calling Tcl_NewStringObj.
+ *
+ * Results:
+ *	A newly created string object is returned that has ref count zero.
+ *
+ * Side effects:
+ *	The new object's internal string representation will be set to a
+ *	copy of the length bytes starting at "bytes". If "length" is
+ *	negative, use bytes up to the first NULL byte; i.e., assume "bytes"
+ *	points to a C-style NULL-terminated string. The object's type is set
+ *	to NULL. An extra NULL is added to the end of the new object's byte
+ *	array.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_MEM_DEBUG
+
+Tcl_Obj *
+Tcl_DbNewStringObj(bytes, length, file, line)
+    register char *bytes;	/* Points to the first of the length bytes
+				 * used to initialize the new object. */
+    register int length;	/* The number of bytes to copy from "bytes"
+				 * when initializing the new object. If 
+				 * negative, use bytes up to the first
+				 * NULL byte. */
+    char *file;			/* The name of the source file calling this
+				 * procedure; used for debugging. */
+    int line;			/* Line number in the source file; used
+				 * for debugging. */
+{
+    register Tcl_Obj *objPtr;
+
+    if (length < 0) {
+	length = (bytes? strlen(bytes) : 0);
+    }
+    TclDbNewObj(objPtr, file, line);
+    TclInitStringRep(objPtr, bytes, length);
+    return objPtr;
+}
+
+#else /* if not TCL_MEM_DEBUG */
+
+Tcl_Obj *
+Tcl_DbNewStringObj(bytes, length, file, line)
+    register char *bytes;	/* Points to the first of the length bytes
+				 * used to initialize the new object. */
+    register int length;	/* The number of bytes to copy from "bytes"
+				 * when initializing the new object. If 
+				 * negative, use bytes up to the first
+				 * NULL byte. */
+    char *file;			/* The name of the source file calling this
+				 * procedure; used for debugging. */
+    int line;			/* Line number in the source file; used
+				 * for debugging. */
+{
+    return Tcl_NewStringObj(bytes, length);
+}
+#endif /* TCL_MEM_DEBUG */
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetStringObj --
+ *
+ *	Modify an object to hold a string that is a copy of the bytes
+ *	indicated by the byte pointer and length arguments. 
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The object's string representation will be set to a copy of
+ *	the "length" bytes starting at "bytes". If "length" is negative, use
+ *	bytes up to the first NULL byte; i.e., assume "bytes" points to a
+ *	C-style NULL-terminated string. The object's old string and internal
+ *	representations are freed and the object's type is set NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetStringObj(objPtr, bytes, length)
+    register Tcl_Obj *objPtr;	/* Object whose internal rep to init. */
+    char *bytes;		/* Points to the first of the length bytes
+				 * used to initialize the object. */
+    register int length;	/* The number of bytes to copy from "bytes"
+				 * when initializing the object. If 
+				 * negative, use bytes up to the first
+				 * NULL byte.*/
+{
+    register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
+
+    /*
+     * Free any old string rep, then set the string rep to a copy of
+     * the length bytes starting at "bytes".
+     */
+
+    if (Tcl_IsShared(objPtr)) {
+	panic("Tcl_SetStringObj called with shared object");
+    }
+
+    Tcl_InvalidateStringRep(objPtr);
+    if (length < 0) {
+	length = strlen(bytes);
+    }
+    TclInitStringRep(objPtr, bytes, length);
+        
+    /*
+     * Set the type to NULL and free any internal rep for the old type.
+     */
+
+    if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
+	oldTypePtr->freeIntRepProc(objPtr);
+    }
+    objPtr->typePtr = NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetObjLength --
+ *
+ *	This procedure changes the length of the string representation
+ *	of an object.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	If the size of objPtr's string representation is greater than
+ *	length, then it is reduced to length and a new terminating null
+ *	byte is stored in the strength.  If the length of the string
+ *	representation is greater than length, the storage space is
+ *	reallocated to the given length; a null byte is stored at the
+ *	end, but other bytes past the end of the original string
+ *	representation are undefined.  The object's internal
+ *	representation is changed to "expendable string".
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetObjLength(objPtr, length)
+    register Tcl_Obj *objPtr;	/* Pointer to object.  This object must
+				 * not currently be shared. */
+    register int length;	/* Number of bytes desired for string
+				 * representation of object, not including
+				 * terminating null byte. */
+{
+    char *new;
+
+    if (Tcl_IsShared(objPtr)) {
+	panic("Tcl_SetObjLength called with shared object");
+    }
+    if (objPtr->typePtr != &tclStringType) {
+	ConvertToStringType(objPtr);
+    }
+    
+    if ((long)length > objPtr->internalRep.longValue) {
+	/*
+	 * Not enough space in current string. Reallocate the string
+	 * space and free the old string.
+	 */
+
+	new = (char *) ckalloc((unsigned) (length+1));
+	if (objPtr->bytes != NULL) {
+	    memcpy((VOID *) new, (VOID *) objPtr->bytes,
+		    (size_t) objPtr->length);
+	    Tcl_InvalidateStringRep(objPtr);
+	}
+	objPtr->bytes = new;
+	objPtr->internalRep.longValue = (long) length;
+    }
+    objPtr->length = length;
+    if ((objPtr->bytes != NULL) && (objPtr->bytes != tclEmptyStringRep)) {
+	objPtr->bytes[length] = 0;
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AppendToObj --
+ *
+ *	This procedure appends a sequence of bytes to an object.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The bytes at *bytes are appended to the string representation
+ *	of objPtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_AppendToObj(objPtr, bytes, length)
+    register Tcl_Obj *objPtr;	/* Points to the object to append to. */
+    char *bytes;		/* Points to the bytes to append to the
+				 * object. */
+    register int length;	/* The number of bytes to append from
+				 * "bytes". If < 0, then append all bytes
+				 * up to NULL byte. */
+{
+    int newLength, oldLength;
+
+    if (Tcl_IsShared(objPtr)) {
+	panic("Tcl_AppendToObj called with shared object");
+    }
+    if (objPtr->typePtr != &tclStringType) {
+	ConvertToStringType(objPtr);
+    }
+    if (length < 0) {
+	length = strlen(bytes);
+    }
+    if (length == 0) {
+	return;
+    }
+    oldLength = objPtr->length;
+    newLength = length + oldLength;
+    if ((long)newLength > objPtr->internalRep.longValue) {
+	/*
+	 * There isn't currently enough space in the string
+	 * representation so allocate additional space.  In fact,
+	 * overallocate so that there is room for future growth without
+	 * having to reallocate again.
+	 */
+
+	Tcl_SetObjLength(objPtr, 2*newLength);
+    }
+    if (length > 0) {
+	memcpy((VOID *) (objPtr->bytes + oldLength), (VOID *) bytes,
+	       (size_t) length);
+	objPtr->length = newLength;
+	objPtr->bytes[objPtr->length] = 0;
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AppendStringsToObj --
+ *
+ *	This procedure appends one or more null-terminated strings
+ *	to an object.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The contents of all the string arguments are appended to the
+ *	string representation of objPtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_AppendStringsToObj TCL_VARARGS_DEF(Tcl_Obj *,arg1)
+{
+    va_list argList;
+    register Tcl_Obj *objPtr;
+    int newLength, oldLength;
+    register char *string, *dst;
+
+    objPtr = (Tcl_Obj *) TCL_VARARGS_START(Tcl_Obj *,arg1,argList);
+    if (Tcl_IsShared(objPtr)) {
+	panic("Tcl_AppendStringsToObj called with shared object");
+    }
+    if (objPtr->typePtr != &tclStringType) {
+	ConvertToStringType(objPtr);
+    }
+
+    /*
+     * Figure out how much space is needed for all the strings, and
+     * expand the string representation if it isn't big enough. If no
+     * bytes would be appended, just return.
+     */
+
+    newLength = oldLength = objPtr->length;
+    while (1) {
+	string = va_arg(argList, char *);
+	if (string == NULL) {
+	    break;
+	}
+	newLength += strlen(string);
+    }
+    if (newLength == oldLength) {
+	return;
+    }
+
+    if ((long)newLength > objPtr->internalRep.longValue) {
+	/*
+	 * There isn't currently enough space in the string
+	 * representation so allocate additional space.  If the current
+	 * string representation isn't empty (i.e. it looks like we're
+	 * doing a series of appends) then overallocate the space so
+	 * that we won't have to do as much reallocation in the future.
+	 */
+
+	Tcl_SetObjLength(objPtr,
+		(objPtr->length == 0) ? newLength : 2*newLength);
+    }
+
+    /*
+     * Make a second pass through the arguments, appending all the
+     * strings to the object.
+     */
+
+    TCL_VARARGS_START(Tcl_Obj *,arg1,argList);
+    dst = objPtr->bytes + oldLength;
+    while (1) {
+	string = va_arg(argList, char *);
+	if (string == NULL) {
+	    break;
+	}
+	while (*string != 0) {
+	    *dst = *string;
+	    dst++;
+	    string++;
+	}
+    }
+
+    /*
+     * Add a null byte to terminate the string.  However, be careful:
+     * it's possible that the object is totally empty (if it was empty
+     * originally and there was nothing to append).  In this case dst is
+     * NULL; just leave everything alone.
+     */
+
+    if (dst != NULL) {
+	*dst = 0;
+    }
+    objPtr->length = newLength;
+    va_end(argList);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConvertToStringType --
+ *
+ *	This procedure converts the internal representation of an object
+ *	to "expandable string" type.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Any old internal reputation for objPtr is freed and the
+ *	internal representation is set to that for an expandable string
+ *	(the field internalRep.longValue holds 1 less than the allocated
+ *	length of objPtr's string representation).
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ConvertToStringType(objPtr)
+    register Tcl_Obj *objPtr;	/* Pointer to object.  Must have a
+				 * typePtr that isn't &tclStringType. */
+{
+    if (objPtr->typePtr != NULL) {
+	if (objPtr->bytes == NULL) {
+	    objPtr->typePtr->updateStringProc(objPtr);
+	}
+	if (objPtr->typePtr->freeIntRepProc != NULL) {
+	    objPtr->typePtr->freeIntRepProc(objPtr);
+	}
+    }
+    objPtr->typePtr = &tclStringType;
+    if (objPtr->bytes != NULL) {
+	objPtr->internalRep.longValue = (long)objPtr->length;
+    } else {
+	objPtr->internalRep.longValue = 0;
+	objPtr->length = 0;
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupStringInternalRep --
+ *
+ *	Initialize the internal representation of a new Tcl_Obj to a
+ *	copy of the internal representation of an existing string object.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	copyPtr's internal rep is set to a copy of srcPtr's internal
+ *	representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DupStringInternalRep(srcPtr, copyPtr)
+    register Tcl_Obj *srcPtr;	/* Object with internal rep to copy.  Must
+				 * have an internal representation of type
+				 * "expandable string". */
+    register Tcl_Obj *copyPtr;	/* Object with internal rep to set.  Must
+				 * not currently have an internal rep.*/
+{
+    /*
+     * Tricky point: the string value was copied by generic object
+     * management code, so it doesn't contain any extra bytes that
+     * might exist in the source object.
+     */
+
+    copyPtr->internalRep.longValue = (long)copyPtr->length;
+    copyPtr->typePtr = &tclStringType;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetStringFromAny --
+ *
+ *	Create an internal representation of type "expandable string"
+ *	for an object.
+ *
+ * Results:
+ *	This operation always succeeds and returns TCL_OK.
+ *
+ * Side effects:
+ *	This procedure does nothing; there is no advantage in converting
+ *	the internal representation now, so we just defer it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetStringFromAny(interp, objPtr)
+    Tcl_Interp *interp;		/* Used for error reporting if not NULL. */
+    Tcl_Obj *objPtr;		/* The object to convert. */
+{
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateStringOfString --
+ *
+ *	Update the string representation for an object whose internal
+ *	representation is "expandable string".
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateStringOfString(objPtr)
+    Tcl_Obj *objPtr;		/* Object with string rep to update. */
+{
+    /*
+     * The string is almost always valid already, in which case there's
+     * nothing for us to do. The only case we have to worry about is if
+     * the object is totally null. In this case, set the string rep to
+     * an empty string.
+     */
+
+    if (objPtr->bytes == NULL) {
+	objPtr->bytes = tclEmptyStringRep;
+	objPtr->length = 0;
+    }
+    return;
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclUnixPort.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclUnixPort.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclUnixPort.h	(revision 5)
@@ -0,0 +1,49 @@
+/*
+ * tclUnixPort.h --
+ *
+ *	This header file handles porting issues that occur because
+ *	of differences between systems.  It reads in UNIX-related
+ *	header files and sets up UNIX-related macros for Tcl's UNIX
+ *	core.  It should be the only file that contains #ifdefs to
+ *	handle different flavors of UNIX.  This file sets up the
+ *	union of all UNIX-related things needed by any of the Tcl
+ *	core files.  This file depends on configuration #defines such
+ *	as NO_DIRENT_H that are set up by the "configure" script.
+ *
+ *	Much of the material in this file was originally contributed
+ *	by Karl Lehenbauer, Mark Diekhans and Peter da Silva.
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclUnixPort.h,v 1.1 2008-06-04 13:58:11 demin Exp $
+ */
+
+#ifndef _TCLUNIXPORT
+#define _TCLUNIXPORT
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/*
+ * Define access mode constants if they aren't already defined.
+ */
+
+#ifndef F_OK
+#    define F_OK 00
+#endif
+#ifndef X_OK
+#    define X_OK 01
+#endif
+#ifndef W_OK
+#    define W_OK 02
+#endif
+#ifndef R_OK
+#    define R_OK 04
+#endif
+
+#endif /* _TCLUNIXPORT */
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclUtil.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclUtil.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclUtil.c	(revision 5)
@@ -0,0 +1,2659 @@
+/* 
+ * tclUtil.c --
+ *
+ *	This file contains utility procedures that are used by many Tcl
+ *	commands.
+ *
+ * Copyright (c) 1987-1993 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ *  RCS: @(#) $Id: tclUtil.c,v 1.1 2008-06-04 13:58:11 demin Exp $
+ */
+
+#include "tclInt.h"
+#include "tclPort.h"
+
+/*
+ * The following variable holds the full path name of the binary
+ * from which this application was executed, or NULL if it isn't
+ * know.  The value of the variable is set by the procedure
+ * Tcl_FindExecutable.  The storage space is dynamically allocated.
+ */
+ 
+char *tclExecutableName = NULL;
+
+/*
+ * The following values are used in the flags returned by Tcl_ScanElement
+ * and used by Tcl_ConvertElement.  The value TCL_DONT_USE_BRACES is also
+ * defined in tcl.h;  make sure its value doesn't overlap with any of the
+ * values below.
+ *
+ * TCL_DONT_USE_BRACES -	1 means the string mustn't be enclosed in
+ *				braces (e.g. it contains unmatched braces,
+ *				or ends in a backslash character, or user
+ *				just doesn't want braces);  handle all
+ *				special characters by adding backslashes.
+ * USE_BRACES -			1 means the string contains a special
+ *				character that can be handled simply by
+ *				enclosing the entire argument in braces.
+ * BRACES_UNMATCHED -		1 means that braces aren't properly matched
+ *				in the argument.
+ */
+
+#define USE_BRACES		2
+#define BRACES_UNMATCHED	4
+
+/*
+ * The following values determine the precision used when converting
+ * floating-point values to strings.  This information is linked to all
+ * of the tcl_precision variables in all interpreters via the procedure
+ * TclPrecTraceProc.
+ *
+ * NOTE: these variables are not thread-safe.
+ */
+
+static char precisionString[10] = "12";
+				/* The string value of all the tcl_precision
+				 * variables. */
+static char precisionFormat[10] = "%.12g";
+				/* The format string actually used in calls
+				 * to sprintf. */
+
+
+/*
+ * Function prototypes for local procedures in this file:
+ */
+
+static void		SetupAppendBuffer _ANSI_ARGS_((Interp *iPtr,
+			    int newSpace));
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFindElement --
+ *
+ *	Given a pointer into a Tcl list, locate the first (or next)
+ *	element in the list.
+ *
+ * Results:
+ *	The return value is normally TCL_OK, which means that the
+ *	element was successfully located.  If TCL_ERROR is returned
+ *	it means that list didn't have proper list structure;
+ *	interp->result contains a more detailed error message.
+ *
+ *	If TCL_OK is returned, then *elementPtr will be set to point to the
+ *	first element of list, and *nextPtr will be set to point to the
+ *	character just after any white space following the last character
+ *	that's part of the element. If this is the last argument in the
+ *	list, then *nextPtr will point just after the last character in the
+ *	list (i.e., at the character at list+listLength). If sizePtr is
+ *	non-NULL, *sizePtr is filled in with the number of characters in the
+ *	element.  If the element is in braces, then *elementPtr will point
+ *	to the character after the opening brace and *sizePtr will not
+ *	include either of the braces. If there isn't an element in the list,
+ *	*sizePtr will be zero, and both *elementPtr and *termPtr will point
+ *	just after the last character in the list. Note: this procedure does
+ *	NOT collapse backslash sequences.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclFindElement(interp, list, listLength, elementPtr, nextPtr, sizePtr,
+	       bracePtr)
+    Tcl_Interp *interp;		/* Interpreter to use for error reporting. 
+				 * If NULL, then no error message is left
+				 * after errors. */
+    char *list;			/* Points to the first byte of a string
+				 * containing a Tcl list with zero or more
+				 * elements (possibly in braces). */
+    int listLength;		/* Number of bytes in the list's string. */
+    char **elementPtr;		/* Where to put address of first significant
+				 * character in first element of list. */
+    char **nextPtr;		/* Fill in with location of character just
+				 * after all white space following end of
+				 * argument (next arg or end of list). */
+    int *sizePtr;		/* If non-zero, fill in with size of
+				 * element. */
+    int *bracePtr;		/* If non-zero, fill in with non-zero/zero
+				 * to indicate that arg was/wasn't
+				 * in braces. */
+{
+    char *p = list;
+    char *elemStart;		/* Points to first byte of first element. */
+    char *limit;		/* Points just after list's last byte. */
+    int openBraces = 0;		/* Brace nesting level during parse. */
+    int inQuotes = 0;
+    int size = 0;		/* Init. avoids compiler warning. */
+    int numChars;
+    char *p2;
+    
+    /*
+     * Skim off leading white space and check for an opening brace or
+     * quote. We treat embedded NULLs in the list as bytes belonging to
+     * a list element. Note: use of "isascii" below and elsewhere in this
+     * procedure is a temporary hack (7/27/90) because Mx uses characters
+     * with the high-order bit set for some things. This should probably
+     * be changed back eventually, or all of Tcl should call isascii.
+     */
+
+    limit = (list + listLength);
+    while ((p < limit) && (isspace(UCHAR(*p)))) {
+	p++;
+    }
+    if (p == limit) {		/* no element found */
+	elemStart = limit;
+	goto done;
+    }
+
+    if (*p == '{') {
+	openBraces = 1;
+	p++;
+    } else if (*p == '"') {
+	inQuotes = 1;
+	p++;
+    }
+    elemStart = p;
+    if (bracePtr != 0) {
+	*bracePtr = openBraces;
+    }
+
+    /*
+     * Find element's end (a space, close brace, or the end of the string).
+     */
+
+    while (p < limit) {
+	switch (*p) {
+
+	    /*
+	     * Open brace: don't treat specially unless the element is in
+	     * braces. In this case, keep a nesting count.
+	     */
+
+	    case '{':
+		if (openBraces != 0) {
+		    openBraces++;
+		}
+		break;
+
+	    /*
+	     * Close brace: if element is in braces, keep nesting count and
+	     * quit when the last close brace is seen.
+	     */
+
+	    case '}':
+		if (openBraces > 1) {
+		    openBraces--;
+		} else if (openBraces == 1) {
+		    size = (p - elemStart);
+		    p++;
+		    if ((p >= limit) || isspace(UCHAR(*p))) {
+			goto done;
+		    }
+
+		    /*
+		     * Garbage after the closing brace; return an error.
+		     */
+		    
+		    if (interp != NULL) {
+			char buf[100];
+			
+			p2 = p;
+			while ((p2 < limit) && (!isspace(UCHAR(*p2)))
+			        && (p2 < p+20)) {
+			    p2++;
+			}
+			sprintf(buf,
+				"list element in braces followed by \"%.*s\" instead of space",
+				(int) (p2-p), p);
+			Tcl_SetResult(interp, buf, TCL_VOLATILE);
+		    }
+		    return TCL_ERROR;
+		}
+		break;
+
+	    /*
+	     * Backslash:  skip over everything up to the end of the
+	     * backslash sequence.
+	     */
+
+	    case '\\': {
+		(void) Tcl_Backslash(p, &numChars);
+		p += (numChars - 1);
+		break;
+	    }
+
+	    /*
+	     * Space: ignore if element is in braces or quotes; otherwise
+	     * terminate element.
+	     */
+
+	    case ' ':
+	    case '\f':
+	    case '\n':
+	    case '\r':
+	    case '\t':
+	    case '\v':
+		if ((openBraces == 0) && !inQuotes) {
+		    size = (p - elemStart);
+		    goto done;
+		}
+		break;
+
+	    /*
+	     * Double-quote: if element is in quotes then terminate it.
+	     */
+
+	    case '"':
+		if (inQuotes) {
+		    size = (p - elemStart);
+		    p++;
+		    if ((p >= limit) || isspace(UCHAR(*p))) {
+			goto done;
+		    }
+
+		    /*
+		     * Garbage after the closing quote; return an error.
+		     */
+		    
+		    if (interp != NULL) {
+			char buf[100];
+			
+			p2 = p;
+			while ((p2 < limit) && (!isspace(UCHAR(*p2)))
+				 && (p2 < p+20)) {
+			    p2++;
+			}
+			sprintf(buf,
+				"list element in quotes followed by \"%.*s\" %s",
+				(int) (p2-p), p, "instead of space");
+			Tcl_SetResult(interp, buf, TCL_VOLATILE);
+		    }
+		    return TCL_ERROR;
+		}
+		break;
+	}
+	p++;
+    }
+
+
+    /*
+     * End of list: terminate element.
+     */
+
+    if (p == limit) {
+	if (openBraces != 0) {
+	    if (interp != NULL) {
+		Tcl_SetResult(interp, "unmatched open brace in list",
+			TCL_STATIC);
+	    }
+	    return TCL_ERROR;
+	} else if (inQuotes) {
+	    if (interp != NULL) {
+		Tcl_SetResult(interp, "unmatched open quote in list",
+			TCL_STATIC);
+	    }
+	    return TCL_ERROR;
+	}
+	size = (p - elemStart);
+    }
+
+    done:
+    while ((p < limit) && (isspace(UCHAR(*p)))) {
+	p++;
+    }
+    *elementPtr = elemStart;
+    *nextPtr = p;
+    if (sizePtr != 0) {
+	*sizePtr = size;
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCopyAndCollapse --
+ *
+ *	Copy a string and eliminate any backslashes that aren't in braces.
+ *
+ * Results:
+ *	There is no return value. Count characters get copied from src to
+ *	dst. Along the way, if backslash sequences are found outside braces,
+ *	the backslashes are eliminated in the copy. After scanning count
+ *	chars from source, a null character is placed at the end of dst.
+ *	Returns the number of characters that got copied.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCopyAndCollapse(count, src, dst)
+    int count;			/* Number of characters to copy from src. */
+    char *src;			/* Copy from here... */
+    char *dst;			/* ... to here. */
+{
+    char c;
+    int numRead;
+    int newCount = 0;
+
+    for (c = *src;  count > 0;  src++, c = *src, count--) {
+	if (c == '\\') {
+	    *dst = Tcl_Backslash(src, &numRead);
+	    dst++;
+	    src += numRead-1;
+	    count -= numRead-1;
+	    newCount++;
+	} else {
+	    *dst = c;
+	    dst++;
+	    newCount++;
+	}
+    }
+    *dst = 0;
+    return newCount;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SplitList --
+ *
+ *	Splits a list up into its constituent fields.
+ *
+ * Results
+ *	The return value is normally TCL_OK, which means that
+ *	the list was successfully split up.  If TCL_ERROR is
+ *	returned, it means that "list" didn't have proper list
+ *	structure;  interp->result will contain a more detailed
+ *	error message.
+ *
+ *	*argvPtr will be filled in with the address of an array
+ *	whose elements point to the elements of list, in order.
+ *	*argcPtr will get filled in with the number of valid elements
+ *	in the array.  A single block of memory is dynamically allocated
+ *	to hold both the argv array and a copy of the list (with
+ *	backslashes and braces removed in the standard way).
+ *	The caller must eventually free this memory by calling free()
+ *	on *argvPtr.  Note:  *argvPtr and *argcPtr are only modified
+ *	if the procedure returns normally.
+ *
+ * Side effects:
+ *	Memory is allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_SplitList(interp, list, argcPtr, argvPtr)
+    Tcl_Interp *interp;		/* Interpreter to use for error reporting. 
+				 * If NULL, no error message is left. */
+    char *list;			/* Pointer to string with list structure. */
+    int *argcPtr;		/* Pointer to location to fill in with
+				 * the number of elements in the list. */
+    char ***argvPtr;		/* Pointer to place to store pointer to
+				 * array of pointers to list elements. */
+{
+    char **argv;
+    char *p;
+    int length, size, i, result, elSize, brace;
+    char *element;
+
+    /*
+     * Figure out how much space to allocate.  There must be enough
+     * space for both the array of pointers and also for a copy of
+     * the list.  To estimate the number of pointers needed, count
+     * the number of space characters in the list.
+     */
+
+    for (size = 1, p = list; *p != 0; p++) {
+	if (isspace(UCHAR(*p))) {
+	    size++;
+	}
+    }
+    size++;			/* Leave space for final NULL pointer. */
+    argv = (char **) ckalloc((unsigned)
+	    ((size * sizeof(char *)) + (p - list) + 1));
+    length = strlen(list);
+    for (i = 0, p = ((char *) argv) + size*sizeof(char *);
+	    *list != 0;  i++) {
+	char *prevList = list;
+	
+	result = TclFindElement(interp, list, length, &element,
+				&list, &elSize, &brace);
+	length -= (list - prevList);
+	if (result != TCL_OK) {
+	    ckfree((char *) argv);
+	    return result;
+	}
+	if (*element == 0) {
+	    break;
+	}
+	if (i >= size) {
+	    ckfree((char *) argv);
+	    if (interp != NULL) {
+		Tcl_SetResult(interp, "internal error in Tcl_SplitList",
+			TCL_STATIC);
+	    }
+	    return TCL_ERROR;
+	}
+	argv[i] = p;
+	if (brace) {
+	    memcpy((VOID *) p, (VOID *) element, (size_t) elSize);
+	    p += elSize;
+	    *p = 0;
+	    p++;
+	} else {
+	    TclCopyAndCollapse(elSize, element, p);
+	    p += elSize+1;
+	}
+    }
+
+    argv[i] = NULL;
+    *argvPtr = argv;
+    *argcPtr = i;
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ScanElement --
+ *
+ *	This procedure is a companion procedure to Tcl_ConvertElement.
+ *	It scans a string to see what needs to be done to it (e.g. add
+ *	backslashes or enclosing braces) to make the string into a
+ *	valid Tcl list element.
+ *
+ * Results:
+ *	The return value is an overestimate of the number of characters
+ *	that will be needed by Tcl_ConvertElement to produce a valid
+ *	list element from string.  The word at *flagPtr is filled in
+ *	with a value needed by Tcl_ConvertElement when doing the actual
+ *	conversion.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_ScanElement(string, flagPtr)
+    CONST char *string;		/* String to convert to Tcl list element. */
+    int *flagPtr;		/* Where to store information to guide
+				 * Tcl_ConvertCountedElement. */
+{
+    return Tcl_ScanCountedElement(string, -1, flagPtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ScanCountedElement --
+ *
+ *	This procedure is a companion procedure to
+ *	Tcl_ConvertCountedElement.  It scans a string to see what
+ *	needs to be done to it (e.g. add backslashes or enclosing
+ *	braces) to make the string into a valid Tcl list element.
+ *	If length is -1, then the string is scanned up to the first
+ *	null byte.
+ *
+ * Results:
+ *	The return value is an overestimate of the number of characters
+ *	that will be needed by Tcl_ConvertCountedElement to produce a
+ *	valid list element from string.  The word at *flagPtr is
+ *	filled in with a value needed by Tcl_ConvertCountedElement
+ *	when doing the actual conversion.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_ScanCountedElement(string, length, flagPtr)
+    CONST char *string;		/* String to convert to Tcl list element. */
+    int length;			/* Number of bytes in string, or -1. */
+    int *flagPtr;		/* Where to store information to guide
+				 * Tcl_ConvertElement. */
+{
+    int flags, nestingLevel;
+    CONST char *p, *lastChar;
+
+    /*
+     * This procedure and Tcl_ConvertElement together do two things:
+     *
+     * 1. They produce a proper list, one that will yield back the
+     * argument strings when evaluated or when disassembled with
+     * Tcl_SplitList.  This is the most important thing.
+     * 
+     * 2. They try to produce legible output, which means minimizing the
+     * use of backslashes (using braces instead).  However, there are
+     * some situations where backslashes must be used (e.g. an element
+     * like "{abc": the leading brace will have to be backslashed.
+     * For each element, one of three things must be done:
+     *
+     * (a) Use the element as-is (it doesn't contain any special
+     * characters).  This is the most desirable option.
+     *
+     * (b) Enclose the element in braces, but leave the contents alone.
+     * This happens if the element contains embedded space, or if it
+     * contains characters with special interpretation ($, [, ;, or \),
+     * or if it starts with a brace or double-quote, or if there are
+     * no characters in the element.
+     *
+     * (c) Don't enclose the element in braces, but add backslashes to
+     * prevent special interpretation of special characters.  This is a
+     * last resort used when the argument would normally fall under case
+     * (b) but contains unmatched braces.  It also occurs if the last
+     * character of the argument is a backslash or if the element contains
+     * a backslash followed by newline.
+     *
+     * The procedure figures out how many bytes will be needed to store
+     * the result (actually, it overestimates). It also collects information
+     * about the element in the form of a flags word.
+     *
+     * Note: list elements produced by this procedure and
+     * Tcl_ConvertCountedElement must have the property that they can be
+     * enclosing in curly braces to make sub-lists.  This means, for
+     * example, that we must not leave unmatched curly braces in the
+     * resulting list element.  This property is necessary in order for
+     * procedures like Tcl_DStringStartSublist to work.
+     */
+
+    nestingLevel = 0;
+    flags = 0;
+    if (string == NULL) {
+	string = "";
+    }
+    if (length == -1) {
+	length = strlen(string);
+    }
+    lastChar = string + length;
+    p = string;
+    if ((p == lastChar) || (*p == '{') || (*p == '"')) {
+	flags |= USE_BRACES;
+    }
+    for ( ; p != lastChar; p++) {
+	switch (*p) {
+	    case '{':
+		nestingLevel++;
+		break;
+	    case '}':
+		nestingLevel--;
+		if (nestingLevel < 0) {
+		    flags |= TCL_DONT_USE_BRACES|BRACES_UNMATCHED;
+		}
+		break;
+	    case '[':
+	    case '$':
+	    case ';':
+	    case ' ':
+	    case '\f':
+	    case '\n':
+	    case '\r':
+	    case '\t':
+	    case '\v':
+		flags |= USE_BRACES;
+		break;
+	    case '\\':
+		if ((p+1 == lastChar) || (p[1] == '\n')) {
+		    flags = TCL_DONT_USE_BRACES | BRACES_UNMATCHED;
+		} else {
+		    int size;
+
+		    (void) Tcl_Backslash(p, &size);
+		    p += size-1;
+		    flags |= USE_BRACES;
+		}
+		break;
+	}
+    }
+    if (nestingLevel != 0) {
+	flags = TCL_DONT_USE_BRACES | BRACES_UNMATCHED;
+    }
+    *flagPtr = flags;
+
+    /*
+     * Allow enough space to backslash every character plus leave
+     * two spaces for braces.
+     */
+
+    return 2*(p-string) + 2;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ConvertElement --
+ *
+ *	This is a companion procedure to Tcl_ScanElement.  Given
+ *	the information produced by Tcl_ScanElement, this procedure
+ *	converts a string to a list element equal to that string.
+ *
+ * Results:
+ *	Information is copied to *dst in the form of a list element
+ *	identical to src (i.e. if Tcl_SplitList is applied to dst it
+ *	will produce a string identical to src).  The return value is
+ *	a count of the number of characters copied (not including the
+ *	terminating NULL character).
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_ConvertElement(src, dst, flags)
+    CONST char *src;		/* Source information for list element. */
+    char *dst;			/* Place to put list-ified element. */
+    int flags;			/* Flags produced by Tcl_ScanElement. */
+{
+    return Tcl_ConvertCountedElement(src, -1, dst, flags);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ConvertCountedElement --
+ *
+ *	This is a companion procedure to Tcl_ScanCountedElement.  Given
+ *	the information produced by Tcl_ScanCountedElement, this
+ *	procedure converts a string to a list element equal to that
+ *	string.
+ *
+ * Results:
+ *	Information is copied to *dst in the form of a list element
+ *	identical to src (i.e. if Tcl_SplitList is applied to dst it
+ *	will produce a string identical to src).  The return value is
+ *	a count of the number of characters copied (not including the
+ *	terminating NULL character).
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_ConvertCountedElement(src, length, dst, flags)
+    CONST char *src;		/* Source information for list element. */
+    int length;			/* Number of bytes in src, or -1. */
+    char *dst;			/* Place to put list-ified element. */
+    int flags;			/* Flags produced by Tcl_ScanElement. */
+{
+    char *p = dst;
+    CONST char *lastChar;
+
+    /*
+     * See the comment block at the beginning of the Tcl_ScanElement
+     * code for details of how this works.
+     */
+
+    if (src && length == -1) {
+	length = strlen(src);
+    }
+    if ((src == NULL) || (length == 0)) {
+	p[0] = '{';
+	p[1] = '}';
+	p[2] = 0;
+	return 2;
+    }
+    lastChar = src + length;
+    if ((flags & USE_BRACES) && !(flags & TCL_DONT_USE_BRACES)) {
+	*p = '{';
+	p++;
+	for ( ; src != lastChar; src++, p++) {
+	    *p = *src;
+	}
+	*p = '}';
+	p++;
+    } else {
+	if (*src == '{') {
+	    /*
+	     * Can't have a leading brace unless the whole element is
+	     * enclosed in braces.  Add a backslash before the brace.
+	     * Furthermore, this may destroy the balance between open
+	     * and close braces, so set BRACES_UNMATCHED.
+	     */
+
+	    p[0] = '\\';
+	    p[1] = '{';
+	    p += 2;
+	    src++;
+	    flags |= BRACES_UNMATCHED;
+	}
+	for (; src != lastChar; src++) {
+	    switch (*src) {
+		case ']':
+		case '[':
+		case '$':
+		case ';':
+		case ' ':
+		case '\\':
+		case '"':
+		    *p = '\\';
+		    p++;
+		    break;
+		case '{':
+		case '}':
+		    /*
+		     * It may not seem necessary to backslash braces, but
+		     * it is.  The reason for this is that the resulting
+		     * list element may actually be an element of a sub-list
+		     * enclosed in braces (e.g. if Tcl_DStringStartSublist
+		     * has been invoked), so there may be a brace mismatch
+		     * if the braces aren't backslashed.
+		     */
+
+		    if (flags & BRACES_UNMATCHED) {
+			*p = '\\';
+			p++;
+		    }
+		    break;
+		case '\f':
+		    *p = '\\';
+		    p++;
+		    *p = 'f';
+		    p++;
+		    continue;
+		case '\n':
+		    *p = '\\';
+		    p++;
+		    *p = 'n';
+		    p++;
+		    continue;
+		case '\r':
+		    *p = '\\';
+		    p++;
+		    *p = 'r';
+		    p++;
+		    continue;
+		case '\t':
+		    *p = '\\';
+		    p++;
+		    *p = 't';
+		    p++;
+		    continue;
+		case '\v':
+		    *p = '\\';
+		    p++;
+		    *p = 'v';
+		    p++;
+		    continue;
+	    }
+	    *p = *src;
+	    p++;
+	}
+    }
+    *p = '\0';
+    return p-dst;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_Merge --
+ *
+ *	Given a collection of strings, merge them together into a
+ *	single string that has proper Tcl list structured (i.e.
+ *	Tcl_SplitList may be used to retrieve strings equal to the
+ *	original elements, and Tcl_Eval will parse the string back
+ *	into its original elements).
+ *
+ * Results:
+ *	The return value is the address of a dynamically-allocated
+ *	string containing the merged list.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_Merge(argc, argv)
+    int argc;			/* How many strings to merge. */
+    char **argv;		/* Array of string values. */
+{
+#   define LOCAL_SIZE 20
+    int localFlags[LOCAL_SIZE], *flagPtr;
+    int numChars;
+    char *result;
+    char *dst;
+    int i;
+
+    /*
+     * Pass 1: estimate space, gather flags.
+     */
+
+    if (argc <= LOCAL_SIZE) {
+	flagPtr = localFlags;
+    } else {
+	flagPtr = (int *) ckalloc((unsigned) argc*sizeof(int));
+    }
+    numChars = 1;
+    for (i = 0; i < argc; i++) {
+	numChars += Tcl_ScanElement(argv[i], &flagPtr[i]) + 1;
+    }
+
+    /*
+     * Pass two: copy into the result area.
+     */
+
+    result = (char *) ckalloc((unsigned) numChars);
+    dst = result;
+    for (i = 0; i < argc; i++) {
+	numChars = Tcl_ConvertElement(argv[i], dst, flagPtr[i]);
+	dst += numChars;
+	*dst = ' ';
+	dst++;
+    }
+    if (dst == result) {
+	*dst = 0;
+    } else {
+	dst[-1] = 0;
+    }
+
+    if (flagPtr != localFlags) {
+	ckfree((char *) flagPtr);
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_Concat --
+ *
+ *	Concatenate a set of strings into a single large string.
+ *
+ * Results:
+ *	The return value is dynamically-allocated string containing
+ *	a concatenation of all the strings in argv, with spaces between
+ *	the original argv elements.
+ *
+ * Side effects:
+ *	Memory is allocated for the result;  the caller is responsible
+ *	for freeing the memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_Concat(argc, argv)
+    int argc;			/* Number of strings to concatenate. */
+    char **argv;		/* Array of strings to concatenate. */
+{
+    int totalSize, i;
+    char *p;
+    char *result;
+
+    for (totalSize = 1, i = 0; i < argc; i++) {
+	totalSize += strlen(argv[i]) + 1;
+    }
+    result = (char *) ckalloc((unsigned) totalSize);
+    if (argc == 0) {
+	*result = '\0';
+	return result;
+    }
+    for (p = result, i = 0; i < argc; i++) {
+	char *element;
+	int length;
+
+	/*
+	 * Clip white space off the front and back of the string
+	 * to generate a neater result, and ignore any empty
+	 * elements.
+	 */
+
+	element = argv[i];
+	while (isspace(UCHAR(*element))) {
+	    element++;
+	}
+	for (length = strlen(element);
+		(length > 0) && (isspace(UCHAR(element[length-1])))
+		&& ((length < 2) || (element[length-2] != '\\'));
+		length--) {
+	    /* Null loop body. */
+	}
+	if (length == 0) {
+	    continue;
+	}
+	memcpy((VOID *) p, (VOID *) element, (size_t) length);
+	p += length;
+	*p = ' ';
+	p++;
+    }
+    if (p != result) {
+	p[-1] = 0;
+    } else {
+	*p = 0;
+    }
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ConcatObj --
+ *
+ *	Concatenate the strings from a set of objects into a single string
+ *	object with spaces between the original strings.
+ *
+ * Results:
+ *	The return value is a new string object containing a concatenation
+ *	of the strings in objv. Its ref count is zero.
+ *
+ * Side effects:
+ *	A new object is created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_ConcatObj(objc, objv)
+    int objc;			/* Number of objects to concatenate. */
+    Tcl_Obj *CONST objv[];	/* Array of objects to concatenate. */
+{
+    int allocSize, finalSize, length, elemLength, i;
+    char *p;
+    char *element;
+    char *concatStr;
+    Tcl_Obj *objPtr;
+
+    allocSize = 0;
+    for (i = 0;  i < objc;  i++) {
+	objPtr = objv[i];
+	element = TclGetStringFromObj(objPtr, &length);
+	if ((element != NULL) && (length > 0)) {
+	    allocSize += (length + 1);
+	}
+    }
+    if (allocSize == 0) {
+	allocSize = 1;		/* enough for the NULL byte at end */
+    }
+
+    /*
+     * Allocate storage for the concatenated result. Note that allocSize
+     * is one more than the total number of characters, and so includes
+     * room for the terminating NULL byte.
+     */
+    
+    concatStr = (char *) ckalloc((unsigned) allocSize);
+
+    /*
+     * Now concatenate the elements. Clip white space off the front and back
+     * to generate a neater result, and ignore any empty elements. Also put
+     * a null byte at the end.
+     */
+
+    finalSize = 0;
+    if (objc == 0) {
+	*concatStr = '\0';
+    } else {
+	p = concatStr;
+        for (i = 0;  i < objc;  i++) {
+	    objPtr = objv[i];
+	    element = TclGetStringFromObj(objPtr, &elemLength);
+	    while ((elemLength > 0) && (isspace(UCHAR(*element)))) {
+	         element++;
+		 elemLength--;
+	    }
+
+	    /*
+	     * Trim trailing white space.  But, be careful not to trim
+	     * a space character if it is preceded by a backslash: in
+	     * this case it could be significant.
+	     */
+
+	    while ((elemLength > 0)
+		    && isspace(UCHAR(element[elemLength-1]))
+		    && ((elemLength < 2) || (element[elemLength-2] != '\\'))) {
+		elemLength--;
+	    }
+	    if (elemLength == 0) {
+	         continue;	/* nothing left of this element */
+	    }
+	    memcpy((VOID *) p, (VOID *) element, (size_t) elemLength);
+	    p += elemLength;
+	    *p = ' ';
+	    p++;
+	    finalSize += (elemLength + 1);
+        }
+        if (p != concatStr) {
+	    p[-1] = 0;
+	    finalSize -= 1;	/* we overwrote the final ' ' */
+        } else {
+	    *p = 0;
+        }
+    }
+    
+    TclNewObj(objPtr);
+    objPtr->bytes  = concatStr;
+    objPtr->length = finalSize;
+    return objPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_StringMatch --
+ *
+ *	See if a particular string matches a particular pattern.
+ *
+ * Results:
+ *	The return value is 1 if string matches pattern, and
+ *	0 otherwise.  The matching operation permits the following
+ *	special characters in the pattern: *?\[] (see the manual
+ *	entry for details on what these mean).
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_StringMatch(string, pattern)
+    char *string;		/* String. */
+    char *pattern;		/* Pattern, which may contain special
+				 * characters. */
+{
+    char c2;
+
+    while (1) {
+	/* See if we're at the end of both the pattern and the string.
+	 * If so, we succeeded.  If we're at the end of the pattern
+	 * but not at the end of the string, we failed.
+	 */
+	
+	if (*pattern == 0) {
+	    if (*string == 0) {
+		return 1;
+	    } else {
+		return 0;
+	    }
+	}
+	if ((*string == 0) && (*pattern != '*')) {
+	    return 0;
+	}
+
+	/* Check for a "*" as the next pattern character.  It matches
+	 * any substring.  We handle this by calling ourselves
+	 * recursively for each postfix of string, until either we
+	 * match or we reach the end of the string.
+	 */
+	
+	if (*pattern == '*') {
+	    pattern += 1;
+	    if (*pattern == 0) {
+		return 1;
+	    }
+	    while (1) {
+		if (Tcl_StringMatch(string, pattern)) {
+		    return 1;
+		}
+		if (*string == 0) {
+		    return 0;
+		}
+		string += 1;
+	    }
+	}
+    
+	/* Check for a "?" as the next pattern character.  It matches
+	 * any single character.
+	 */
+
+	if (*pattern == '?') {
+	    goto thisCharOK;
+	}
+
+	/* Check for a "[" as the next pattern character.  It is followed
+	 * by a list of characters that are acceptable, or by a range
+	 * (two characters separated by "-").
+	 */
+	
+	if (*pattern == '[') {
+	    pattern += 1;
+	    while (1) {
+		if ((*pattern == ']') || (*pattern == 0)) {
+		    return 0;
+		}
+		if (*pattern == *string) {
+		    break;
+		}
+		if (pattern[1] == '-') {
+		    c2 = pattern[2];
+		    if (c2 == 0) {
+			return 0;
+		    }
+		    if ((*pattern <= *string) && (c2 >= *string)) {
+			break;
+		    }
+		    if ((*pattern >= *string) && (c2 <= *string)) {
+			break;
+		    }
+		    pattern += 2;
+		}
+		pattern += 1;
+	    }
+	    while (*pattern != ']') {
+		if (*pattern == 0) {
+		    pattern--;
+		    break;
+		}
+		pattern += 1;
+	    }
+	    goto thisCharOK;
+	}
+    
+	/* If the next pattern character is '/', just strip off the '/'
+	 * so we do exact matching on the character that follows.
+	 */
+	
+	if (*pattern == '\\') {
+	    pattern += 1;
+	    if (*pattern == 0) {
+		return 0;
+	    }
+	}
+
+	/* There's no special character.  Just make sure that the next
+	 * characters of each string match.
+	 */
+	
+	if (*pattern != *string) {
+	    return 0;
+	}
+
+	thisCharOK: pattern += 1;
+	string += 1;
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetResult --
+ *
+ *	Arrange for "string" to be the Tcl return value.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	interp->result is left pointing either to "string" (if "copy" is 0)
+ *	or to a copy of string. Also, the object result is reset.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetResult(interp, string, freeProc)
+    Tcl_Interp *interp;		/* Interpreter with which to associate the
+				 * return value. */
+    char *string;		/* Value to be returned.  If NULL, the
+				 * result is set to an empty string. */
+    Tcl_FreeProc *freeProc;	/* Gives information about the string:
+				 * TCL_STATIC, TCL_VOLATILE, or the address
+				 * of a Tcl_FreeProc such as free. */
+{
+    Interp *iPtr = (Interp *) interp;
+    int length;
+    Tcl_FreeProc *oldFreeProc = iPtr->freeProc;
+    char *oldResult = iPtr->result;
+
+    if (string == NULL) {
+	iPtr->resultSpace[0] = 0;
+	iPtr->result = iPtr->resultSpace;
+	iPtr->freeProc = 0;
+    } else if (freeProc == TCL_VOLATILE) {
+	length = strlen(string);
+	if (length > TCL_RESULT_SIZE) {
+	    iPtr->result = (char *) ckalloc((unsigned) length+1);
+	    iPtr->freeProc = TCL_DYNAMIC;
+	} else {
+	    iPtr->result = iPtr->resultSpace;
+	    iPtr->freeProc = 0;
+	}
+	strcpy(iPtr->result, string);
+    } else {
+	iPtr->result = string;
+	iPtr->freeProc = freeProc;
+    }
+
+    /*
+     * If the old result was dynamically-allocated, free it up.  Do it
+     * here, rather than at the beginning, in case the new result value
+     * was part of the old result value.
+     */
+
+    if (oldFreeProc != 0) {
+	if ((oldFreeProc == TCL_DYNAMIC)
+		|| (oldFreeProc == (Tcl_FreeProc *) free)) {
+	    ckfree(oldResult);
+	} else {
+	    (*oldFreeProc)(oldResult);
+	}
+    }
+
+    /*
+     * Reset the object result since we just set the string result.
+     */
+
+    TclResetObjResult(iPtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetStringResult --
+ *
+ *	Returns an interpreter's result value as a string.
+ *
+ * Results:
+ *	The interpreter's result as a string.
+ *
+ * Side effects:
+ *	If the string result is empty, the object result is moved to the
+ *	string result, then the object result is reset.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_GetStringResult(interp)
+     Tcl_Interp *interp;	/* Interpreter whose result to return. */
+{
+    /*
+     * If the string result is empty, move the object result to the
+     * string result, then reset the object result.
+     * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS.
+     */
+    
+    if (*(interp->result) == 0) {
+	Tcl_SetResult(interp,
+	        TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL),
+	        TCL_VOLATILE);
+    }
+    return interp->result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetObjResult --
+ *
+ *	Arrange for objPtr to be an interpreter's result value.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	interp->objResultPtr is left pointing to the object referenced
+ *	by objPtr. The object's reference count is incremented since
+ *	there is now a new reference to it. The reference count for any
+ *	old objResultPtr value is decremented. Also, the string result
+ *	is reset.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetObjResult(interp, objPtr)
+    Tcl_Interp *interp;		/* Interpreter with which to associate the
+				 * return object value. */
+    Tcl_Obj *objPtr;		/* Tcl object to be returned. If NULL, the
+				 * obj result is made an empty string
+				 * object. */
+{
+    Interp *iPtr = (Interp *) interp;
+    Tcl_Obj *oldObjResult = iPtr->objResultPtr;
+
+    iPtr->objResultPtr = objPtr;
+    Tcl_IncrRefCount(objPtr);	/* since interp result is a reference */
+
+    /*
+     * We wait until the end to release the old object result, in case
+     * we are setting the result to itself.
+     */
+    
+    TclDecrRefCount(oldObjResult);
+
+    /*
+     * Reset the string result since we just set the result object.
+     */
+
+    if (iPtr->freeProc != NULL) {
+	if ((iPtr->freeProc == TCL_DYNAMIC)
+	        || (iPtr->freeProc == (Tcl_FreeProc *) free)) {
+	    ckfree(iPtr->result);
+	} else {
+	    (*iPtr->freeProc)(iPtr->result);
+	}
+	iPtr->freeProc = 0;
+    }
+    iPtr->result = iPtr->resultSpace;
+    iPtr->resultSpace[0] = 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetObjResult --
+ *
+ *	Returns an interpreter's result value as a Tcl object. The object's
+ *	reference count is not modified; the caller must do that if it
+ *	needs to hold on to a long-term reference to it.
+ *
+ * Results:
+ *	The interpreter's result as an object.
+ *
+ * Side effects:
+ *	If the interpreter has a non-empty string result, the result object
+ *	is either empty or stale because some procedure set interp->result
+ *	directly. If so, the string result is moved to the result object
+ *	then the string result is reset.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_GetObjResult(interp)
+    Tcl_Interp *interp;		/* Interpreter whose result to return. */
+{
+    Interp *iPtr = (Interp *) interp;
+    Tcl_Obj *objResultPtr;
+    int length;
+
+    /*
+     * If the string result is non-empty, move the string result to the
+     * object result, then reset the string result.
+     */
+    
+    if (*(iPtr->result) != 0) {
+	TclResetObjResult(iPtr);
+	
+	objResultPtr = iPtr->objResultPtr;
+	length = strlen(iPtr->result);
+	TclInitStringRep(objResultPtr, iPtr->result, length);
+	
+	if (iPtr->freeProc != NULL) {
+	    if ((iPtr->freeProc == TCL_DYNAMIC)
+	            || (iPtr->freeProc == (Tcl_FreeProc *) free)) {
+		ckfree(iPtr->result);
+	    } else {
+		(*iPtr->freeProc)(iPtr->result);
+	    }
+	    iPtr->freeProc = 0;
+	}
+	iPtr->result = iPtr->resultSpace;
+	iPtr->resultSpace[0] = 0;
+    }
+    return iPtr->objResultPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AppendResult --
+ *
+ *	Append a variable number of strings onto the interpreter's string
+ *	result.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The result of the interpreter given by the first argument is
+ *	extended by the strings given by the second and following arguments
+ *	(up to a terminating NULL argument).
+ *
+ *	If the string result is empty, the object result is moved to the
+ *	string result, then the object result is reset.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_AppendResult TCL_VARARGS_DEF(Tcl_Interp *,arg1)
+{
+    va_list argList;
+    Interp *iPtr;
+    char *string;
+    int newSpace;
+
+    /*
+     * If the string result is empty, move the object result to the
+     * string result, then reset the object result.
+     * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS.
+     */
+
+    iPtr = (Interp *) TCL_VARARGS_START(Tcl_Interp *,arg1,argList);
+    if (*(iPtr->result) == 0) {
+	Tcl_SetResult((Tcl_Interp *) iPtr,
+	        TclGetStringFromObj(Tcl_GetObjResult((Tcl_Interp *) iPtr),
+		        (int *) NULL),
+	        TCL_VOLATILE);
+    }
+    
+    /*
+     * Scan through all the arguments to see how much space is needed.
+     */
+
+    newSpace = 0;
+    while (1) {
+	string = va_arg(argList, char *);
+	if (string == NULL) {
+	    break;
+	}
+	newSpace += strlen(string);
+    }
+    va_end(argList);
+
+    /*
+     * If the append buffer isn't already setup and large enough to hold
+     * the new data, set it up.
+     */
+
+    if ((iPtr->result != iPtr->appendResult)
+	    || (iPtr->appendResult[iPtr->appendUsed] != 0)
+	    || ((newSpace + iPtr->appendUsed) >= iPtr->appendAvl)) {
+       SetupAppendBuffer(iPtr, newSpace);
+    }
+
+    /*
+     * Now go through all the argument strings again, copying them into the
+     * buffer.
+     */
+
+    TCL_VARARGS_START(Tcl_Interp *,arg1,argList);
+    while (1) {
+	string = va_arg(argList, char *);
+	if (string == NULL) {
+	    break;
+	}
+	strcpy(iPtr->appendResult + iPtr->appendUsed, string);
+	iPtr->appendUsed += strlen(string);
+    }
+    va_end(argList);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AppendElement --
+ *
+ *	Convert a string to a valid Tcl list element and append it to the
+ *	result (which is ostensibly a list).
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The result in the interpreter given by the first argument is
+ *	extended with a list element converted from string. A separator
+ *	space is added before the converted list element unless the current
+ *	result is empty, contains the single character "{", or ends in " {".
+ *
+ *	If the string result is empty, the object result is moved to the
+ *	string result, then the object result is reset.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_AppendElement(interp, string)
+    Tcl_Interp *interp;		/* Interpreter whose result is to be
+				 * extended. */
+    char *string;		/* String to convert to list element and
+				 * add to result. */
+{
+    Interp *iPtr = (Interp *) interp;
+    char *dst;
+    int size;
+    int flags;
+
+    /*
+     * If the string result is empty, move the object result to the
+     * string result, then reset the object result.
+     * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS.
+     */
+
+    if (*(iPtr->result) == 0) {
+	Tcl_SetResult(interp,
+	        TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL),
+	        TCL_VOLATILE);
+    }
+
+    /*
+     * See how much space is needed, and grow the append buffer if
+     * needed to accommodate the list element.
+     */
+
+    size = Tcl_ScanElement(string, &flags) + 1;
+    if ((iPtr->result != iPtr->appendResult)
+	    || (iPtr->appendResult[iPtr->appendUsed] != 0)
+	    || ((size + iPtr->appendUsed) >= iPtr->appendAvl)) {
+       SetupAppendBuffer(iPtr, size+iPtr->appendUsed);
+    }
+
+    /*
+     * Convert the string into a list element and copy it to the
+     * buffer that's forming, with a space separator if needed.
+     */
+
+    dst = iPtr->appendResult + iPtr->appendUsed;
+    if (TclNeedSpace(iPtr->appendResult, dst)) {
+	iPtr->appendUsed++;
+	*dst = ' ';
+	dst++;
+    }
+    iPtr->appendUsed += Tcl_ConvertElement(string, dst, flags);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetupAppendBuffer --
+ *
+ *	This procedure makes sure that there is an append buffer properly
+ *	initialized, if necessary, from the interpreter's result, and
+ *	that it has at least enough room to accommodate newSpace new
+ *	bytes of information.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SetupAppendBuffer(iPtr, newSpace)
+    Interp *iPtr;		/* Interpreter whose result is being set up. */
+    int newSpace;		/* Make sure that at least this many bytes
+				 * of new information may be added. */
+{
+    int totalSpace;
+
+    /*
+     * Make the append buffer larger, if that's necessary, then copy the
+     * result into the append buffer and make the append buffer the official
+     * Tcl result.
+     */
+
+    if (iPtr->result != iPtr->appendResult) {
+	/*
+	 * If an oversized buffer was used recently, then free it up
+	 * so we go back to a smaller buffer.  This avoids tying up
+	 * memory forever after a large operation.
+	 */
+
+	if (iPtr->appendAvl > 500) {
+	    ckfree(iPtr->appendResult);
+	    iPtr->appendResult = NULL;
+	    iPtr->appendAvl = 0;
+	}
+	iPtr->appendUsed = strlen(iPtr->result);
+    } else if (iPtr->result[iPtr->appendUsed] != 0) {
+	/*
+	 * Most likely someone has modified a result created by
+	 * Tcl_AppendResult et al. so that it has a different size.
+	 * Just recompute the size.
+	 */
+
+	iPtr->appendUsed = strlen(iPtr->result);
+    }
+    
+    totalSpace = newSpace + iPtr->appendUsed;
+    if (totalSpace >= iPtr->appendAvl) {
+	char *new;
+
+	if (totalSpace < 100) {
+	    totalSpace = 200;
+	} else {
+	    totalSpace *= 2;
+	}
+	new = (char *) ckalloc((unsigned) totalSpace);
+	strcpy(new, iPtr->result);
+	if (iPtr->appendResult != NULL) {
+	    ckfree(iPtr->appendResult);
+	}
+	iPtr->appendResult = new;
+	iPtr->appendAvl = totalSpace;
+    } else if (iPtr->result != iPtr->appendResult) {
+	strcpy(iPtr->appendResult, iPtr->result);
+    }
+    
+    Tcl_FreeResult((Tcl_Interp *) iPtr);
+    iPtr->result = iPtr->appendResult;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_FreeResult --
+ *
+ *	This procedure frees up the memory associated with an interpreter's
+ *	string result. It also resets the interpreter's result object.
+ *	Tcl_FreeResult is most commonly used when a procedure is about to
+ *	replace one result value with another.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Frees the memory associated with interp's string result and sets
+ *	interp->freeProc to zero, but does not change interp->result or
+ *	clear error state. Resets interp's result object to an unshared
+ *	empty object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_FreeResult(interp)
+    Tcl_Interp *interp;		/* Interpreter for which to free result. */
+{
+    Interp *iPtr = (Interp *) interp;
+    
+    if (iPtr->freeProc != NULL) {
+	if ((iPtr->freeProc == TCL_DYNAMIC)
+	        || (iPtr->freeProc == (Tcl_FreeProc *) free)) {
+	    ckfree(iPtr->result);
+	} else {
+	    (*iPtr->freeProc)(iPtr->result);
+	}
+	iPtr->freeProc = 0;
+    }
+    
+    TclResetObjResult(iPtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ResetResult --
+ *
+ *	This procedure resets both the interpreter's string and object
+ *	results.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	It resets the result object to an unshared empty object. It
+ *	then restores the interpreter's string result area to its default
+ *	initialized state, freeing up any memory that may have been
+ *	allocated. It also clears any error information for the interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_ResetResult(interp)
+    Tcl_Interp *interp;		/* Interpreter for which to clear result. */
+{
+    Interp *iPtr = (Interp *) interp;
+
+    TclResetObjResult(iPtr);
+    
+    Tcl_FreeResult(interp);
+    iPtr->result = iPtr->resultSpace;
+    iPtr->resultSpace[0] = 0;
+    
+    iPtr->flags &= ~(ERR_ALREADY_LOGGED | ERR_IN_PROGRESS | ERROR_CODE_SET);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetErrorCode --
+ *
+ *	This procedure is called to record machine-readable information
+ *	about an error that is about to be returned.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The errorCode global variable is modified to hold all of the
+ *	arguments to this procedure, in a list form with each argument
+ *	becoming one element of the list.  A flag is set internally
+ *	to remember that errorCode has been set, so the variable doesn't
+ *	get set automatically when the error is returned.
+ *
+ *----------------------------------------------------------------------
+ */
+	/* VARARGS2 */
+void
+Tcl_SetErrorCode TCL_VARARGS_DEF(Tcl_Interp *,arg1)
+{
+    va_list argList;
+    char *string;
+    int flags;
+    Interp *iPtr;
+
+    /*
+     * Scan through the arguments one at a time, appending them to
+     * $errorCode as list elements.
+     */
+
+    iPtr = (Interp *) TCL_VARARGS_START(Tcl_Interp *,arg1,argList);
+    flags = TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT;
+    while (1) {
+	string = va_arg(argList, char *);
+	if (string == NULL) {
+	    break;
+	}
+	(void) Tcl_SetVar2((Tcl_Interp *) iPtr, "errorCode",
+		(char *) NULL, string, flags);
+	flags |= TCL_APPEND_VALUE;
+    }
+    va_end(argList);
+    iPtr->flags |= ERROR_CODE_SET;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetObjErrorCode --
+ *
+ *	This procedure is called to record machine-readable information
+ *	about an error that is about to be returned. The caller should
+ *	build a list object up and pass it to this routine.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The errorCode global variable is modified to be the new value.
+ *	A flag is set internally to remember that errorCode has been
+ *	set, so the variable doesn't get set automatically when the
+ *	error is returned.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetObjErrorCode(interp, errorObjPtr)
+    Tcl_Interp *interp;
+    Tcl_Obj *errorObjPtr;
+{
+    Tcl_Obj *namePtr;
+    Interp *iPtr;
+    
+    namePtr = Tcl_NewStringObj("errorCode", -1);
+    iPtr = (Interp *) interp;
+    Tcl_ObjSetVar2(interp, namePtr, (Tcl_Obj *) NULL, errorObjPtr,
+	    TCL_GLOBAL_ONLY);
+    iPtr->flags |= ERROR_CODE_SET;
+    Tcl_DecrRefCount(namePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DStringInit --
+ *
+ *	Initializes a dynamic string, discarding any previous contents
+ *	of the string (Tcl_DStringFree should have been called already
+ *	if the dynamic string was previously in use).
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The dynamic string is initialized to be empty.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DStringInit(dsPtr)
+    Tcl_DString *dsPtr;		/* Pointer to structure for dynamic string. */
+{
+    dsPtr->string = dsPtr->staticSpace;
+    dsPtr->length = 0;
+    dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE;
+    dsPtr->staticSpace[0] = 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DStringAppend --
+ *
+ *	Append more characters to the current value of a dynamic string.
+ *
+ * Results:
+ *	The return value is a pointer to the dynamic string's new value.
+ *
+ * Side effects:
+ *	Length bytes from string (or all of string if length is less
+ *	than zero) are added to the current value of the string. Memory
+ *	gets reallocated if needed to accomodate the string's new size.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_DStringAppend(dsPtr, string, length)
+    Tcl_DString *dsPtr;		/* Structure describing dynamic string. */
+    CONST char *string;		/* String to append.  If length is -1 then
+				 * this must be null-terminated. */
+    int length;			/* Number of characters from string to
+				 * append.  If < 0, then append all of string,
+				 * up to null at end. */
+{
+    int newSize;
+    char *newString, *dst;
+    CONST char *end;
+
+    if (length < 0) {
+	length = strlen(string);
+    }
+    newSize = length + dsPtr->length;
+
+    /*
+     * Allocate a larger buffer for the string if the current one isn't
+     * large enough. Allocate extra space in the new buffer so that there
+     * will be room to grow before we have to allocate again.
+     */
+
+    if (newSize >= dsPtr->spaceAvl) {
+	dsPtr->spaceAvl = newSize*2;
+	newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl);
+	memcpy((VOID *) newString, (VOID *) dsPtr->string,
+		(size_t) dsPtr->length);
+	if (dsPtr->string != dsPtr->staticSpace) {
+	    ckfree(dsPtr->string);
+	}
+	dsPtr->string = newString;
+    }
+
+    /*
+     * Copy the new string into the buffer at the end of the old
+     * one.
+     */
+
+    for (dst = dsPtr->string + dsPtr->length, end = string+length;
+	    string < end; string++, dst++) {
+	*dst = *string;
+    }
+    *dst = '\0';
+    dsPtr->length += length;
+    return dsPtr->string;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DStringAppendElement --
+ *
+ *	Append a list element to the current value of a dynamic string.
+ *
+ * Results:
+ *	The return value is a pointer to the dynamic string's new value.
+ *
+ * Side effects:
+ *	String is reformatted as a list element and added to the current
+ *	value of the string.  Memory gets reallocated if needed to
+ *	accomodate the string's new size.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_DStringAppendElement(dsPtr, string)
+    Tcl_DString *dsPtr;		/* Structure describing dynamic string. */
+    CONST char *string;		/* String to append.  Must be
+				 * null-terminated. */
+{
+    int newSize, flags;
+    char *dst, *newString;
+
+    newSize = Tcl_ScanElement(string, &flags) + dsPtr->length + 1;
+
+    /*
+     * Allocate a larger buffer for the string if the current one isn't
+     * large enough.  Allocate extra space in the new buffer so that there
+     * will be room to grow before we have to allocate again.
+     * SPECIAL NOTE: must use memcpy, not strcpy, to copy the string
+     * to a larger buffer, since there may be embedded NULLs in the
+     * string in some cases.
+     */
+
+    if (newSize >= dsPtr->spaceAvl) {
+	dsPtr->spaceAvl = newSize*2;
+	newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl);
+	memcpy((VOID *) newString, (VOID *) dsPtr->string,
+		(size_t) dsPtr->length);
+	if (dsPtr->string != dsPtr->staticSpace) {
+	    ckfree(dsPtr->string);
+	}
+	dsPtr->string = newString;
+    }
+
+    /*
+     * Convert the new string to a list element and copy it into the
+     * buffer at the end, with a space, if needed.
+     */
+
+    dst = dsPtr->string + dsPtr->length;
+    if (TclNeedSpace(dsPtr->string, dst)) {
+	*dst = ' ';
+	dst++;
+	dsPtr->length++;
+    }
+    dsPtr->length += Tcl_ConvertElement(string, dst, flags);
+    return dsPtr->string;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DStringSetLength --
+ *
+ *	Change the length of a dynamic string.  This can cause the
+ *	string to either grow or shrink, depending on the value of
+ *	length.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The length of dsPtr is changed to length and a null byte is
+ *	stored at that position in the string.  If length is larger
+ *	than the space allocated for dsPtr, then a panic occurs.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DStringSetLength(dsPtr, length)
+    Tcl_DString *dsPtr;		/* Structure describing dynamic string. */
+    int length;			/* New length for dynamic string. */
+{
+    if (length < 0) {
+	length = 0;
+    }
+    if (length >= dsPtr->spaceAvl) {
+	char *newString;
+
+	dsPtr->spaceAvl = length+1;
+	newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl);
+
+	/*
+	 * SPECIAL NOTE: must use memcpy, not strcpy, to copy the string
+	 * to a larger buffer, since there may be embedded NULLs in the
+	 * string in some cases.
+	 */
+
+	memcpy((VOID *) newString, (VOID *) dsPtr->string,
+		(size_t) dsPtr->length);
+	if (dsPtr->string != dsPtr->staticSpace) {
+	    ckfree(dsPtr->string);
+	}
+	dsPtr->string = newString;
+    }
+    dsPtr->length = length;
+    dsPtr->string[length] = 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DStringFree --
+ *
+ *	Frees up any memory allocated for the dynamic string and
+ *	reinitializes the string to an empty state.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The previous contents of the dynamic string are lost, and
+ *	the new value is an empty string.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DStringFree(dsPtr)
+    Tcl_DString *dsPtr;		/* Structure describing dynamic string. */
+{
+    if (dsPtr->string != dsPtr->staticSpace) {
+	ckfree(dsPtr->string);
+    }
+    dsPtr->string = dsPtr->staticSpace;
+    dsPtr->length = 0;
+    dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE;
+    dsPtr->staticSpace[0] = 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DStringResult --
+ *
+ *	This procedure moves the value of a dynamic string into an
+ *	interpreter as its string result. Afterwards, the dynamic string
+ *	is reset to an empty string.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The string is "moved" to interp's result, and any existing
+ *	string result for interp is freed. dsPtr is reinitialized to
+ *	an empty string.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DStringResult(interp, dsPtr)
+    Tcl_Interp *interp;		/* Interpreter whose result is to be reset. */
+    Tcl_DString *dsPtr;		/* Dynamic string that is to become the
+				 * result of interp. */
+{
+    Tcl_ResetResult(interp);
+    
+    if (dsPtr->string != dsPtr->staticSpace) {
+	interp->result = dsPtr->string;
+	interp->freeProc = TCL_DYNAMIC;
+    } else if (dsPtr->length < TCL_RESULT_SIZE) {
+	interp->result = ((Interp *) interp)->resultSpace;
+	strcpy(interp->result, dsPtr->string);
+    } else {
+	Tcl_SetResult(interp, dsPtr->string, TCL_VOLATILE);
+    }
+    
+    dsPtr->string = dsPtr->staticSpace;
+    dsPtr->length = 0;
+    dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE;
+    dsPtr->staticSpace[0] = 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DStringGetResult --
+ *
+ *	This procedure moves an interpreter's result into a dynamic string.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The interpreter's string result is cleared, and the previous
+ *	contents of dsPtr are freed.
+ *
+ *	If the string result is empty, the object result is moved to the
+ *	string result, then the object result is reset.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DStringGetResult(interp, dsPtr)
+    Tcl_Interp *interp;		/* Interpreter whose result is to be reset. */
+    Tcl_DString *dsPtr;		/* Dynamic string that is to become the
+				 * result of interp. */
+{
+    Interp *iPtr = (Interp *) interp;
+    
+    if (dsPtr->string != dsPtr->staticSpace) {
+	ckfree(dsPtr->string);
+    }
+
+    /*
+     * If the string result is empty, move the object result to the
+     * string result, then reset the object result.
+     * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS.
+     */
+
+    if (*(iPtr->result) == 0) {
+	Tcl_SetResult(interp,
+	        TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL),
+	        TCL_VOLATILE);
+    }
+
+    dsPtr->length = strlen(iPtr->result);
+    if (iPtr->freeProc != NULL) {
+	if ((iPtr->freeProc == TCL_DYNAMIC)
+		|| (iPtr->freeProc == (Tcl_FreeProc *) free)) {
+	    dsPtr->string = iPtr->result;
+	    dsPtr->spaceAvl = dsPtr->length+1;
+	} else {
+	    dsPtr->string = (char *) ckalloc((unsigned) (dsPtr->length+1));
+	    strcpy(dsPtr->string, iPtr->result);
+	    (*iPtr->freeProc)(iPtr->result);
+	}
+	dsPtr->spaceAvl = dsPtr->length+1;
+	iPtr->freeProc = NULL;
+    } else {
+	if (dsPtr->length < TCL_DSTRING_STATIC_SIZE) {
+	    dsPtr->string = dsPtr->staticSpace;
+	    dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE;
+	} else {
+	    dsPtr->string = (char *) ckalloc((unsigned) (dsPtr->length + 1));
+	    dsPtr->spaceAvl = dsPtr->length + 1;
+	}
+	strcpy(dsPtr->string, iPtr->result);
+    }
+    
+    iPtr->result = iPtr->resultSpace;
+    iPtr->resultSpace[0] = 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DStringStartSublist --
+ *
+ *	This procedure adds the necessary information to a dynamic
+ *	string (e.g. " {" to start a sublist.  Future element
+ *	appends will be in the sublist rather than the main list.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Characters get added to the dynamic string.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DStringStartSublist(dsPtr)
+    Tcl_DString *dsPtr;			/* Dynamic string. */
+{
+    if (TclNeedSpace(dsPtr->string, dsPtr->string + dsPtr->length)) {
+	Tcl_DStringAppend(dsPtr, " {", -1);
+    } else {
+	Tcl_DStringAppend(dsPtr, "{", -1);
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DStringEndSublist --
+ *
+ *	This procedure adds the necessary characters to a dynamic
+ *	string to end a sublist (e.g. "}").  Future element appends
+ *	will be in the enclosing (sub)list rather than the current
+ *	sublist.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DStringEndSublist(dsPtr)
+    Tcl_DString *dsPtr;			/* Dynamic string. */
+{
+    Tcl_DStringAppend(dsPtr, "}", -1);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_PrintDouble --
+ *
+ *	Given a floating-point value, this procedure converts it to
+ *	an ASCII string using.
+ *
+ * Results:
+ *	The ASCII equivalent of "value" is written at "dst".  It is
+ *	written using the current precision, and it is guaranteed to
+ *	contain a decimal point or exponent, so that it looks like
+ *	a floating-point value and not an integer.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_PrintDouble(interp, value, dst)
+    Tcl_Interp *interp;			/* Interpreter whose tcl_precision
+					 * variable used to be used to control
+					 * printing.  It's ignored now. */
+    double value;			/* Value to print as string. */
+    char *dst;				/* Where to store converted value;
+					 * must have at least TCL_DOUBLE_SPACE
+					 * characters. */
+{
+    char *p;
+
+    sprintf(dst, precisionFormat, value);
+
+    /*
+     * If the ASCII result looks like an integer, add ".0" so that it
+     * doesn't look like an integer anymore.  This prevents floating-point
+     * values from being converted to integers unintentionally.
+     */
+
+    for (p = dst; *p != 0; p++) {
+	if ((*p == '.') || (isalpha(UCHAR(*p)))) {
+	    return;
+	}
+    }
+    p[0] = '.';
+    p[1] = '0';
+    p[2] = 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclPrecTraceProc --
+ *
+ *	This procedure is invoked whenever the variable "tcl_precision"
+ *	is written.
+ *
+ * Results:
+ *	Returns NULL if all went well, or an error message if the
+ *	new value for the variable doesn't make sense.
+ *
+ * Side effects:
+ *	If the new value doesn't make sense then this procedure
+ *	undoes the effect of the variable modification.  Otherwise
+ *	it modifies the format string that's used by Tcl_PrintDouble.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+char *
+TclPrecTraceProc(clientData, interp, name1, name2, flags)
+    ClientData clientData;	/* Not used. */
+    Tcl_Interp *interp;		/* Interpreter containing variable. */
+    char *name1;		/* Name of variable. */
+    char *name2;		/* Second part of variable name. */
+    int flags;			/* Information about what happened. */
+{
+    char *value, *end;
+    int prec;
+
+    /*
+     * If the variable is unset, then recreate the trace.
+     */
+
+    if (flags & TCL_TRACE_UNSETS) {
+	if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
+	    Tcl_TraceVar2(interp, name1, name2,
+		    TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES
+		    |TCL_TRACE_UNSETS, TclPrecTraceProc, clientData);
+	}
+	return (char *) NULL;
+    }
+
+    /*
+     * When the variable is read, reset its value from our shared
+     * value.  This is needed in case the variable was modified in
+     * some other interpreter so that this interpreter's value is
+     * out of date.
+     */
+
+    if (flags & TCL_TRACE_READS) {
+	Tcl_SetVar2(interp, name1, name2, precisionString,
+		flags & TCL_GLOBAL_ONLY);
+	return (char *) NULL;
+    }
+
+    /*
+     * The variable is being written.  Check the new value and disallow
+     * it if it isn't reasonable or if this is a safe interpreter (we
+     * don't want safe interpreters messing up the precision of other
+     * interpreters).
+     */
+
+    value = Tcl_GetVar2(interp, name1, name2, flags & TCL_GLOBAL_ONLY);
+    if (value == NULL) {
+	value = "";
+    }
+    prec = strtoul(value, &end, 10);
+    if ((prec <= 0) || (prec > TCL_MAX_PREC) || (prec > 100) ||
+	    (end == value) || (*end != 0)) {
+	Tcl_SetVar2(interp, name1, name2, precisionString,
+		flags & TCL_GLOBAL_ONLY);
+	return "improper value for precision";
+    }
+    TclFormatInt(precisionString, prec);
+    sprintf(precisionFormat, "%%.%dg", prec);
+    return (char *) NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclNeedSpace --
+ *
+ *	This procedure checks to see whether it is appropriate to
+ *	add a space before appending a new list element to an
+ *	existing string.
+ *
+ * Results:
+ *	The return value is 1 if a space is appropriate, 0 otherwise.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclNeedSpace(start, end)
+    char *start;		/* First character in string. */
+    char *end;			/* End of string (place where space will
+				 * be added, if appropriate). */
+{
+    /*
+     * A space is needed unless either
+     * (a) we're at the start of the string, or
+     * (b) the trailing characters of the string consist of one or more
+     *     open curly braces preceded by a space or extending back to
+     *     the beginning of the string.
+     * (c) the trailing characters of the string consist of a space
+     *	   preceded by a character other than backslash.
+     */
+
+    if (end == start) {
+	return 0;
+    }
+    end--;
+    if (*end != '{') {
+	if (isspace(UCHAR(*end)) && ((end == start) || (end[-1] != '\\'))) {
+	    return 0;
+	}
+	return 1;
+    }
+    do {
+	if (end == start) {
+	    return 0;
+	}
+	end--;
+    } while (*end == '{');
+    if (isspace(UCHAR(*end))) {
+	return 0;
+    }
+    return 1;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFormatInt --
+ *
+ *	This procedure formats an integer into a sequence of decimal digit
+ *	characters in a buffer. If the integer is negative, a minus sign is
+ *	inserted at the start of the buffer. A null character is inserted at
+ *	the end of the formatted characters. It is the caller's
+ *	responsibility to ensure that enough storage is available. This
+ *	procedure has the effect of sprintf(buffer, "%d", n) but is faster.
+ *
+ * Results:
+ *	An integer representing the number of characters formatted, not
+ *	including the terminating \0.
+ *
+ * Side effects:
+ *	The formatted characters are written into the storage pointer to
+ *	by the "buffer" argument.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclFormatInt(buffer, n)
+    char *buffer;		/* Points to the storage into which the
+				 * formatted characters are written. */
+    long n;			/* The integer to format. */
+{
+    long intVal;
+    int i;
+    int numFormatted, j;
+    char *digits = "0123456789";
+
+    /*
+     * Check first whether "n" is the maximum negative value. This is
+     * -2^(m-1) for an m-bit word, and has no positive equivalent;
+     * negating it produces the same value.
+     */
+
+    if (n == -n) {
+	sprintf(buffer, "%ld", n);
+	return strlen(buffer);
+    }
+
+    /*
+     * Generate the characters of the result backwards in the buffer.
+     */
+
+    intVal = (n < 0? -n : n);
+    i = 0;
+    buffer[0] = '\0';
+    do {
+	i++;
+	buffer[i] = digits[intVal % 10];
+	intVal = intVal/10;
+    } while (intVal > 0);
+    if (n < 0) {
+	i++;
+	buffer[i] = '-';
+    }
+    numFormatted = i;
+
+    /*
+     * Now reverse the characters.
+     */
+
+    for (j = 0;  j < i;  j++, i--) {
+	char tmp = buffer[i];
+	buffer[i] = buffer[j];
+	buffer[j] = tmp;
+    }
+    return numFormatted;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclLooksLikeInt --
+ *
+ *	This procedure decides whether the leading characters of a
+ *	string look like an integer or something else (such as a
+ *	floating-point number or string).
+ *
+ * Results:
+ *	The return value is 1 if the leading characters of p look
+ *	like a valid Tcl integer.  If they look like a floating-point
+ *	number (e.g. "e01" or "2.4"), or if they don't look like a
+ *	number at all, then 0 is returned.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclLooksLikeInt(p)
+    char *p;			/* Pointer to string. */
+{
+    while (isspace(UCHAR(*p))) {
+	p++;
+    }
+    if ((*p == '+') || (*p == '-')) {
+	p++;
+    }
+    if (!isdigit(UCHAR(*p))) {
+	return 0;
+    }
+    p++;
+    while (isdigit(UCHAR(*p))) {
+	p++;
+    }
+    if ((*p != '.') && (*p != 'e') && (*p != 'E')) {
+	return 1;
+    }
+    return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetIntForIndex --
+ *
+ *	This procedure returns an integer corresponding to the list index
+ *	held in a Tcl object. The Tcl object's value is expected to be
+ *	either an integer or the string "end". 
+ *
+ * Results:
+ *	The return value is normally TCL_OK, which means that the index was
+ *	successfully stored into the location referenced by "indexPtr".  If
+ *	the Tcl object referenced by "objPtr" has the value "end", the
+ *	value stored is "endValue". If "objPtr"s values is not "end" and
+ *	can not be converted to an integer, TCL_ERROR is returned and, if
+ *	"interp" is non-NULL, an error message is left in the interpreter's
+ *	result object.
+ *
+ * Side effects:
+ *	The object referenced by "objPtr" might be converted to an
+ *	integer object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclGetIntForIndex(interp, objPtr, endValue, indexPtr)
+     Tcl_Interp *interp;	/* Interpreter to use for error reporting. 
+				 * If NULL, then no error message is left
+				 * after errors. */
+     Tcl_Obj *objPtr;		/* Points to an object containing either
+				 * "end" or an integer. */
+     int endValue;		/* The value to be stored at "indexPtr" if
+				 * "objPtr" holds "end". */
+     int *indexPtr;		/* Location filled in with an integer
+				 * representing an index. */
+{
+    Interp *iPtr = (Interp *) interp;
+    char *bytes;
+    int index, length, result;
+
+    /*
+     * THIS FAILS IF THE INDEX OBJECT'S STRING REP CONTAINS NULLS.
+     */
+    
+    if (objPtr->typePtr == &tclIntType) {
+	*indexPtr = (int)objPtr->internalRep.longValue;
+	return TCL_OK;
+    }
+    
+    bytes = TclGetStringFromObj(objPtr, &length);
+    if ((*bytes == 'e')
+	    && (strncmp(bytes, "end", (unsigned) length) == 0)) {
+	index = endValue;
+    } else {
+	result = Tcl_GetIntFromObj((Tcl_Interp *) NULL, objPtr, &index);
+	if (result != TCL_OK) {
+	    if (iPtr != NULL) {
+		Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+			"bad index \"", bytes,
+			"\": must be integer or \"end\"", (char *) NULL);
+	    }
+	    return result;
+	}
+    }
+    *indexPtr = index;
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetNameOfExecutable --
+ *
+ *	This procedure simply returns a pointer to the internal full
+ *	path name of the executable file as computed by
+ *	Tcl_FindExecutable.  This procedure call is the C API
+ *	equivalent to the "info nameofexecutable" command.
+ *
+ * Results:
+ *	A pointer to the internal string or NULL if the internal full
+ *	path name has not been computed or unknown.
+ *
+ * Side effects:
+ *	The object referenced by "objPtr" might be converted to an
+ *	integer object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+CONST char *
+Tcl_GetNameOfExecutable()
+{
+    return (tclExecutableName);
+}
Index: trunk/Delphes/Delphes-3.0.9/external/tcl/tclVar.c
===================================================================
--- trunk/Delphes/Delphes-3.0.9/external/tcl/tclVar.c	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/external/tcl/tclVar.c	(revision 5)
@@ -0,0 +1,4682 @@
+/* 
+ * tclVar.c --
+ *
+ *	This file contains routines that implement Tcl variables
+ *	(both scalars and arrays).
+ *
+ *	The implementation of arrays is modelled after an initial
+ *	implementation by Mark Diekhans and Karl Lehenbauer.
+ *
+ * Copyright (c) 1987-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tclVar.c,v 1.1 2008-06-04 13:58:11 demin Exp $
+ */
+
+#include "tclInt.h"
+#include "tclPort.h"
+
+/*
+ * The strings below are used to indicate what went wrong when a
+ * variable access is denied.
+ */
+
+static char *noSuchVar =	"no such variable";
+static char *isArray =		"variable is array";
+static char *needArray =	"variable isn't array";
+static char *noSuchElement =	"no such element in array";
+static char *danglingElement =  "upvar refers to element in deleted array";
+static char *danglingVar =     "upvar refers to variable in deleted namespace";
+static char *badNamespace =	"parent namespace doesn't exist";
+static char *missingName =	"missing variable name";
+
+/*
+ * Forward references to procedures defined later in this file:
+ */
+
+static  char *		CallTraces _ANSI_ARGS_((Interp *iPtr, Var *arrayPtr,
+			    Var *varPtr, char *part1, char *part2,
+			    int flags));
+static void		CleanupVar _ANSI_ARGS_((Var *varPtr,
+			    Var *arrayPtr));
+static void		DeleteSearches _ANSI_ARGS_((Var *arrayVarPtr));
+static void		DeleteArray _ANSI_ARGS_((Interp *iPtr,
+			    char *arrayName, Var *varPtr, int flags));
+static int		MakeUpvar _ANSI_ARGS_((
+			    Interp *iPtr, CallFrame *framePtr,
+			    char *otherP1, char *otherP2, int otherFlags,
+			    char *myName, int myFlags));
+static Var *		NewVar _ANSI_ARGS_((void));
+static ArraySearch *	ParseSearchId _ANSI_ARGS_((Tcl_Interp *interp,
+			    Var *varPtr, char *varName, char *string));
+static void		VarErrMsg _ANSI_ARGS_((Tcl_Interp *interp,
+			    char *part1, char *part2, char *operation,
+			    char *reason));
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclLookupVar --
+ *
+ *	This procedure is used by virtually all of the variable code to
+ *	locate a variable given its name(s).
+ *
+ * Results:
+ *	The return value is a pointer to the variable structure indicated by
+ *	part1 and part2, or NULL if the variable couldn't be found. If the
+ *	variable is found, *arrayPtrPtr is filled in with the address of the
+ *	variable structure for the array that contains the variable (or NULL
+ *	if the variable is a scalar). If the variable can't be found and
+ *	either createPart1 or createPart2 are 1, a new as-yet-undefined
+ *	(VAR_UNDEFINED) variable structure is created, entered into a hash
+ *	table, and returned.
+ *
+ *	If the variable isn't found and creation wasn't specified, or some
+ *	other error occurs, NULL is returned and an error message is left in
+ *	interp->result if TCL_LEAVE_ERR_MSG is set in flags. (The result
+ *	isn't put in interp->objResultPtr because this procedure is used
+ *	by so many string-based routines.)
+ *
+ *	Note: it's possible for the variable returned to be VAR_UNDEFINED
+ *	even if createPart1 or createPart2 are 1 (these only cause the hash
+ *	table entry or array to be created). For example, the variable might
+ *	be a global that has been unset but is still referenced by a
+ *	procedure, or a variable that has been unset but it only being kept
+ *	in existence (if VAR_UNDEFINED) by a trace.
+ *
+ * Side effects:
+ *	New hashtable entries may be created if createPart1 or createPart2
+ *	are 1.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Var *
+TclLookupVar(interp, part1, part2, flags, msg, createPart1, createPart2,
+        arrayPtrPtr)
+    Tcl_Interp *interp;		/* Interpreter to use for lookup. */
+    char *part1;		/* If part2 isn't NULL, this is the name of
+				 * an array. Otherwise, if the
+				 * TCL_PARSE_PART1 flag bit is set this
+				 * is a full variable name that could
+				 * include a parenthesized array elemnt. If
+				 * TCL_PARSE_PART1 isn't present, then
+				 * this is the name of a scalar variable. */
+    char *part2;		/* Name of element within array, or NULL. */
+    int flags;			/* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
+				 * TCL_LEAVE_ERR_MSG, and
+				 * TCL_PARSE_PART1 bits matter. */
+    char *msg;			/* Verb to use in error messages, e.g.
+				 * "read" or "set". Only needed if
+				 * TCL_LEAVE_ERR_MSG is set in flags. */
+    int createPart1;		/* If 1, create hash table entry for part 1
+				 * of name, if it doesn't already exist. If
+				 * 0, return error if it doesn't exist. */
+    int createPart2;		/* If 1, create hash table entry for part 2
+				 * of name, if it doesn't already exist. If
+				 * 0, return error if it doesn't exist. */
+    Var **arrayPtrPtr;		/* If the name refers to an element of an
+				 * array, *arrayPtrPtr gets filled in with
+				 * address of array variable. Otherwise
+				 * this is set to NULL. */
+{
+    Interp *iPtr = (Interp *) interp;
+    CallFrame *varFramePtr = iPtr->varFramePtr;
+				/* Points to the procedure call frame whose
+				 * variables are currently in use. Same as
+				 * the current procedure's frame, if any,
+				 * unless an "uplevel" is executing. */
+    Tcl_HashTable *tablePtr;	/* Points to the hashtable, if any, in which
+				 * to look up the variable. */
+    Tcl_Var var;                /* Used to search for global names. */
+    Var *varPtr;		/* Points to the Var structure returned for
+    				 * the variable. */
+    char *elName;		/* Name of array element or NULL; may be
+				 * same as part2, or may be openParen+1. */
+    char *openParen, *closeParen;
+                                /* If this procedure parses a name into
+				 * array and index, these point to the
+				 * parens around the index.  Otherwise they
+				 * are NULL. These are needed to restore
+				 * the parens after parsing the name. */
+    Namespace *varNsPtr, *cxtNsPtr, *dummy1Ptr, *dummy2Ptr;
+    ResolverScheme *resPtr;
+    Tcl_HashEntry *hPtr;
+    register char *p;
+    int new, i, result;
+
+    varPtr = NULL;
+    *arrayPtrPtr = NULL;
+    openParen = closeParen = NULL;
+    varNsPtr = NULL;		/* set non-NULL if a nonlocal variable */
+
+    /*
+     * If the name hasn't been parsed into array name and index yet,
+     * do it now.
+     */
+
+    elName = part2;
+    if (flags & TCL_PARSE_PART1) {
+	for (p = part1; ; p++) {
+	    if (*p == 0) {
+		elName = NULL;
+		break;
+	    }
+	    if (*p == '(') {
+		openParen = p;
+		do {
+		    p++;
+		} while (*p != '\0');
+		p--;
+		if (*p == ')') {
+		    closeParen = p;
+		    *openParen = 0;
+		    elName = openParen+1;
+		} else {
+		    openParen = NULL;
+		    elName = NULL;
+		}
+		break;
+	    }
+	}
+    }
+
+    /*
+     * If this namespace has a variable resolver, then give it first
+     * crack at the variable resolution.  It may return a Tcl_Var
+     * value, it may signal to continue onward, or it may signal
+     * an error.
+     */
+    if ((flags & TCL_GLOBAL_ONLY) != 0 || iPtr->varFramePtr == NULL) {
+        cxtNsPtr = iPtr->globalNsPtr;
+    } else {
+        cxtNsPtr = iPtr->varFramePtr->nsPtr;
+    }
+
+    if (cxtNsPtr->varResProc != NULL || iPtr->resolverPtr != NULL) {
+        resPtr = iPtr->resolverPtr;
+
+        if (cxtNsPtr->varResProc) {
+            result = (*cxtNsPtr->varResProc)(interp, part1,
+		    (Tcl_Namespace *) cxtNsPtr, flags, &var);
+        } else {
+            result = TCL_CONTINUE;
+        }
+
+        while (result == TCL_CONTINUE && resPtr) {
+            if (resPtr->varResProc) {
+                result = (*resPtr->varResProc)(interp, part1,
+			(Tcl_Namespace *) cxtNsPtr, flags, &var);
+            }
+            resPtr = resPtr->nextPtr;
+        }
+
+        if (result == TCL_OK) {
+            varPtr = (Var *) var;
+            goto lookupVarPart2;
+        } else if (result != TCL_CONTINUE) {
+            return (Var *) NULL;
+        }
+    }
+
+    /*
+     * Look up part1. Look it up as either a namespace variable or as a
+     * local variable in a procedure call frame (varFramePtr).
+     * Interpret part1 as a namespace variable if:
+     *    1) so requested by a TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY flag,
+     *    2) there is no active frame (we're at the global :: scope),
+     *    3) the active frame was pushed to define the namespace context
+     *       for a "namespace eval" or "namespace inscope" command,
+     *    4) the name has namespace qualifiers ("::"s).
+     * Otherwise, if part1 is a local variable, search first in the
+     * frame's array of compiler-allocated local variables, then in its
+     * hashtable for runtime-created local variables.
+     *
+     * If createPart1 and the variable isn't found, create the variable and,
+     * if necessary, create varFramePtr's local var hashtable.
+     */
+
+    if (((flags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY)) != 0)
+	    || (varFramePtr == NULL)
+	    || !varFramePtr->isProcCallFrame
+	    || (strstr(part1, "::") != NULL)) {
+	char *tail;
+	
+	/*
+	 * Don't pass TCL_LEAVE_ERR_MSG, we may yet create the variable,
+	 * or otherwise generate our own error!
+	 */
+	var = Tcl_FindNamespaceVar(interp, part1, (Tcl_Namespace *) NULL,
+		flags & ~TCL_LEAVE_ERR_MSG);
+	if (var != (Tcl_Var) NULL) {
+            varPtr = (Var *) var;
+        }
+	if (varPtr == NULL) {
+	    if (createPart1) {   /* var wasn't found so create it  */
+		TclGetNamespaceForQualName(interp, part1, (Namespace *) NULL,
+			flags, &varNsPtr, &dummy1Ptr, &dummy2Ptr, &tail);
+		if (varNsPtr == NULL) {
+		    if (flags & TCL_LEAVE_ERR_MSG) {
+			VarErrMsg(interp, part1, part2, msg, badNamespace);
+		    }
+		    goto done;
+		}
+		if (tail == NULL) {
+		    if (flags & TCL_LEAVE_ERR_MSG) {
+			VarErrMsg(interp, part1, part2, msg, missingName);
+		    }
+		    goto done;
+		}
+		hPtr = Tcl_CreateHashEntry(&varNsPtr->varTable, tail, &new);
+		varPtr = NewVar();
+		Tcl_SetHashValue(hPtr, varPtr);
+		varPtr->hPtr = hPtr;
+		varPtr->nsPtr = varNsPtr;
+	    } else {		/* var wasn't found and not to create it */
+		if (flags & TCL_LEAVE_ERR_MSG) {
+		    VarErrMsg(interp, part1, part2, msg, noSuchVar);
+		}
+		goto done;
+	    }
+	}
+    } else {			/* local var: look in frame varFramePtr */
+	Proc *procPtr = varFramePtr->procPtr;
+	int localCt = procPtr->numCompiledLocals;
+	CompiledLocal *localPtr = procPtr->firstLocalPtr;
+	Var *localVarPtr = varFramePtr->compiledLocals;
+	int part1Len = strlen(part1);
+	
+	for (i = 0;  i < localCt;  i++) {
+	    if (!TclIsVarTemporary(localPtr)) {
+		char *localName = localVarPtr->name;
+		if ((part1[0] == localName[0])
+		        && (part1Len == localPtr->nameLength)
+		        && (strcmp(part1, localName) == 0)) {
+		    varPtr = localVarPtr;
+		    break;
+		}
+	    }
+	    localVarPtr++;
+	    localPtr = localPtr->nextPtr;
+	}
+	if (varPtr == NULL) {	/* look in the frame's var hash table */
+	    tablePtr = varFramePtr->varTablePtr;
+	    if (createPart1) {
+		if (tablePtr == NULL) {
+		    tablePtr = (Tcl_HashTable *)
+			ckalloc(sizeof(Tcl_HashTable));
+		    Tcl_InitHashTable(tablePtr, TCL_STRING_KEYS);
+		    varFramePtr->varTablePtr = tablePtr;
+		}
+		hPtr = Tcl_CreateHashEntry(tablePtr, part1, &new);
+		if (new) {
+		    varPtr = NewVar();
+		    Tcl_SetHashValue(hPtr, varPtr);
+		    varPtr->hPtr = hPtr;
+                    varPtr->nsPtr = NULL; /* a local variable */
+		} else {
+		    varPtr = (Var *) Tcl_GetHashValue(hPtr);
+		}
+	    } else {
+		hPtr = NULL;
+		if (tablePtr != NULL) {
+		    hPtr = Tcl_FindHashEntry(tablePtr, part1);
+		}
+		if (hPtr == NULL) {
+		    if (flags & TCL_LEAVE_ERR_MSG) {
+			VarErrMsg(interp, part1, part2, msg, noSuchVar);
+		    }
+		    goto done;
+		}
+		varPtr = (Var *) Tcl_GetHashValue(hPtr);
+	    }
+	}
+    }
+
+    lookupVarPart2:
+    if (openParen != NULL) {
+	*openParen = '(';
+	openParen = NULL;
+    }
+
+    /*
+     * If varPtr is a link variable, we have a reference to some variable
+     * that was created through an "upvar" or "global" command. Traverse
+     * through any links until we find the referenced variable.
+     */
+	
+    while (TclIsVarLink(varPtr)) {
+	varPtr = varPtr->value.linkPtr;
+    }
+
+    /*
+     * If we're not dealing with an array element, return varPtr.
+     */
+    
+    if (elName == NULL) {
+        goto done;
+    }
+
+    /*
+     * We're dealing with an array element. Make sure the variable is an
+     * array and look up the element (create the element if desired).
+     */
+
+    if (TclIsVarUndefined(varPtr) && !TclIsVarArrayElement(varPtr)) {
+	if (!createPart1) {
+	    if (flags & TCL_LEAVE_ERR_MSG) {
+		VarErrMsg(interp, part1, part2, msg, noSuchVar);
+	    }
+	    varPtr = NULL;
+	    goto done;
+	}
+
+	/*
+	 * Make sure we are not resurrecting a namespace variable from a
+	 * deleted namespace!
+	 */
+	if ((varPtr->flags & VAR_IN_HASHTABLE) && (varPtr->hPtr == NULL)) {
+	    if (flags & TCL_LEAVE_ERR_MSG) {
+		VarErrMsg(interp, part1, part2, msg, danglingVar);
+	    }
+	    varPtr = NULL;
+	    goto done;
+	}
+
+	TclSetVarArray(varPtr);
+	TclClearVarUndefined(varPtr);
+	varPtr->value.tablePtr =
+	    (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
+	Tcl_InitHashTable(varPtr->value.tablePtr, TCL_STRING_KEYS);
+    } else if (!TclIsVarArray(varPtr)) {
+	if (flags & TCL_LEAVE_ERR_MSG) {
+	    VarErrMsg(interp, part1, part2, msg, needArray);
+	}
+	varPtr = NULL;
+	goto done;
+    }
+    *arrayPtrPtr = varPtr;
+    if (closeParen != NULL) {
+	*closeParen = 0;
+    }
+    if (createPart2) {
+	hPtr = Tcl_CreateHashEntry(varPtr->value.tablePtr, elName, &new);
+	if (closeParen != NULL) {
+	    *closeParen = ')';
+	}
+	if (new) {
+	    if (varPtr->searchPtr != NULL) {
+		DeleteSearches(varPtr);
+	    }
+	    varPtr = NewVar();
+	    Tcl_SetHashValue(hPtr, varPtr);
+	    varPtr->hPtr = hPtr;
+	    varPtr->nsPtr = varNsPtr;
+	    TclSetVarArrayElement(varPtr);
+	}
+    } else {
+	hPtr = Tcl_FindHashEntry(varPtr->value.tablePtr, elName);
+	if (closeParen != NULL) {
+	    *closeParen = ')';
+	}
+	if (hPtr == NULL) {
+	    if (flags & TCL_LEAVE_ERR_MSG) {
+		VarErrMsg(interp, part1, part2, msg, noSuchElement);
+	    }
+	    varPtr = NULL;
+	    goto done;
+	}
+    }
+    varPtr = (Var *) Tcl_GetHashValue(hPtr);
+
+    done:
+    if (openParen != NULL) {
+        *openParen = '(';
+    }
+    return varPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetVar --
+ *
+ *	Return the value of a Tcl variable as a string.
+ *
+ * Results:
+ *	The return value points to the current value of varName as a string.
+ *	If the variable is not defined or can't be read because of a clash
+ *	in array usage then a NULL pointer is returned and an error message
+ *	is left in interp->result if the TCL_LEAVE_ERR_MSG flag is set.
+ *	Note: the return value is only valid up until the next change to the
+ *	variable; if you depend on the value lasting longer than that, then
+ *	make yourself a private copy.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_GetVar(interp, varName, flags)
+    Tcl_Interp *interp;		/* Command interpreter in which varName is
+				 * to be looked up. */
+    char *varName;		/* Name of a variable in interp. */
+    int flags;			/* OR-ed combination of TCL_GLOBAL_ONLY,
+				 * TCL_NAMESPACE_ONLY or TCL_LEAVE_ERR_MSG
+				 * bits. */
+{
+    return Tcl_GetVar2(interp, varName, (char *) NULL,
+	    (flags | TCL_PARSE_PART1));
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetVar2 --
+ *
+ *	Return the value of a Tcl variable as a string, given a two-part
+ *	name consisting of array name and element within array.
+ *
+ * Results:
+ *	The return value points to the current value of the variable given
+ *	by part1 and part2 as a string. If the specified variable doesn't
+ *	exist, or if there is a clash in array usage, then NULL is returned
+ *	and a message will be left in interp->result if the
+ *	TCL_LEAVE_ERR_MSG flag is set. Note: the return value is only valid
+ *	up until the next change to the variable; if you depend on the value
+ *	lasting longer than that, then make yourself a private copy.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_GetVar2(interp, part1, part2, flags)
+    Tcl_Interp *interp;		/* Command interpreter in which variable is
+				 * to be looked up. */
+    char *part1;		/* Name of an array (if part2 is non-NULL)
+				 * or the name of a variable. */
+    char *part2;		/* If non-NULL, gives the name of an element
+				 * in the array part1. */
+    int flags;			/* OR-ed combination of TCL_GLOBAL_ONLY,
+				 * TCL_NAMESPACE_ONLY, TCL_LEAVE_ERR_MSG,
+                                 * and TCL_PARSE_PART1 bits. */
+{
+    register Tcl_Obj *part1Ptr;
+    register Tcl_Obj *part2Ptr = NULL;
+    Tcl_Obj *objPtr;
+    int length;
+
+    length = strlen(part1);
+    TclNewObj(part1Ptr);
+    TclInitStringRep(part1Ptr, part1, length);
+    Tcl_IncrRefCount(part1Ptr);
+
+    if (part2 != NULL) {
+        length = strlen(part2);
+        TclNewObj(part2Ptr);
+        TclInitStringRep(part2Ptr, part2, length);
+	Tcl_IncrRefCount(part2Ptr);
+    }
+    
+    objPtr = Tcl_ObjGetVar2(interp, part1Ptr, part2Ptr, flags);
+    
+    TclDecrRefCount(part1Ptr);	    /* done with the part1 name object */
+    if (part2Ptr != NULL) {
+	TclDecrRefCount(part2Ptr);  /* and the part2 name object */
+    }
+    
+    if (objPtr == NULL) {
+	/*
+	 * Move the interpreter's object result to the string result, 
+	 * then reset the object result.
+	 * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS.
+	 */
+
+	Tcl_SetResult(interp,
+	        TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL),
+	        TCL_VOLATILE);
+	return NULL;
+    }
+
+    /*
+     * THIS FAILS IF Tcl_ObjGetVar2's RESULT'S STRING REP HAS A NULL BYTE.
+     */
+    
+    return TclGetStringFromObj(objPtr, (int *) NULL);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ObjGetVar2 --
+ *
+ *	Return the value of a Tcl variable as a Tcl object, given a
+ *	two-part name consisting of array name and element within array.
+ *
+ * Results:
+ *	The return value points to the current object value of the variable
+ *	given by part1Ptr and part2Ptr. If the specified variable doesn't
+ *	exist, or if there is a clash in array usage, then NULL is returned
+ *	and a message will be left in the interpreter's result if the
+ *	TCL_LEAVE_ERR_MSG flag is set.
+ *
+ * Side effects:
+ *	The ref count for the returned object is _not_ incremented to
+ *	reflect the returned reference; if you want to keep a reference to
+ *	the object you must increment its ref count yourself.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_ObjGetVar2(interp, part1Ptr, part2Ptr, flags)
+    Tcl_Interp *interp;		/* Command interpreter in which variable is
+				 * to be looked up. */
+    register Tcl_Obj *part1Ptr;	/* Points to an object holding the name of
+				 * an array (if part2 is non-NULL) or the
+				 * name of a variable. */
+    register Tcl_Obj *part2Ptr;	/* If non-null, points to an object holding
+				 * the name of an element in the array
+				 * part1Ptr. */
+    int flags;			/* OR-ed combination of TCL_GLOBAL_ONLY,
+				 * TCL_LEAVE_ERR_MSG, and
+				 * TCL_PARSE_PART1 bits. */
+{
+    Interp *iPtr = (Interp *) interp;
+    register Var *varPtr;
+    Var *arrayPtr;
+    char *part1, *msg;
+    char *part2 = NULL;
+
+    /*
+     * THIS FAILS IF A NAME OBJECT'S STRING REP HAS A NULL BYTE.
+     */
+
+    part1 = TclGetStringFromObj(part1Ptr, (int *) NULL);
+    if (part2Ptr != NULL) {
+	part2 = TclGetStringFromObj(part2Ptr, (int *) NULL);
+    }
+    varPtr = TclLookupVar(interp, part1, part2, flags, "read",
+            /*createPart1*/ 0, /*createPart2*/ 1, &arrayPtr);
+    if (varPtr == NULL) {
+	return NULL;
+    }
+
+    /*
+     * Invoke any traces that have been set for the variable.
+     */
+
+    if ((varPtr->tracePtr != NULL)
+	    || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL))) {
+	msg = CallTraces(iPtr, arrayPtr, varPtr, part1, part2,
+		(flags & (TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY|TCL_PARSE_PART1)) | TCL_TRACE_READS);
+	if (msg != NULL) {
+	    if (flags & TCL_LEAVE_ERR_MSG) {
+		VarErrMsg(interp, part1, part2, "read", msg);
+	    }
+	    goto errorReturn;
+	}
+    }
+
+    /*
+     * Return the element if it's an existing scalar variable.
+     */
+    
+    if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)) {
+	return varPtr->value.objPtr;
+    }
+    
+    if (flags & TCL_LEAVE_ERR_MSG) {
+	if (TclIsVarUndefined(varPtr) && (arrayPtr != NULL)
+	        && !TclIsVarUndefined(arrayPtr)) {
+	    msg = noSuchElement;
+	} else if (TclIsVarArray(varPtr)) {
+	    msg = isArray;
+	} else {
+	    msg = noSuchVar;
+	}
+	VarErrMsg(interp, part1, part2, "read", msg);
+    }
+
+    /*
+     * An error. If the variable doesn't exist anymore and no-one's using
+     * it, then free up the relevant structures and hash table entries.
+     */
+
+    errorReturn:
+    if (TclIsVarUndefined(varPtr)) {
+	CleanupVar(varPtr, arrayPtr);
+    }
+    return NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetIndexedScalar --
+ *
+ *	Return the Tcl object value of a local scalar variable in the active
+ *	procedure, given its index in the procedure's array of compiler
+ *	allocated local variables.
+ *
+ * Results:
+ *	The return value points to the current object value of the variable
+ *	given by localIndex. If the specified variable doesn't exist, or
+ *	there is a clash in array usage, or an error occurs while executing
+ *	variable traces, then NULL is returned and a message will be left in
+ *	the interpreter's result if leaveErrorMsg is 1.
+ *
+ * Side effects:
+ *	The ref count for the returned object is _not_ incremented to
+ *	reflect the returned reference; if you want to keep a reference to
+ *	the object you must increment its ref count yourself.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclGetIndexedScalar(interp, localIndex, leaveErrorMsg)
+    Tcl_Interp *interp;		/* Command interpreter in which variable is
+				 * to be looked up. */
+    int localIndex;		/* Index of variable in procedure's array
+				 * of local variables. */
+    int leaveErrorMsg;		/* 1 if to leave an error message in
+				 * interpreter's result on an error.
+				 * Otherwise no error message is left. */
+{
+    Interp *iPtr = (Interp *) interp;
+    CallFrame *varFramePtr = iPtr->varFramePtr;
+				/* Points to the procedure call frame whose
+				 * variables are currently in use. Same as
+				 * the current procedure's frame, if any,
+				 * unless an "uplevel" is executing. */
+    Var *compiledLocals = varFramePtr->compiledLocals;
+    Var *varPtr;		/* Points to the variable's in-frame Var
+				 * structure. */
+    char *varName;		/* Name of the local variable. */
+    char *msg;
+
+#ifdef TCL_COMPILE_DEBUG
+    Proc *procPtr = varFramePtr->procPtr;
+    int localCt = procPtr->numCompiledLocals;
+
+    if (compiledLocals == NULL) {
+	fprintf(stderr, "\nTclGetIndexedScalar: can't get local %i in frame 0x%x, no compiled locals\n",
+		localIndex, (unsigned int) varFramePtr);
+	panic("TclGetIndexedScalar: no compiled locals in frame 0x%x",
+		(unsigned int) varFramePtr);
+    }
+    if ((localIndex < 0) || (localIndex >= localCt)) {
+	fprintf(stderr, "\nTclGetIndexedScalar: can't get local %i in frame 0x%x with %i locals\n",
+		localIndex, (unsigned int) varFramePtr, localCt);
+	panic("TclGetIndexedScalar: bad local index %i in frame 0x%x",
+		localIndex, (unsigned int) varFramePtr);
+    }
+#endif /* TCL_COMPILE_DEBUG */
+    
+    varPtr = &(compiledLocals[localIndex]);
+    varName = varPtr->name;
+
+    /*
+     * If varPtr is a link variable, we have a reference to some variable
+     * that was created through an "upvar" or "global" command, or we have a
+     * reference to a variable in an enclosing namespace. Traverse through
+     * any links until we find the referenced variable.
+     */
+	
+    while (TclIsVarLink(varPtr)) {
+	varPtr = varPtr->value.linkPtr;
+    }
+
+    /*
+     * Invoke any traces that have been set for the variable.
+     */
+
+    if (varPtr->tracePtr != NULL) {
+	msg = CallTraces(iPtr, /*arrayPtr*/ NULL, varPtr, varName, NULL,
+	        TCL_TRACE_READS);
+	if (msg != NULL) {
+	    if (leaveErrorMsg) {
+		VarErrMsg(interp, varName, NULL, "read", msg);
+	    }
+	    return NULL;
+	}
+    }
+
+    /*
+     * Make sure we're dealing with a scalar variable and not an array, and
+     * that the variable exists (isn't undefined).
+     */
+
+    if (!TclIsVarScalar(varPtr) || TclIsVarUndefined(varPtr)) {
+	if (leaveErrorMsg) {
+	    if (TclIsVarArray(varPtr)) {
+		msg = isArray;
+	    } else {
+		msg = noSuchVar;
+	    }
+	    VarErrMsg(interp, varName, NULL, "read", msg);
+	}
+	return NULL;
+    }
+    return varPtr->value.objPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetElementOfIndexedArray --
+ *
+ *	Return the Tcl object value for an element in a local array
+ *	variable. The element is named by the object elemPtr while the 
+ *	array is specified by its index in the active procedure's array
+ *	of compiler allocated local variables.
+ *
+ * Results:
+ *	The return value points to the current object value of the
+ *	element. If the specified array or element doesn't exist, or there
+ *	is a clash in array usage, or an error occurs while executing
+ *	variable traces, then NULL is returned and a message will be left in
+ *	the interpreter's result if leaveErrorMsg is 1.
+ *
+ * Side effects:
+ *	The ref count for the returned object is _not_ incremented to
+ *	reflect the returned reference; if you want to keep a reference to
+ *	the object you must increment its ref count yourself.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclGetElementOfIndexedArray(interp, localIndex, elemPtr, leaveErrorMsg)
+    Tcl_Interp *interp;		/* Command interpreter in which variable is
+				 * to be looked up. */
+    int localIndex;		/* Index of array variable in procedure's
+				 * array of local variables. */
+    Tcl_Obj *elemPtr;		/* Points to an object holding the name of
+				 * an element to get in the array. */
+    int leaveErrorMsg;		/* 1 if to leave an error message in
+				 * the interpreter's result on an error.
+				 * Otherwise no error message is left. */
+{
+    Interp *iPtr = (Interp *) interp;
+    CallFrame *varFramePtr = iPtr->varFramePtr;
+				/* Points to the procedure call frame whose
+				 * variables are currently in use. Same as
+				 * the current procedure's frame, if any,
+				 * unless an "uplevel" is executing. */
+    Var *compiledLocals = varFramePtr->compiledLocals;
+    Var *arrayPtr;		/* Points to the array's in-frame Var
+				 * structure. */
+    char *arrayName;		/* Name of the local array. */
+    Tcl_HashEntry *hPtr;
+    Var *varPtr = NULL;		/* Points to the element's Var structure
+				 * that we return. Initialized to avoid
+				 * compiler warning. */
+    char *elem, *msg;
+    int new;
+
+#ifdef TCL_COMPILE_DEBUG
+    Proc *procPtr = varFramePtr->procPtr;
+    int localCt = procPtr->numCompiledLocals;
+
+    if (compiledLocals == NULL) {
+	fprintf(stderr, "\nTclGetElementOfIndexedArray: can't get element of local %i in frame 0x%x, no compiled locals\n",
+		localIndex, (unsigned int) varFramePtr);
+	panic("TclGetIndexedScalar: no compiled locals in frame 0x%x",
+		(unsigned int) varFramePtr);
+    }
+    if ((localIndex < 0) || (localIndex >= localCt)) {
+	fprintf(stderr, "\nTclGetIndexedScalar: can't get element of local %i in frame 0x%x with %i locals\n",
+		localIndex, (unsigned int) varFramePtr, localCt);
+	panic("TclGetElementOfIndexedArray: bad local index %i in frame 0x%x",
+		localIndex, (unsigned int) varFramePtr);
+    }
+#endif /* TCL_COMPILE_DEBUG */
+
+    /*
+     * THIS FAILS IF THE ELEMENT NAME OBJECT'S STRING REP HAS A NULL BYTE.
+     */
+    
+    elem = Tcl_GetStringFromObj(elemPtr, (int *) NULL);
+    arrayPtr = &(compiledLocals[localIndex]);
+    arrayName = arrayPtr->name;
+
+    /*
+     * If arrayPtr is a link variable, we have a reference to some variable
+     * that was created through an "upvar" or "global" command, or we have a
+     * reference to a variable in an enclosing namespace. Traverse through
+     * any links until we find the referenced variable.
+     */
+	
+    while (TclIsVarLink(arrayPtr)) {
+	arrayPtr = arrayPtr->value.linkPtr;
+    }
+
+    /*
+     * Make sure we're dealing with an array and that the array variable
+     * exists (isn't undefined).
+     */
+
+    if (!TclIsVarArray(arrayPtr) || TclIsVarUndefined(arrayPtr)) {
+	if (leaveErrorMsg) {
+	    VarErrMsg(interp, arrayName, elem, "read", noSuchVar);
+	}
+	goto errorReturn;
+    } 
+
+    /*
+     * Look up the element. Note that we must create the element (but leave
+     * it marked undefined) if it does not already exist. This allows a
+     * trace to create new array elements "on the fly" that did not exist
+     * before. A trace is always passed a variable for the array element. If
+     * the trace does not define the variable, it will be deleted below (at
+     * errorReturn) and an error returned.
+     */
+
+    hPtr = Tcl_CreateHashEntry(arrayPtr->value.tablePtr, elem, &new);
+    if (new) {
+	if (arrayPtr->searchPtr != NULL) {
+	    DeleteSearches(arrayPtr);
+	}
+	varPtr = NewVar();
+	Tcl_SetHashValue(hPtr, varPtr);
+	varPtr->hPtr = hPtr;
+	varPtr->nsPtr = varFramePtr->nsPtr;
+	TclSetVarArrayElement(varPtr);
+    } else {
+	varPtr = (Var *) Tcl_GetHashValue(hPtr);
+    }
+
+    /*
+     * Invoke any traces that have been set for the element variable.
+     */
+
+    if ((varPtr->tracePtr != NULL)
+            || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL))) {
+	msg = CallTraces(iPtr, arrayPtr, varPtr, arrayName, elem,
+	        TCL_TRACE_READS);
+	if (msg != NULL) {
+	    if (leaveErrorMsg) {
+		VarErrMsg(interp, arrayName, elem, "read", msg);
+	    }
+	    goto errorReturn;
+	}
+    }
+
+    /*
+     * Return the element if it's an existing scalar variable.
+     */
+    
+    if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)) {
+	return varPtr->value.objPtr;
+    }
+    
+    if (leaveErrorMsg) {
+	if (TclIsVarArray(varPtr)) {
+	    msg = isArray;
+	} else {
+	    msg = noSuchVar;
+	}
+	VarErrMsg(interp, arrayName, elem, "read", msg);
+    }
+
+    /*
+     * An error. If the variable doesn't exist anymore and no-one's using
+     * it, then free up the relevant structures and hash table entries.
+     */
+
+    errorReturn:
+    if ((varPtr != NULL) && TclIsVarUndefined(varPtr)) {
+	CleanupVar(varPtr, NULL); /* the array is not in a hashtable */
+    }
+    return NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetCmd --
+ *
+ *	This procedure is invoked to process the "set" Tcl command.
+ *	See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl result value.
+ *
+ * Side effects:
+ *	A variable's value may be changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_SetCmd(dummy, interp, argc, argv)
+    ClientData dummy;			/* Not used. */
+    register Tcl_Interp *interp;	/* Current interpreter. */
+    int argc;				/* Number of arguments. */
+    char **argv;			/* Argument strings. */
+{
+    if (argc == 2) {
+	char *value;
+
+	value = Tcl_GetVar2(interp, argv[1], (char *) NULL,
+		TCL_LEAVE_ERR_MSG|TCL_PARSE_PART1);
+	if (value == NULL) {
+	    return TCL_ERROR;
+	}
+	Tcl_SetResult(interp, value, TCL_VOLATILE);
+	return TCL_OK;
+    } else if (argc == 3) {
+	char *result;
+
+	result = Tcl_SetVar2(interp, argv[1], (char *) NULL, argv[2],
+		TCL_LEAVE_ERR_MSG|TCL_PARSE_PART1);
+	if (result == NULL) {
+	    return TCL_ERROR;
+	}
+	Tcl_SetResult(interp, result, TCL_VOLATILE);
+	return TCL_OK;
+    } else {
+	Tcl_AppendResult(interp, "wrong # args: should be \"",
+		argv[0], " varName ?newValue?\"", (char *) NULL);
+	return TCL_ERROR;
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetVar --
+ *
+ *	Change the value of a variable.
+ *
+ * Results:
+ *	Returns a pointer to the malloc'ed string which is the character
+ *	representation of the variable's new value. The caller must not
+ *	modify this string. If the write operation was disallowed then NULL
+ *	is returned; if the TCL_LEAVE_ERR_MSG flag is set, then an
+ *	explanatory message will be left in interp->result. Note that the
+ *	returned string may not be the same as newValue; this is because
+ *	variable traces may modify the variable's value.
+ *
+ * Side effects:
+ *	If varName is defined as a local or global variable in interp,
+ *	its value is changed to newValue. If varName isn't currently
+ *	defined, then a new global variable by that name is created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_SetVar(interp, varName, newValue, flags)
+    Tcl_Interp *interp;		/* Command interpreter in which varName is
+				 * to be looked up. */
+    char *varName;		/* Name of a variable in interp. */
+    char *newValue;		/* New value for varName. */
+    int flags;			/* Various flags that tell how to set value:
+				 * any of TCL_GLOBAL_ONLY,
+				 * TCL_NAMESPACE_ONLY, TCL_APPEND_VALUE,
+				 * TCL_LIST_ELEMENT, TCL_LEAVE_ERR_MSG. */
+{
+    return Tcl_SetVar2(interp, varName, (char *) NULL, newValue,
+	    (flags | TCL_PARSE_PART1));
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetVar2 --
+ *
+ *      Given a two-part variable name, which may refer either to a
+ *      scalar variable or an element of an array, change the value
+ *      of the variable.  If the named scalar or array or element
+ *      doesn't exist then create one.
+ *
+ * Results:
+ *	Returns a pointer to the malloc'ed string which is the character
+ *	representation of the variable's new value. The caller must not
+ *	modify this string. If the write operation was disallowed because an
+ *	array was expected but not found (or vice versa), then NULL is
+ *	returned; if the TCL_LEAVE_ERR_MSG flag is set, then an explanatory
+ *	message will be left in interp->result. Note that the returned
+ *	string may not be the same as newValue; this is because variable
+ *	traces may modify the variable's value.
+ *
+ * Side effects:
+ *      The value of the given variable is set. If either the array
+ *      or the entry didn't exist then a new one is created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_SetVar2(interp, part1, part2, newValue, flags)
+    Tcl_Interp *interp;         /* Command interpreter in which variable is
+                                 * to be looked up. */
+    char *part1;                /* If part2 is NULL, this is name of scalar
+                                 * variable. Otherwise it is the name of
+                                 * an array. */
+    char *part2;                /* Name of an element within an array, or
+				 * NULL. */
+    char *newValue;             /* New value for variable. */
+    int flags;                  /* Various flags that tell how to set value:
+				 * any of TCL_GLOBAL_ONLY,
+				 * TCL_NAMESPACE_ONLY, TCL_APPEND_VALUE,
+				 * TCL_LIST_ELEMENT, TCL_LEAVE_ERR_MSG, or 
+				 * TCL_PARSE_PART1. */
+{
+    register Tcl_Obj *valuePtr;
+    register Tcl_Obj *part1Ptr;
+    register Tcl_Obj *part2Ptr = NULL;
+    Tcl_Obj *varValuePtr;
+    int length;
+
+    /*
+     * Create an object holding the variable's new value and use
+     * Tcl_ObjSetVar2 to actually set the variable.
+     */
+
+    length = newValue ? strlen(newValue) : 0;
+    TclNewObj(valuePtr);
+    TclInitStringRep(valuePtr, newValue, length);
+    Tcl_IncrRefCount(valuePtr);
+
+    length = strlen(part1) ;
+    TclNewObj(part1Ptr);
+    TclInitStringRep(part1Ptr, part1, length);
+    Tcl_IncrRefCount(part1Ptr);
+
+    if (part2 != NULL) {
+        length = strlen(part2);
+        TclNewObj(part2Ptr);
+        TclInitStringRep(part2Ptr, part2, length);
+	Tcl_IncrRefCount(part2Ptr);
+    }
+    
+    varValuePtr = Tcl_ObjSetVar2(interp, part1Ptr, part2Ptr, valuePtr,
+	    flags);
+    
+    TclDecrRefCount(part1Ptr);      /* done with the part1 name object */
+    if (part2Ptr != NULL) {
+	TclDecrRefCount(part2Ptr);  /* and the part2 name object */
+    }
+    Tcl_DecrRefCount(valuePtr); /* done with the object */
+    
+    if (varValuePtr == NULL) {
+	/*
+	 * Move the interpreter's object result to the string result, 
+	 * then reset the object result.
+	 * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS.
+	 */
+
+	Tcl_SetResult(interp,
+	        TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL),
+	        TCL_VOLATILE);
+	return NULL;
+    }
+
+    /*
+     * THIS FAILS IF Tcl_ObjSetVar2's RESULT'S STRING REP HAS A NULL BYTE.
+     */
+
+    return TclGetStringFromObj(varValuePtr, (int *) NULL);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ObjSetVar2 --
+ *
+ *	Given a two-part variable name, which may refer either to a scalar
+ *	variable or an element of an array, change the value of the variable
+ *	to a new Tcl object value. If the named scalar or array or element
+ *	doesn't exist then create one.
+ *
+ * Results:
+ *	Returns a pointer to the Tcl_Obj holding the new value of the
+ *	variable. If the write operation was disallowed because an array was
+ *	expected but not found (or vice versa), then NULL is returned; if
+ *	the TCL_LEAVE_ERR_MSG flag is set, then an explanatory message will
+ *	be left in the interpreter's result. Note that the returned object
+ *	may not be the same one referenced by newValuePtr; this is because
+ *	variable traces may modify the variable's value.
+ *
+ * Side effects:
+ *	The value of the given variable is set. If either the array or the
+ *	entry didn't exist then a new variable is created.
+ *
+ *	The reference count is decremented for any old value of the variable
+ *	and incremented for its new value. If the new value for the variable
+ *	is not the same one referenced by newValuePtr (perhaps as a result
+ *	of a variable trace), then newValuePtr's ref count is left unchanged
+ *	by Tcl_ObjSetVar2. newValuePtr's ref count is also left unchanged if
+ *	we are appending it as a string value: that is, if "flags" includes
+ *	TCL_APPEND_VALUE but not TCL_LIST_ELEMENT.
+ *
+ *	The reference count for the returned object is _not_ incremented: if
+ *	you want to keep a reference to the object you must increment its
+ *	ref count yourself.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_ObjSetVar2(interp, part1Ptr, part2Ptr, newValuePtr, flags)
+    Tcl_Interp *interp;		/* Command interpreter in which variable is
+				 * to be found. */
+    register Tcl_Obj *part1Ptr;	/* Points to an object holding the name of
+				 * an array (if part2 is non-NULL) or the
+				 * name of a variable. */
+    register Tcl_Obj *part2Ptr;	/* If non-null, points to an object holding
+				 * the name of an element in the array
+				 * part1Ptr. */
+    Tcl_Obj *newValuePtr;	/* New value for variable. */
+    int flags;			/* Various flags that tell how to set value:
+				 * any of TCL_GLOBAL_ONLY,
+				 * TCL_NAMESPACE_ONLY, TCL_APPEND_VALUE,
+				 * TCL_LIST_ELEMENT, TCL_LEAVE_ERR_MSG, or
+				 * TCL_PARSE_PART1. */
+{
+    Interp *iPtr = (Interp *) interp;
+    register Var *varPtr;
+    Var *arrayPtr;
+    Tcl_Obj *oldValuePtr;
+    Tcl_Obj *resultPtr = NULL;
+    char *part1, *bytes;
+    char *part2 = NULL;
+    int length, result;
+
+    /*
+     * THIS FAILS IF A NAME OBJECT'S STRING REP HAS A NULL BYTE.
+     */
+
+    part1 = TclGetStringFromObj(part1Ptr, (int *) NULL);
+    if (part2Ptr != NULL) {
+	part2 = TclGetStringFromObj(part2Ptr, (int *) NULL);
+    }
+    
+    varPtr = TclLookupVar(interp, part1, part2, flags, "set",
+	    /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
+    if (varPtr == NULL) {
+	return NULL;
+    }
+
+    /*
+     * If the variable is in a hashtable and its hPtr field is NULL, then we
+     * may have an upvar to an array element where the array was deleted
+     * or an upvar to a namespace variable whose namespace was deleted.
+     * Generate an error (allowing the variable to be reset would screw up
+     * our storage allocation and is meaningless anyway).
+     */
+
+    if ((varPtr->flags & VAR_IN_HASHTABLE) && (varPtr->hPtr == NULL)) {
+	if (flags & TCL_LEAVE_ERR_MSG) {
+	    if (TclIsVarArrayElement(varPtr)) {
+		VarErrMsg(interp, part1, part2, "set", danglingElement);
+	    } else {
+		VarErrMsg(interp, part1, part2, "set", danglingVar);
+	    }
+	}
+	return NULL;
+    }
+
+    /*
+     * It's an error to try to set an array variable itself.
+     */
+
+    if (TclIsVarArray(varPtr) && !TclIsVarUndefined(varPtr)) {
+	if (flags & TCL_LEAVE_ERR_MSG) {
+	    VarErrMsg(interp, part1, part2, "set", isArray);
+	}
+	return NULL;
+    }
+
+    /*
+     * At this point, if we were appending, we used to call read traces: we
+     * treated append as a read-modify-write. However, it seemed unlikely to
+     * us that a real program would be interested in such reads being done
+     * during a set operation.
+     */
+
+    /*
+     * Set the variable's new value. If appending, append the new value to
+     * the variable, either as a list element or as a string. Also, if
+     * appending, then if the variable's old value is unshared we can modify
+     * it directly, otherwise we must create a new copy to modify: this is
+     * "copy on write".
+     */
+
+    oldValuePtr = varPtr->value.objPtr;
+    if (flags & TCL_APPEND_VALUE) {
+	if (TclIsVarUndefined(varPtr) && (oldValuePtr != NULL)) {
+	    Tcl_DecrRefCount(oldValuePtr);     /* discard old value */
+	    varPtr->value.objPtr = NULL;
+	    oldValuePtr = NULL;
+	}
+	if (flags & TCL_LIST_ELEMENT) {	       /* append list element */
+	    if (oldValuePtr == NULL) {
+		TclNewObj(oldValuePtr);
+		varPtr->value.objPtr = oldValuePtr;
+		Tcl_IncrRefCount(oldValuePtr); /* since var is reference */
+	    } else if (Tcl_IsShared(oldValuePtr)) {
+		varPtr->value.objPtr = Tcl_DuplicateObj(oldValuePtr);
+		Tcl_DecrRefCount(oldValuePtr);
+		oldValuePtr = varPtr->value.objPtr;
+		Tcl_IncrRefCount(oldValuePtr); /* since var is reference */
+	    }
+	    result = Tcl_ListObjAppendElement(interp, oldValuePtr,
+		    newValuePtr);
+	    if (result != TCL_OK) {
+		return NULL;
+	    }
+	} else {		               /* append string */
+	    /*
+	     * We append newValuePtr's bytes but don't change its ref count.
+	     */
+
+	    bytes = Tcl_GetStringFromObj(newValuePtr, &length);
+	    if (oldValuePtr == NULL) {
+		varPtr->value.objPtr = Tcl_NewStringObj(bytes, length);
+		Tcl_IncrRefCount(varPtr->value.objPtr);
+	    } else {
+		if (Tcl_IsShared(oldValuePtr)) {   /* append to copy */
+		    varPtr->value.objPtr = Tcl_DuplicateObj(oldValuePtr);
+		    TclDecrRefCount(oldValuePtr);
+		    oldValuePtr = varPtr->value.objPtr;
+		    Tcl_IncrRefCount(oldValuePtr); /* since var is ref */
+		}
+		Tcl_AppendToObj(oldValuePtr, bytes, length);
+	    }
+	}
+    } else {
+	if (flags & TCL_LIST_ELEMENT) {	       /* set var to list element */
+	    int neededBytes, listFlags;
+
+	    /*
+	     * We set the variable to the result of converting newValuePtr's
+	     * string rep to a list element. We do not change newValuePtr's
+	     * ref count.
+	     */
+
+	    if (oldValuePtr != NULL) {
+		Tcl_DecrRefCount(oldValuePtr); /* discard old value */
+	    }
+	    bytes = Tcl_GetStringFromObj(newValuePtr, &length);
+	    neededBytes = Tcl_ScanElement(bytes, &listFlags);
+	    oldValuePtr = Tcl_NewObj();
+	    oldValuePtr->bytes = (char *)
+		ckalloc((unsigned) (neededBytes + 1));
+	    oldValuePtr->length = Tcl_ConvertElement(bytes,
+		    oldValuePtr->bytes, listFlags);
+	    varPtr->value.objPtr = oldValuePtr;
+	    Tcl_IncrRefCount(varPtr->value.objPtr);
+	} else if (newValuePtr != oldValuePtr) {
+	    varPtr->value.objPtr = newValuePtr;
+	    Tcl_IncrRefCount(newValuePtr);      /* var is another ref */
+	    if (oldValuePtr != NULL) {
+		TclDecrRefCount(oldValuePtr);   /* discard old value */
+	    }
+	}
+    }
+    TclSetVarScalar(varPtr);
+    TclClearVarUndefined(varPtr);
+    if (arrayPtr != NULL) {
+	TclClearVarUndefined(arrayPtr);
+    }
+
+    /*
+     * Invoke any write traces for the variable.
+     */
+
+    if ((varPtr->tracePtr != NULL)
+	    || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL))) {
+	char *msg = CallTraces(iPtr, arrayPtr, varPtr, part1, part2,
+	        (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_PARSE_PART1)) | TCL_TRACE_WRITES);
+	if (msg != NULL) {
+	    if (flags & TCL_LEAVE_ERR_MSG) {
+		VarErrMsg(interp, part1, part2, "set", msg);
+	    }
+	    goto cleanup;
+	}
+    }
+
+    /*
+     * Return the variable's value unless the variable was changed in some
+     * gross way by a trace (e.g. it was unset and then recreated as an
+     * array). 
+     */
+
+    if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)) {
+	return varPtr->value.objPtr;
+    }
+
+    /*
+     * A trace changed the value in some gross way. Return an empty string
+     * object.
+     */
+    
+    resultPtr = iPtr->emptyObjPtr;
+
+    /*
+     * If the variable doesn't exist anymore and no-one's using it, then
+     * free up the relevant structures and hash table entries.
+     */
+
+    cleanup:
+    if (TclIsVarUndefined(varPtr)) {
+	CleanupVar(varPtr, arrayPtr);
+    }
+    return resultPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclSetIndexedScalar --
+ *
+ *	Change the Tcl object value of a local scalar variable in the active
+ *	procedure, given its compile-time allocated index in the procedure's
+ *	array of local variables.
+ *
+ * Results:
+ *	Returns a pointer to the Tcl_Obj holding the new value of the
+ *	variable given by localIndex. If the specified variable doesn't
+ *	exist, or there is a clash in array usage, or an error occurs while
+ *	executing variable traces, then NULL is returned and a message will
+ *	be left in the interpreter's result if leaveErrorMsg is 1. Note
+ *	that the returned object may not be the same one referenced by
+ *	newValuePtr; this is because variable traces may modify the
+ *	variable's value.
+ *
+ * Side effects:
+ *	The value of the given variable is set. The reference count is
+ *	decremented for any old value of the variable and incremented for
+ *	its new value. If as a result of a variable trace the new value for
+ *	the variable is not the same one referenced by newValuePtr, then
+ *	newValuePtr's ref count is left unchanged. The ref count for the
+ *	returned object is _not_ incremented to reflect the returned
+ *	reference; if you want to keep a reference to the object you must
+ *	increment its ref count yourself. This procedure does not create
+ *	new variables, but only sets those recognized at compile time.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclSetIndexedScalar(interp, localIndex, newValuePtr, leaveErrorMsg)
+    Tcl_Interp *interp;		/* Command interpreter in which variable is
+				 * to be found. */
+    int localIndex;		/* Index of variable in procedure's array
+				 * of local variables. */
+    Tcl_Obj *newValuePtr;	/* New value for variable. */
+    int leaveErrorMsg;		/* 1 if to leave an error message in
+				 * the interpreter's result on an error.
+				 * Otherwise no error message is left. */
+{
+    Interp *iPtr = (Interp *) interp;
+    CallFrame *varFramePtr = iPtr->varFramePtr;
+				/* Points to the procedure call frame whose
+				 * variables are currently in use. Same as
+				 * the current procedure's frame, if any,
+				 * unless an "uplevel" is executing. */
+    Var *compiledLocals = varFramePtr->compiledLocals;
+    register Var *varPtr;	/* Points to the variable's in-frame Var
+				 * structure. */
+    char *varName;		/* Name of the local variable. */
+    Tcl_Obj *oldValuePtr;
+    Tcl_Obj *resultPtr = NULL;
+
+#ifdef TCL_COMPILE_DEBUG
+    Proc *procPtr = varFramePtr->procPtr;
+    int localCt = procPtr->numCompiledLocals;
+
+    if (compiledLocals == NULL) {
+	fprintf(stderr, "\nTclSetIndexedScalar: can't set local %i in frame 0x%x, no compiled locals\n",
+		localIndex, (unsigned int) varFramePtr);
+	panic("TclSetIndexedScalar: no compiled locals in frame 0x%x",
+		(unsigned int) varFramePtr);
+    }
+    if ((localIndex < 0) || (localIndex >= localCt)) {
+	fprintf(stderr, "\nTclSetIndexedScalar: can't set local %i in frame 0x%x with %i locals\n",
+		localIndex, (unsigned int) varFramePtr, localCt);
+	panic("TclSetIndexedScalar: bad local index %i in frame 0x%x",
+		localIndex, (unsigned int) varFramePtr);
+    }
+#endif /* TCL_COMPILE_DEBUG */
+    
+    varPtr = &(compiledLocals[localIndex]);
+    varName = varPtr->name;
+
+    /*
+     * If varPtr is a link variable, we have a reference to some variable
+     * that was created through an "upvar" or "global" command, or we have a
+     * reference to a variable in an enclosing namespace. Traverse through
+     * any links until we find the referenced variable.
+     */
+	
+    while (TclIsVarLink(varPtr)) {
+	varPtr = varPtr->value.linkPtr;
+    }
+
+    /*
+     * If the variable is in a hashtable and its hPtr field is NULL, then we
+     * may have an upvar to an array element where the array was deleted
+     * or an upvar to a namespace variable whose namespace was deleted.
+     * Generate an error (allowing the variable to be reset would screw up
+     * our storage allocation and is meaningless anyway).
+     */
+
+    if ((varPtr->flags & VAR_IN_HASHTABLE) && (varPtr->hPtr == NULL)) {
+	if (leaveErrorMsg) {
+	    if (TclIsVarArrayElement(varPtr)) {
+		VarErrMsg(interp, varName, NULL, "set", danglingElement);
+	    } else {
+		VarErrMsg(interp, varName, NULL, "set", danglingVar);
+	    }
+	}
+	return NULL;
+    }
+
+    /*
+     * It's an error to try to set an array variable itself.
+     */
+
+    if (TclIsVarArray(varPtr) && !TclIsVarUndefined(varPtr)) {
+	if (leaveErrorMsg) {
+	    VarErrMsg(interp, varName, NULL, "set", isArray);
+	}
+	return NULL;
+    }
+
+    /*
+     * Set the variable's new value and discard its old value. We don't
+     * append with this "set" procedure so the old value isn't needed.
+     */
+
+    oldValuePtr = varPtr->value.objPtr;
+    if (newValuePtr != oldValuePtr) {        /* set new value */
+	varPtr->value.objPtr = newValuePtr;
+	Tcl_IncrRefCount(newValuePtr);       /* var is another ref to obj */
+	if (oldValuePtr != NULL) {
+	    TclDecrRefCount(oldValuePtr);    /* discard old value */
+	}
+    }
+    TclSetVarScalar(varPtr);
+    TclClearVarUndefined(varPtr);
+
+    /*
+     * Invoke any write traces for the variable.
+     */
+
+    if (varPtr->tracePtr != NULL) {
+	char *msg = CallTraces(iPtr, /*arrayPtr*/ NULL, varPtr,
+	        varName, (char *) NULL, TCL_TRACE_WRITES);
+	if (msg != NULL) {
+	    if (leaveErrorMsg) {
+		VarErrMsg(interp, varName, NULL, "set", msg);
+	    }
+	    goto cleanup;
+	}
+    }
+
+    /*
+     * Return the variable's value unless the variable was changed in some
+     * gross way by a trace (e.g. it was unset and then recreated as an
+     * array). If it was changed is a gross way, just return an empty string
+     * object.
+     */
+
+    if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)) {
+	return varPtr->value.objPtr;
+    }
+    
+    resultPtr = Tcl_NewObj();
+
+    /*
+     * If the variable doesn't exist anymore and no-one's using it, then
+     * free up the relevant structures and hash table entries.
+     */
+
+    cleanup:
+    if (TclIsVarUndefined(varPtr)) {
+	CleanupVar(varPtr, NULL);
+    }
+    return resultPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclSetElementOfIndexedArray --
+ *
+ *	Change the Tcl object value of an element in a local array
+ *	variable. The element is named by the object elemPtr while the array
+ *	is specified by its index in the active procedure's array of
+ *	compiler allocated local variables.
+ *
+ * Results:
+ *	Returns a pointer to the Tcl_Obj holding the new value of the
+ *	element. If the specified array or element doesn't exist, or there
+ *	is a clash in array usage, or an error occurs while executing
+ *	variable traces, then NULL is returned and a message will be left in
+ *	the interpreter's result if leaveErrorMsg is 1. Note that the
+ *	returned object may not be the same one referenced by newValuePtr;
+ *	this is because variable traces may modify the variable's value.
+ *
+ * Side effects:
+ *	The value of the given array element is set. The reference count is
+ *	decremented for any old value of the element and incremented for its
+ *	new value. If as a result of a variable trace the new value for the
+ *	element is not the same one referenced by newValuePtr, then
+ *	newValuePtr's ref count is left unchanged. The ref count for the
+ *	returned object is _not_ incremented to reflect the returned
+ *	reference; if you want to keep a reference to the object you must
+ *	increment its ref count yourself. This procedure will not create new
+ *	array variables, but only sets elements of those arrays recognized
+ *	at compile time. However, if the entry doesn't exist then a new
+ *	variable is created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclSetElementOfIndexedArray(interp, localIndex, elemPtr, newValuePtr,
+        leaveErrorMsg)
+    Tcl_Interp *interp;		/* Command interpreter in which the array is
+				 * to be found. */
+    int localIndex;		/* Index of array variable in procedure's
+				 * array of local variables. */
+    Tcl_Obj *elemPtr;		/* Points to an object holding the name of
+				 * an element to set in the array. */
+    Tcl_Obj *newValuePtr;	/* New value for variable. */
+    int leaveErrorMsg;		/* 1 if to leave an error message in
+				 * the interpreter's result on an error.
+				 * Otherwise no error message is left. */
+{
+    Interp *iPtr = (Interp *) interp;
+    CallFrame *varFramePtr = iPtr->varFramePtr;
+				/* Points to the procedure call frame whose
+				 * variables are currently in use. Same as
+				 * the current procedure's frame, if any,
+				 * unless an "uplevel" is executing. */
+    Var *compiledLocals = varFramePtr->compiledLocals;
+    Var *arrayPtr;		/* Points to the array's in-frame Var
+				 * structure. */
+    char *arrayName;		/* Name of the local array. */
+    char *elem;
+    Tcl_HashEntry *hPtr;
+    Var *varPtr = NULL;		/* Points to the element's Var structure
+				 * that we return. */
+    Tcl_Obj *resultPtr = NULL;
+    Tcl_Obj *oldValuePtr;
+    int new;
+    
+#ifdef TCL_COMPILE_DEBUG
+    Proc *procPtr = varFramePtr->procPtr;
+    int localCt = procPtr->numCompiledLocals;
+
+    if (compiledLocals == NULL) {
+	fprintf(stderr, "\nTclSetElementOfIndexedArray: can't set element of local %i in frame 0x%x, no compiled locals\n",
+		localIndex, (unsigned int) varFramePtr);
+	panic("TclSetIndexedScalar: no compiled locals in frame 0x%x",
+		(unsigned int) varFramePtr);
+    }
+    if ((localIndex < 0) || (localIndex >= localCt)) {
+	fprintf(stderr, "\nTclSetIndexedScalar: can't set elememt of local %i in frame 0x%x with %i locals\n",
+		localIndex, (unsigned int) varFramePtr, localCt);
+	panic("TclSetElementOfIndexedArray: bad local index %i in frame 0x%x",
+		localIndex, (unsigned int) varFramePtr);
+    }
+#endif /* TCL_COMPILE_DEBUG */
+
+    /*
+     * THIS FAILS IF THE ELEMENT NAME OBJECT'S STRING REP HAS A NULL BYTE.
+     */
+    
+    elem = Tcl_GetStringFromObj(elemPtr, (int *) NULL);
+    arrayPtr = &(compiledLocals[localIndex]);
+    arrayName = arrayPtr->name;
+
+    /*
+     * If arrayPtr is a link variable, we have a reference to some variable
+     * that was created through an "upvar" or "global" command, or we have a
+     * reference to a variable in an enclosing namespace. Traverse through
+     * any links until we find the referenced variable.
+     */
+	
+    while (TclIsVarLink(arrayPtr)) {
+	arrayPtr = arrayPtr->value.linkPtr;
+    }
+
+    /*
+     * If the variable is in a hashtable and its hPtr field is NULL, then we
+     * may have an upvar to an array element where the array was deleted
+     * or an upvar to a namespace variable whose namespace was deleted.
+     * Generate an error (allowing the variable to be reset would screw up
+     * our storage allocation and is meaningless anyway).
+     */
+
+    if ((arrayPtr->flags & VAR_IN_HASHTABLE) && (arrayPtr->hPtr == NULL)) {
+	if (leaveErrorMsg) {
+	    if (TclIsVarArrayElement(arrayPtr)) {
+		VarErrMsg(interp, arrayName, elem, "set", danglingElement);
+	    } else {
+		VarErrMsg(interp, arrayName, elem, "set", danglingVar);
+	    }
+	}
+	goto errorReturn;
+    }
+
+    /*
+     * Make sure we're dealing with an array.
+     */
+
+    if (TclIsVarUndefined(arrayPtr) && !TclIsVarArrayElement(arrayPtr)) {
+	TclSetVarArray(arrayPtr);
+	arrayPtr->value.tablePtr =
+	    (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
+	Tcl_InitHashTable(arrayPtr->value.tablePtr, TCL_STRING_KEYS);
+	TclClearVarUndefined(arrayPtr);
+    } else if (!TclIsVarArray(arrayPtr)) {
+	if (leaveErrorMsg) {
+	    VarErrMsg(interp, arrayName, elem, "set", needArray);
+	}
+	goto errorReturn;
+    } 
+
+    /*
+     * Look up the element.
+     */
+
+    hPtr = Tcl_CreateHashEntry(arrayPtr->value.tablePtr, elem, &new);
+    if (new) {
+	if (arrayPtr->searchPtr != NULL) {
+	    DeleteSearches(arrayPtr);
+	}
+	varPtr = NewVar();
+	Tcl_SetHashValue(hPtr, varPtr);
+	varPtr->hPtr = hPtr;
+        varPtr->nsPtr = varFramePtr->nsPtr;
+	TclSetVarArrayElement(varPtr);
+    }
+    varPtr = (Var *) Tcl_GetHashValue(hPtr);
+
+    /*
+     * It's an error to try to set an array variable itself.
+     */
+
+    if (TclIsVarArray(varPtr)) {
+	if (leaveErrorMsg) {
+	    VarErrMsg(interp, arrayName, elem, "set", isArray);
+	}
+	goto errorReturn;
+    }
+
+    /*
+     * Set the variable's new value and discard the old one. We don't
+     * append with this "set" procedure so the old value isn't needed.
+     */
+
+    oldValuePtr = varPtr->value.objPtr;
+    if (newValuePtr != oldValuePtr) {	     /* set new value */
+	varPtr->value.objPtr = newValuePtr;
+	Tcl_IncrRefCount(newValuePtr);       /* var is another ref to obj */
+	if (oldValuePtr != NULL) {
+	    TclDecrRefCount(oldValuePtr);    /* discard old value */
+	}
+    }
+    TclSetVarScalar(varPtr);
+    TclClearVarUndefined(varPtr);
+
+    /*
+     * Invoke any write traces for the element variable.
+     */
+
+    if ((varPtr->tracePtr != NULL)
+	    || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL))) {
+	char *msg = CallTraces(iPtr, arrayPtr, varPtr, arrayName, elem,
+		TCL_TRACE_WRITES);
+	if (msg != NULL) {
+	    if (leaveErrorMsg) {
+		VarErrMsg(interp, arrayName, elem, "set", msg);
+	    }
+	    goto errorReturn;
+	}
+    }
+
+    /*
+     * Return the element's value unless it was changed in some gross way by
+     * a trace (e.g. it was unset and then recreated as an array). If it was
+     * changed is a gross way, just return an empty string object.
+     */
+
+    if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)) {
+	return varPtr->value.objPtr;
+    }
+    
+    resultPtr = Tcl_NewObj();
+
+    /*
+     * An error. If the variable doesn't exist anymore and no-one's using
+     * it, then free up the relevant structures and hash table entries.
+     */
+
+    errorReturn:
+    if (varPtr != NULL) {
+	if (TclIsVarUndefined(varPtr)) {
+	    CleanupVar(varPtr, NULL); /* note: array isn't in hashtable */
+	}
+    }
+    return resultPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclIncrVar2 --
+ *
+ *	Given a two-part variable name, which may refer either to a scalar
+ *	variable or an element of an array, increment the Tcl object value
+ *	of the variable by a specified amount.
+ *
+ * Results:
+ *	Returns a pointer to the Tcl_Obj holding the new value of the
+ *	variable. If the specified variable doesn't exist, or there is a
+ *	clash in array usage, or an error occurs while executing variable
+ *	traces, then NULL is returned and a message will be left in
+ *	the interpreter's result.
+ *
+ * Side effects:
+ *	The value of the given variable is incremented by the specified
+ *	amount. If either the array or the entry didn't exist then a new
+ *	variable is created. The ref count for the returned object is _not_
+ *	incremented to reflect the returned reference; if you want to keep a
+ *	reference to the object you must increment its ref count yourself.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclIncrVar2(interp, part1Ptr, part2Ptr, incrAmount, part1NotParsed)
+    Tcl_Interp *interp;		/* Command interpreter in which variable is
+				 * to be found. */
+    Tcl_Obj *part1Ptr;		/* Points to an object holding the name of
+				 * an array (if part2 is non-NULL) or the
+				 * name of a variable. */
+    Tcl_Obj *part2Ptr;		/* If non-null, points to an object holding
+				 * the name of an element in the array
+				 * part1Ptr. */
+    long incrAmount;		/* Amount to be added to variable. */
+    int part1NotParsed;		/* 1 if part1 hasn't yet been parsed into
+				 * an array name and index (if any). */
+{
+    register Tcl_Obj *varValuePtr;
+    Tcl_Obj *resultPtr;
+    int createdNewObj;		/* Set 1 if var's value object is shared
+				 * so we must increment a copy (i.e. copy
+				 * on write). */
+    long i;
+    int flags, result;
+
+    flags = TCL_LEAVE_ERR_MSG;
+    if (part1NotParsed) {
+	flags |= TCL_PARSE_PART1;
+    }
+    
+    varValuePtr = Tcl_ObjGetVar2(interp, part1Ptr, part2Ptr, flags);
+    if (varValuePtr == NULL) {
+	Tcl_AddObjErrorInfo(interp,
+		"\n    (reading value of variable to increment)", -1);
+	return NULL;
+    }
+
+    /*
+     * Increment the variable's value. If the object is unshared we can
+     * modify it directly, otherwise we must create a new copy to modify:
+     * this is "copy on write". Then free the variable's old string
+     * representation, if any, since it will no longer be valid.
+     */
+
+    createdNewObj = 0;
+    if (Tcl_IsShared(varValuePtr)) {
+	varValuePtr = Tcl_DuplicateObj(varValuePtr);
+	createdNewObj = 1;
+    }
+    result = Tcl_GetLongFromObj(interp, varValuePtr, &i);
+    if (result != TCL_OK) {
+	if (createdNewObj) {
+	    Tcl_DecrRefCount(varValuePtr); /* free unneeded copy */
+	}
+	return NULL;
+    }
+    Tcl_SetLongObj(varValuePtr, (i + incrAmount));
+
+    /*
+     * Store the variable's new value and run any write traces.
+     */
+    
+    resultPtr = Tcl_ObjSetVar2(interp, part1Ptr, part2Ptr, varValuePtr,
+	    flags);
+    if (resultPtr == NULL) {
+	return NULL;
+    }
+    return resultPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclIncrIndexedScalar --
+ *
+ *	Increments the Tcl object value of a local scalar variable in the
+ *	active procedure, given its compile-time allocated index in the
+ *	procedure's array of local variables.
+ *
+ * Results:
+ *	Returns a pointer to the Tcl_Obj holding the new value of the
+ *	variable given by localIndex. If the specified variable doesn't
+ *	exist, or there is a clash in array usage, or an error occurs while
+ *	executing variable traces, then NULL is returned and a message will
+ *	be left in the interpreter's result. 
+ *
+ * Side effects:
+ *	The value of the given variable is incremented by the specified
+ *	amount. The ref count for the returned object is _not_ incremented
+ *	to reflect the returned reference; if you want to keep a reference
+ *	to the object you must increment its ref count yourself.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclIncrIndexedScalar(interp, localIndex, incrAmount)
+    Tcl_Interp *interp;		/* Command interpreter in which variable is
+				 * to be found. */
+    int localIndex;		/* Index of variable in procedure's array
+				 * of local variables. */
+    long incrAmount;		/* Amount to be added to variable. */
+{
+    register Tcl_Obj *varValuePtr;
+    Tcl_Obj *resultPtr;
+    int createdNewObj;		/* Set 1 if var's value object is shared
+				 * so we must increment a copy (i.e. copy
+				 * on write). */
+    long i;
+    int result;
+
+    varValuePtr = TclGetIndexedScalar(interp, localIndex,
+	    /*leaveErrorMsg*/ 1);
+    if (varValuePtr == NULL) {
+	Tcl_AddObjErrorInfo(interp,
+		"\n    (reading value of variable to increment)", -1);
+	return NULL;
+    }
+
+    /*
+     * Reach into the object's representation to extract and increment the
+     * variable's value. If the object is unshared we can modify it
+     * directly, otherwise we must create a new copy to modify: this is
+     * "copy on write". Then free the variable's old string representation,
+     * if any, since it will no longer be valid.
+     */
+
+    createdNewObj = 0;
+    if (Tcl_IsShared(varValuePtr)) {
+	createdNewObj = 1;
+	varValuePtr = Tcl_DuplicateObj(varValuePtr);
+    }
+    result = Tcl_GetLongFromObj(interp, varValuePtr, &i);
+    if (result != TCL_OK) {
+	if (createdNewObj) {
+	    Tcl_DecrRefCount(varValuePtr); /* free unneeded copy */
+	}
+	return NULL;
+    }
+    Tcl_SetLongObj(varValuePtr, (i + incrAmount));
+
+    /*
+     * Store the variable's new value and run any write traces.
+     */
+    
+    resultPtr = TclSetIndexedScalar(interp, localIndex, varValuePtr,
+	    /*leaveErrorMsg*/ 1);
+    if (resultPtr == NULL) {
+	return NULL;
+    }
+    return resultPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclIncrElementOfIndexedArray --
+ *
+ *	Increments the Tcl object value of an element in a local array
+ *	variable. The element is named by the object elemPtr while the array
+ *	is specified by its index in the active procedure's array of
+ *	compiler allocated local variables.
+ *
+ * Results:
+ *	Returns a pointer to the Tcl_Obj holding the new value of the
+ *	element. If the specified array or element doesn't exist, or there
+ *	is a clash in array usage, or an error occurs while executing
+ *	variable traces, then NULL is returned and a message will be left in
+ *	the interpreter's result.
+ *
+ * Side effects:
+ *	The value of the given array element is incremented by the specified
+ *	amount. The ref count for the returned object is _not_ incremented
+ *	to reflect the returned reference; if you want to keep a reference
+ *	to the object you must increment its ref count yourself. If the
+ *	entry doesn't exist then a new variable is created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclIncrElementOfIndexedArray(interp, localIndex, elemPtr, incrAmount)
+    Tcl_Interp *interp;		/* Command interpreter in which the array is
+				 * to be found. */
+    int localIndex;		/* Index of array variable in procedure's
+				 * array of local variables. */
+    Tcl_Obj *elemPtr;		/* Points to an object holding the name of
+				 * an element to increment in the array. */
+    long incrAmount;		/* Amount to be added to variable. */
+{
+    register Tcl_Obj *varValuePtr;
+    Tcl_Obj *resultPtr;
+    int createdNewObj;		/* Set 1 if var's value object is shared
+				 * so we must increment a copy (i.e. copy
+				 * on write). */
+    long i;
+    int result;
+
+    varValuePtr = TclGetElementOfIndexedArray(interp, localIndex, elemPtr,
+	    /*leaveErrorMsg*/ 1);
+    if (varValuePtr == NULL) {
+	Tcl_AddObjErrorInfo(interp,
+		"\n    (reading value of variable to increment)", -1);
+	return NULL;
+    }
+
+    /*
+     * Reach into the object's representation to extract and increment the
+     * variable's value. If the object is unshared we can modify it
+     * directly, otherwise we must create a new copy to modify: this is
+     * "copy on write". Then free the variable's old string representation,
+     * if any, since it will no longer be valid.
+     */
+
+    createdNewObj = 0;
+    if (Tcl_IsShared(varValuePtr)) {
+	createdNewObj = 1;
+	varValuePtr = Tcl_DuplicateObj(varValuePtr);
+    }
+    result = Tcl_GetLongFromObj(interp, varValuePtr, &i);
+    if (result != TCL_OK) {
+	if (createdNewObj) {
+	    Tcl_DecrRefCount(varValuePtr); /* free unneeded copy */
+	}
+	return NULL;
+    }
+    Tcl_SetLongObj(varValuePtr, (i + incrAmount));
+    
+    /*
+     * Store the variable's new value and run any write traces.
+     */
+    
+    resultPtr = TclSetElementOfIndexedArray(interp, localIndex, elemPtr,
+	    varValuePtr,
+	    /*leaveErrorMsg*/ 1);
+    if (resultPtr == NULL) {
+	return NULL;
+    }
+    return resultPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_UnsetVar --
+ *
+ *	Delete a variable, so that it may not be accessed anymore.
+ *
+ * Results:
+ *	Returns TCL_OK if the variable was successfully deleted, TCL_ERROR
+ *	if the variable can't be unset.  In the event of an error,
+ *	if the TCL_LEAVE_ERR_MSG flag is set then an error message
+ *	is left in interp->result.
+ *
+ * Side effects:
+ *	If varName is defined as a local or global variable in interp,
+ *	it is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_UnsetVar(interp, varName, flags)
+    Tcl_Interp *interp;		/* Command interpreter in which varName is
+				 * to be looked up. */
+    char *varName;		/* Name of a variable in interp.  May be
+				 * either a scalar name or an array name
+				 * or an element in an array. */
+    int flags;			/* OR-ed combination of any of
+				 * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY or
+				 * TCL_LEAVE_ERR_MSG. */
+{
+    return Tcl_UnsetVar2(interp, varName, (char *) NULL,
+	    (flags | TCL_PARSE_PART1));
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_UnsetVar2 --
+ *
+ *	Delete a variable, given a 2-part name.
+ *
+ * Results:
+ *	Returns TCL_OK if the variable was successfully deleted, TCL_ERROR
+ *	if the variable can't be unset.  In the event of an error,
+ *	if the TCL_LEAVE_ERR_MSG flag is set then an error message
+ *	is left in interp->result.
+ *
+ * Side effects:
+ *	If part1 and part2 indicate a local or global variable in interp,
+ *	it is deleted.  If part1 is an array name and part2 is NULL, then
+ *	the whole array is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_UnsetVar2(interp, part1, part2, flags)
+    Tcl_Interp *interp;		/* Command interpreter in which varName is
+				 * to be looked up. */
+    char *part1;		/* Name of variable or array. */
+    char *part2;		/* Name of element within array or NULL. */
+    int flags;			/* OR-ed combination of any of
+				 * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
+				 * TCL_LEAVE_ERR_MSG, or
+				 * TCL_PARSE_PART1. */
+{
+    Var dummyVar;
+    Var *varPtr, *dummyVarPtr;
+    Interp *iPtr = (Interp *) interp;
+    Var *arrayPtr;
+    ActiveVarTrace *activePtr;
+    Tcl_Obj *objPtr;
+    int result;
+
+    varPtr = TclLookupVar(interp, part1, part2, flags, "unset",
+	    /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
+    if (varPtr == NULL) {
+	return TCL_ERROR;
+    }
+    result = (TclIsVarUndefined(varPtr)? TCL_ERROR : TCL_OK);
+
+    if ((arrayPtr != NULL) && (arrayPtr->searchPtr != NULL)) {
+	DeleteSearches(arrayPtr);
+    }
+
+    /*
+     * The code below is tricky, because of the possibility that
+     * a trace procedure might try to access a variable being
+     * deleted. To handle this situation gracefully, do things
+     * in three steps:
+     * 1. Copy the contents of the variable to a dummy variable
+     *    structure, and mark the original Var structure as undefined.
+     * 2. Invoke traces and clean up the variable, using the dummy copy.
+     * 3. If at the end of this the original variable is still
+     *    undefined and has no outstanding references, then delete
+     *	  it (but it could have gotten recreated by a trace).
+     */
+
+    dummyVar = *varPtr;
+    TclSetVarUndefined(varPtr);
+    TclSetVarScalar(varPtr);
+    varPtr->value.objPtr = NULL; /* dummyVar points to any value object */
+    varPtr->tracePtr = NULL;
+    varPtr->searchPtr = NULL;
+
+    /*
+     * Call trace procedures for the variable being deleted. Then delete
+     * its traces. Be sure to abort any other traces for the variable
+     * that are still pending. Special tricks:
+     * 1. We need to increment varPtr's refCount around this: CallTraces
+     *    will use dummyVar so it won't increment varPtr's refCount itself.
+     * 2. Turn off the VAR_TRACE_ACTIVE flag in dummyVar: we want to
+     *    call unset traces even if other traces are pending.
+     */
+
+    if ((dummyVar.tracePtr != NULL)
+	    || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL))) {
+	varPtr->refCount++;
+	dummyVar.flags &= ~VAR_TRACE_ACTIVE;
+	(void) CallTraces(iPtr, arrayPtr, &dummyVar, part1, part2,
+		(flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_PARSE_PART1)) | TCL_TRACE_UNSETS);
+	while (dummyVar.tracePtr != NULL) {
+	    VarTrace *tracePtr = dummyVar.tracePtr;
+	    dummyVar.tracePtr = tracePtr->nextPtr;
+	    ckfree((char *) tracePtr);
+	}
+	for (activePtr = iPtr->activeTracePtr;  activePtr != NULL;
+	     activePtr = activePtr->nextPtr) {
+	    if (activePtr->varPtr == varPtr) {
+		activePtr->nextTracePtr = NULL;
+	    }
+	}
+	varPtr->refCount--;
+    }
+
+    /*
+     * If the variable is an array, delete all of its elements. This must be
+     * done after calling the traces on the array, above (that's the way
+     * traces are defined). If it is a scalar, "discard" its object
+     * (decrement the ref count of its object, if any).
+     */
+
+    dummyVarPtr = &dummyVar;
+    if (TclIsVarArray(dummyVarPtr) && !TclIsVarUndefined(dummyVarPtr)) {
+	DeleteArray(iPtr, part1, dummyVarPtr,
+		(flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY)) | TCL_TRACE_UNSETS);
+    }
+    if (TclIsVarScalar(dummyVarPtr)
+	    && (dummyVarPtr->value.objPtr != NULL)) {
+	objPtr = dummyVarPtr->value.objPtr;
+	TclDecrRefCount(objPtr);
+	dummyVarPtr->value.objPtr = NULL;
+    }
+
+    /*
+     * If the variable was a namespace variable, decrement its reference count.
+     */
+    
+    if (varPtr->flags & VAR_NAMESPACE_VAR) {
+	varPtr->flags &= ~VAR_NAMESPACE_VAR;
+	varPtr->refCount--;
+    }
+
+    /*
+     * It's an error to unset an undefined variable.
+     */
+	
+    if (result != TCL_OK) {
+	if (flags & TCL_LEAVE_ERR_MSG) {
+	    VarErrMsg(interp, part1, part2, "unset", 
+		    ((arrayPtr == NULL) ? noSuchVar : noSuchElement));
+	}
+    }
+
+    /*
+     * Finally, if the variable is truly not in use then free up its Var
+     * structure and remove it from its hash table, if any. The ref count of
+     * its value object, if any, was decremented above.
+     */
+
+    CleanupVar(varPtr, arrayPtr);
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_TraceVar --
+ *
+ *	Arrange for reads and/or writes to a variable to cause a
+ *	procedure to be invoked, which can monitor the operations
+ *	and/or change their actions.
+ *
+ * Results:
+ *	A standard Tcl return value.
+ *
+ * Side effects:
+ *	A trace is set up on the variable given by varName, such that
+ *	future references to the variable will be intermediated by
+ *	proc.  See the manual entry for complete details on the calling
+ *	sequence for proc.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_TraceVar(interp, varName, flags, proc, clientData)
+    Tcl_Interp *interp;		/* Interpreter in which variable is
+				 * to be traced. */
+    char *varName;		/* Name of variable;  may end with "(index)"
+				 * to signify an array reference. */
+    int flags;			/* OR-ed collection of bits, including any
+				 * of TCL_TRACE_READS, TCL_TRACE_WRITES,
+				 * TCL_TRACE_UNSETS, TCL_GLOBAL_ONLY, and
+				 * TCL_NAMESPACE_ONLY. */
+    Tcl_VarTraceProc *proc;	/* Procedure to call when specified ops are
+				 * invoked upon varName. */
+    ClientData clientData;	/* Arbitrary argument to pass to proc. */
+{
+    return Tcl_TraceVar2(interp, varName, (char *) NULL,
+	    (flags | TCL_PARSE_PART1), proc, clientData);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_TraceVar2 --
+ *
+ *	Arrange for reads and/or writes to a variable to cause a
+ *	procedure to be invoked, which can monitor the operations
+ *	and/or change their actions.
+ *
+ * Results:
+ *	A standard Tcl return value.
+ *
+ * Side effects:
+ *	A trace is set up on the variable given by part1 and part2, such
+ *	that future references to the variable will be intermediated by
+ *	proc.  See the manual entry for complete details on the calling
+ *	sequence for proc.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_TraceVar2(interp, part1, part2, flags, proc, clientData)
+    Tcl_Interp *interp;		/* Interpreter in which variable is
+				 * to be traced. */
+    char *part1;		/* Name of scalar variable or array. */
+    char *part2;		/* Name of element within array;  NULL means
+				 * trace applies to scalar variable or array
+				 * as-a-whole. */
+    int flags;			/* OR-ed collection of bits, including any
+				 * of TCL_TRACE_READS, TCL_TRACE_WRITES,
+				 * TCL_TRACE_UNSETS, TCL_GLOBAL_ONLY,
+				 * TCL_NAMESPACE_ONLY and
+				 * TCL_PARSE_PART1. */
+    Tcl_VarTraceProc *proc;	/* Procedure to call when specified ops are
+				 * invoked upon varName. */
+    ClientData clientData;	/* Arbitrary argument to pass to proc. */
+{
+    Var *varPtr, *arrayPtr;
+    register VarTrace *tracePtr;
+
+    varPtr = TclLookupVar(interp, part1, part2, (flags | TCL_LEAVE_ERR_MSG),
+	    "trace", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
+    if (varPtr == NULL) {
+	return TCL_ERROR;
+    }
+
+    /*
+     * Set up trace information.
+     */
+
+    tracePtr = (VarTrace *) ckalloc(sizeof(VarTrace));
+    tracePtr->traceProc = proc;
+    tracePtr->clientData = clientData;
+    tracePtr->flags = 
+	flags & (TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS);
+    tracePtr->nextPtr = varPtr->tracePtr;
+    varPtr->tracePtr = tracePtr;
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_UntraceVar --
+ *
+ *	Remove a previously-created trace for a variable.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	If there exists a trace for the variable given by varName
+ *	with the given flags, proc, and clientData, then that trace
+ *	is removed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_UntraceVar(interp, varName, flags, proc, clientData)
+    Tcl_Interp *interp;		/* Interpreter containing variable. */
+    char *varName;		/* Name of variable; may end with "(index)"
+				 * to signify an array reference. */
+    int flags;			/* OR-ed collection of bits describing
+				 * current trace, including any of
+				 * TCL_TRACE_READS, TCL_TRACE_WRITES,
+				 * TCL_TRACE_UNSETS, TCL_GLOBAL_ONLY
+				 * and TCL_NAMESPACE_ONLY. */
+    Tcl_VarTraceProc *proc;	/* Procedure assocated with trace. */
+    ClientData clientData;	/* Arbitrary argument to pass to proc. */
+{
+    Tcl_UntraceVar2(interp, varName, (char *) NULL,
+	    (flags | TCL_PARSE_PART1), proc, clientData);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_UntraceVar2 --
+ *
+ *	Remove a previously-created trace for a variable.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	If there exists a trace for the variable given by part1
+ *	and part2 with the given flags, proc, and clientData, then
+ *	that trace is removed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_UntraceVar2(interp, part1, part2, flags, proc, clientData)
+    Tcl_Interp *interp;		/* Interpreter containing variable. */
+    char *part1;		/* Name of variable or array. */
+    char *part2;		/* Name of element within array;  NULL means
+				 * trace applies to scalar variable or array
+				 * as-a-whole. */
+    int flags;			/* OR-ed collection of bits describing
+				 * current trace, including any of
+				 * TCL_TRACE_READS, TCL_TRACE_WRITES,
+				 * TCL_TRACE_UNSETS, TCL_GLOBAL_ONLY,
+				 * TCL_NAMESPACE_ONLY and
+				 * TCL_PARSE_PART1. */
+    Tcl_VarTraceProc *proc;	/* Procedure assocated with trace. */
+    ClientData clientData;	/* Arbitrary argument to pass to proc. */
+{
+    register VarTrace *tracePtr;
+    VarTrace *prevPtr;
+    Var *varPtr, *arrayPtr;
+    Interp *iPtr = (Interp *) interp;
+    ActiveVarTrace *activePtr;
+
+    varPtr = TclLookupVar(interp, part1, part2,
+	    flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_PARSE_PART1),
+	    /*msg*/ (char *) NULL,
+	    /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
+    if (varPtr == NULL) {
+	return;
+    }
+
+    flags &= (TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS);
+    for (tracePtr = varPtr->tracePtr, prevPtr = NULL;  ;
+	 prevPtr = tracePtr, tracePtr = tracePtr->nextPtr) {
+	if (tracePtr == NULL) {
+	    return;
+	}
+	if ((tracePtr->traceProc == proc) && (tracePtr->flags == flags)
+		&& (tracePtr->clientData == clientData)) {
+	    break;
+	}
+    }
+
+    /*
+     * The code below makes it possible to delete traces while traces
+     * are active: it makes sure that the deleted trace won't be
+     * processed by CallTraces.
+     */
+
+    for (activePtr = iPtr->activeTracePtr;  activePtr != NULL;
+	 activePtr = activePtr->nextPtr) {
+	if (activePtr->nextTracePtr == tracePtr) {
+	    activePtr->nextTracePtr = tracePtr->nextPtr;
+	}
+    }
+    if (prevPtr == NULL) {
+	varPtr->tracePtr = tracePtr->nextPtr;
+    } else {
+	prevPtr->nextPtr = tracePtr->nextPtr;
+    }
+    ckfree((char *) tracePtr);
+
+    /*
+     * If this is the last trace on the variable, and the variable is
+     * unset and unused, then free up the variable.
+     */
+
+    if (TclIsVarUndefined(varPtr)) {
+	CleanupVar(varPtr, (Var *) NULL);
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_VarTraceInfo --
+ *
+ *	Return the clientData value associated with a trace on a
+ *	variable.  This procedure can also be used to step through
+ *	all of the traces on a particular variable that have the
+ *	same trace procedure.
+ *
+ * Results:
+ *	The return value is the clientData value associated with
+ *	a trace on the given variable.  Information will only be
+ *	returned for a trace with proc as trace procedure.  If
+ *	the clientData argument is NULL then the first such trace is
+ *	returned;  otherwise, the next relevant one after the one
+ *	given by clientData will be returned.  If the variable
+ *	doesn't exist, or if there are no (more) traces for it,
+ *	then NULL is returned.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ClientData
+Tcl_VarTraceInfo(interp, varName, flags, proc, prevClientData)
+    Tcl_Interp *interp;		/* Interpreter containing variable. */
+    char *varName;		/* Name of variable;  may end with "(index)"
+				 * to signify an array reference. */
+    int flags;			/* 0, TCL_GLOBAL_ONLY, or
+				 * TCL_NAMESPACE_ONLY. */
+    Tcl_VarTraceProc *proc;	/* Procedure assocated with trace. */
+    ClientData prevClientData;	/* If non-NULL, gives last value returned
+				 * by this procedure, so this call will
+				 * return the next trace after that one.
+				 * If NULL, this call will return the
+				 * first trace. */
+{
+    return Tcl_VarTraceInfo2(interp, varName, (char *) NULL,
+	    (flags | TCL_PARSE_PART1), proc, prevClientData);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_VarTraceInfo2 --
+ *
+ *	Same as Tcl_VarTraceInfo, except takes name in two pieces
+ *	instead of one.
+ *
+ * Results:
+ *	Same as Tcl_VarTraceInfo.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ClientData
+Tcl_VarTraceInfo2(interp, part1, part2, flags, proc, prevClientData)
+    Tcl_Interp *interp;		/* Interpreter containing variable. */
+    char *part1;		/* Name of variable or array. */
+    char *part2;		/* Name of element within array;  NULL means
+				 * trace applies to scalar variable or array
+				 * as-a-whole. */
+    int flags;			/* OR-ed combination of TCL_GLOBAL_ONLY,
+				 * TCL_NAMESPACE_ONLY, and
+				 * TCL_PARSE_PART1. */
+    Tcl_VarTraceProc *proc;	/* Procedure assocated with trace. */
+    ClientData prevClientData;	/* If non-NULL, gives last value returned
+				 * by this procedure, so this call will
+				 * return the next trace after that one.
+				 * If NULL, this call will return the
+				 * first trace. */
+{
+    register VarTrace *tracePtr;
+    Var *varPtr, *arrayPtr;
+
+    varPtr = TclLookupVar(interp, part1, part2,
+	    flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_PARSE_PART1),
+	    /*msg*/ (char *) NULL,
+	    /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
+    if (varPtr == NULL) {
+	return NULL;
+    }
+
+    /*
+     * Find the relevant trace, if any, and return its clientData.
+     */
+
+    tracePtr = varPtr->tracePtr;
+    if (prevClientData != NULL) {
+	for ( ;  tracePtr != NULL;  tracePtr = tracePtr->nextPtr) {
+	    if ((tracePtr->clientData == prevClientData)
+		    && (tracePtr->traceProc == proc)) {
+		tracePtr = tracePtr->nextPtr;
+		break;
+	    }
+	}
+    }
+    for ( ;  tracePtr != NULL;  tracePtr = tracePtr->nextPtr) {
+	if (tracePtr->traceProc == proc) {
+	    return tracePtr->clientData;
+	}
+    }
+    return NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_UnsetObjCmd --
+ *
+ *	This object-based procedure is invoked to process the "unset" Tcl
+ *	command. See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result value.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_UnsetObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    register int i;
+    register char *name;
+
+    if (objc < 2) {
+	Tcl_WrongNumArgs(interp, 1, objv, "varName ?varName ...?");
+	return TCL_ERROR;
+    }
+    
+    for (i = 1;  i < objc;  i++) {
+	/*
+	 * THIS FAILS IF A NAME OBJECT'S STRING REP HAS A NULL BYTE.
+	 */
+
+	name = Tcl_GetStringFromObj(objv[i], (int *) NULL);
+	if (Tcl_UnsetVar2(interp, name, (char *) NULL,
+	        (TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1)) != TCL_OK) {
+	    return TCL_ERROR;
+	}
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AppendObjCmd --
+ *
+ *	This object-based procedure is invoked to process the "append" 
+ *	Tcl command. See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result value.
+ *
+ * Side effects:
+ *	A variable's value may be changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_AppendObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    register Tcl_Obj *varValuePtr = NULL;
+    /* Initialized to avoid compiler
+     * warning. */
+    int i;
+
+    if (objc < 2) {
+	Tcl_WrongNumArgs(interp, 1, objv, "varName ?value value ...?");
+	return TCL_ERROR;
+    }
+
+    if (objc == 2) {
+	varValuePtr = Tcl_ObjGetVar2(interp, objv[1], (Tcl_Obj *) NULL,
+	        (TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1));
+	if (varValuePtr == NULL) {
+	    return TCL_ERROR;
+	}
+    } else {
+	for (i = 2;  i < objc;  i++) {
+	    varValuePtr = Tcl_ObjSetVar2(interp, objv[1], (Tcl_Obj *) NULL,
+		    objv[i],
+		    (TCL_APPEND_VALUE | TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1));
+	    if (varValuePtr == NULL) {
+		return TCL_ERROR;
+	    }
+	}
+    }
+    
+    Tcl_SetObjResult(interp, varValuePtr);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LappendObjCmd --
+ *
+ *	This object-based procedure is invoked to process the "lappend" 
+ *	Tcl command. See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result value.
+ *
+ * Side effects:
+ *	A variable's value may be changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_LappendObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Tcl_Obj *varValuePtr, *newValuePtr;
+    register List *listRepPtr;
+    register Tcl_Obj **elemPtrs;
+    int numElems, numRequired, createdNewObj, createVar, i, j;
+
+    if (objc < 2) {
+	Tcl_WrongNumArgs(interp, 1, objv, "varName ?value value ...?");
+	return TCL_ERROR;
+    }
+    
+    if (objc == 2) {
+	newValuePtr = Tcl_ObjGetVar2(interp, objv[1], (Tcl_Obj *) NULL,
+		(TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1));
+	if (newValuePtr == NULL) {
+	    /*
+	     * The variable doesn't exist yet. Just create it with an empty
+	     * initial value.
+	     */
+	    
+	    Tcl_Obj *nullObjPtr = Tcl_NewObj();
+	    newValuePtr = Tcl_ObjSetVar2(interp, objv[1], NULL,
+		    nullObjPtr, (TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1));
+	    if (newValuePtr == NULL) {
+		Tcl_DecrRefCount(nullObjPtr); /* free unneeded object */
+		return TCL_ERROR;
+	    }
+	}
+    } else {
+	/*
+	 * We have arguments to append. We used to call Tcl_ObjSetVar2 to
+	 * append each argument one at a time to ensure that traces were run
+	 * for each append step. We now append the arguments all at once
+	 * because it's faster. Note that a read trace and a write trace for
+	 * the variable will now each only be called once. Also, if the
+	 * variable's old value is unshared we modify it directly, otherwise
+	 * we create a new copy to modify: this is "copy on write".
+	 */
+
+	createdNewObj = 0;
+	createVar = 1;
+	varValuePtr = Tcl_ObjGetVar2(interp, objv[1], (Tcl_Obj *) NULL,
+	        TCL_PARSE_PART1);
+	if (varValuePtr == NULL) {
+	    /*
+	     * We couldn't read the old value: either the var doesn't yet
+	     * exist or it's an array element. If it's new, we will try to
+	     * create it with Tcl_ObjSetVar2 below.
+	     */
+	    
+	    char *name, *p;
+	    int nameBytes, i;
+
+	    name = TclGetStringFromObj(objv[1], &nameBytes);
+	    for (i = 0, p = name;  i < nameBytes;  i++, p++) {
+		if (*p == '(') {
+		    p = (name + nameBytes-1);	
+		    if (*p == ')') { /* last char is ')' => array ref */
+			createVar = 0;
+		    }
+		    break;
+		}
+	    }
+	    varValuePtr = Tcl_NewObj();
+	    createdNewObj = 1;
+	} else if (Tcl_IsShared(varValuePtr)) {	
+	    varValuePtr = Tcl_DuplicateObj(varValuePtr);
+	    createdNewObj = 1;
+	}
+
+	/*
+	 * Convert the variable's old value to a list object if necessary.
+	 */
+
+	if (varValuePtr->typePtr != &tclListType) {
+	    int result = tclListType.setFromAnyProc(interp, varValuePtr);
+	    if (result != TCL_OK) {
+		if (createdNewObj) {
+		    Tcl_DecrRefCount(varValuePtr); /* free unneeded obj. */
+		}
+		return result;
+	    }
+	}
+	listRepPtr = (List *) varValuePtr->internalRep.otherValuePtr;
+	elemPtrs = listRepPtr->elements;
+	numElems = listRepPtr->elemCount;
+
+	/*
+	 * If there is no room in the current array of element pointers,
+	 * allocate a new, larger array and copy the pointers to it.
+	 */
+	
+	numRequired = numElems + (objc-2);
+	if (numRequired > listRepPtr->maxElemCount) {
+	    int newMax = (2 * numRequired);
+	    Tcl_Obj **newElemPtrs = (Tcl_Obj **)
+		ckalloc((unsigned) (newMax * sizeof(Tcl_Obj *)));
+	    
+	    memcpy((VOID *) newElemPtrs, (VOID *) elemPtrs,
+		    (size_t) (numElems * sizeof(Tcl_Obj *)));
+	    listRepPtr->maxElemCount = newMax;
+	    listRepPtr->elements = newElemPtrs;
+	    ckfree((char *) elemPtrs);
+	    elemPtrs = newElemPtrs;
+	}
+
+	/*
+	 * Insert the new elements at the end of the list.
+	 */
+
+	for (i = 2, j = numElems;  i < objc;  i++, j++) {
+            elemPtrs[j] = objv[i];
+            Tcl_IncrRefCount(objv[i]);
+        }
+	listRepPtr->elemCount = numRequired;
+
+	/*
+	 * Invalidate and free any old string representation since it no
+	 * longer reflects the list's internal representation.
+	 */
+
+	Tcl_InvalidateStringRep(varValuePtr);
+
+	/*
+	 * Now store the list object back into the variable. If there is an
+	 * error setting the new value, decrement its ref count if it
+	 * was new and we didn't create the variable.
+	 */
+	
+	newValuePtr = Tcl_ObjSetVar2(interp, objv[1], (Tcl_Obj *) NULL,
+		varValuePtr, (TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1));
+	if (newValuePtr == NULL) {
+	    if (createdNewObj && !createVar) {
+		Tcl_DecrRefCount(varValuePtr); /* free unneeded obj */
+	    }
+	    return TCL_ERROR;
+	}
+    }
+
+    /*
+     * Set the interpreter's object result to refer to the variable's value
+     * object.
+     */
+
+    Tcl_SetObjResult(interp, newValuePtr);
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ArrayObjCmd --
+ *
+ *	This object-based procedure is invoked to process the "array" Tcl
+ *	command. See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl result object.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_ArrayObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    /*
+     * The list of constants below should match the arrayOptions string array
+     * below.
+     */
+
+    enum {ARRAY_ANYMORE, ARRAY_DONESEARCH,  ARRAY_EXISTS, ARRAY_GET,
+	  ARRAY_NAMES, ARRAY_NEXTELEMENT, ARRAY_SET, ARRAY_SIZE,
+	  ARRAY_STARTSEARCH}; 
+    static char *arrayOptions[] = {"anymore", "donesearch", "exists",
+				   "get", "names", "nextelement", "set", "size", "startsearch", 
+				   (char *) NULL};
+
+    Var *varPtr, *arrayPtr;
+    Tcl_HashEntry *hPtr;
+    Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
+    int notArray;
+    char *varName;
+    int index, result;
+
+
+    if (objc < 3) {
+	Tcl_WrongNumArgs(interp, 1, objv, "option arrayName ?arg ...?");
+	return TCL_ERROR;
+    }
+
+    if (Tcl_GetIndexFromObj(interp, objv[1], arrayOptions, "option", 0, &index)
+	    != TCL_OK) {
+    	return TCL_ERROR;
+    }
+
+    /*
+     * Locate the array variable (and it better be an array).
+     * THIS FAILS IF A NAME OBJECT'S STRING REP HAS A NULL BYTE.
+     */
+    
+    varName = TclGetStringFromObj(objv[2], (int *) NULL);
+    varPtr = TclLookupVar(interp, varName, (char *) NULL, /*flags*/ 0,
+            /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
+
+    notArray = 0;
+    if ((varPtr == NULL) || !TclIsVarArray(varPtr)
+	    || TclIsVarUndefined(varPtr)) {
+	notArray = 1;
+    }
+    
+    switch (index) {
+        case ARRAY_ANYMORE: {
+	    ArraySearch *searchPtr;
+	    char *searchId;
+	    
+	    if (objc != 4) {
+	        Tcl_WrongNumArgs(interp, 2, objv, 
+                        "arrayName searchId");
+		return TCL_ERROR;
+	    }
+	    if (notArray) {
+	        goto error;
+	    }
+	    searchId = Tcl_GetStringFromObj(objv[3], (int *) NULL);
+	    searchPtr = ParseSearchId(interp, varPtr, varName, searchId);
+	    if (searchPtr == NULL) {
+	        return TCL_ERROR;
+	    }
+	    while (1) {
+	        Var *varPtr2;
+
+		if (searchPtr->nextEntry != NULL) {
+		    varPtr2 = (Var *) Tcl_GetHashValue(searchPtr->nextEntry);
+		    if (!TclIsVarUndefined(varPtr2)) {
+		        break;
+		    }
+		}
+		searchPtr->nextEntry = Tcl_NextHashEntry(&searchPtr->search);
+		if (searchPtr->nextEntry == NULL) {
+		    Tcl_SetIntObj(resultPtr, 0);
+		    return TCL_OK;
+		}
+	    }
+	    Tcl_SetIntObj(resultPtr, 1);
+	    break;
+	}
+        case ARRAY_DONESEARCH: {
+	    ArraySearch *searchPtr, *prevPtr;
+	    char *searchId;
+
+	    if (objc != 4) {
+	        Tcl_WrongNumArgs(interp, 2, objv, 
+                        "arrayName searchId");
+		return TCL_ERROR;
+	    }
+	    if (notArray) {
+	        goto error;
+	    }
+	    searchId = Tcl_GetStringFromObj(objv[3], (int *) NULL);
+	    searchPtr = ParseSearchId(interp, varPtr, varName, searchId);
+	    if (searchPtr == NULL) {
+	        return TCL_ERROR;
+	    }
+	    if (varPtr->searchPtr == searchPtr) {
+	        varPtr->searchPtr = searchPtr->nextPtr;
+	    } else {
+	        for (prevPtr = varPtr->searchPtr;  ;
+		     prevPtr = prevPtr->nextPtr) {
+		    if (prevPtr->nextPtr == searchPtr) {
+		        prevPtr->nextPtr = searchPtr->nextPtr;
+			break;
+		    }
+		}
+	    }
+	    ckfree((char *) searchPtr);
+	    break;
+	}
+        case ARRAY_EXISTS: {
+	    if (objc != 3) {
+	        Tcl_WrongNumArgs(interp, 2, objv, "arrayName");
+	        return TCL_ERROR;
+	    }
+	    Tcl_SetIntObj(resultPtr, !notArray);
+	    break;
+	}
+        case ARRAY_GET: {
+	    Tcl_HashSearch search;
+	    Var *varPtr2;
+	    char *pattern = NULL;
+	    char *name;
+	    Tcl_Obj *namePtr, *valuePtr;
+	    
+	    if ((objc != 3) && (objc != 4)) {
+	        Tcl_WrongNumArgs(interp, 2, objv, "arrayName ?pattern?");
+		return TCL_ERROR;
+	    }
+	    if (notArray) {
+	        return TCL_OK;
+	    }
+	    if (objc == 4) {
+	        pattern = Tcl_GetStringFromObj(objv[3], (int *) NULL);
+	    }
+	    for (hPtr = Tcl_FirstHashEntry(varPtr->value.tablePtr, &search);
+		 hPtr != NULL;  hPtr = Tcl_NextHashEntry(&search)) {
+	        varPtr2 = (Var *) Tcl_GetHashValue(hPtr);
+		if (TclIsVarUndefined(varPtr2)) {
+		    continue;
+		}
+		name = Tcl_GetHashKey(varPtr->value.tablePtr, hPtr);
+		if ((objc == 4) && !Tcl_StringMatch(name, pattern)) {
+		    continue;	/* element name doesn't match pattern */
+		}
+		
+		namePtr = Tcl_NewStringObj(name, -1);
+		result = Tcl_ListObjAppendElement(interp, resultPtr,
+		        namePtr);
+		if (result != TCL_OK) {
+		    Tcl_DecrRefCount(namePtr); /* free unneeded name obj */
+		    return result;
+		}
+
+		valuePtr = Tcl_ObjGetVar2(interp, objv[2], namePtr,
+	                TCL_LEAVE_ERR_MSG);
+		if (valuePtr == NULL) {
+		    Tcl_DecrRefCount(namePtr); /* free unneeded name obj */
+		    return result;
+		}
+		result = Tcl_ListObjAppendElement(interp, resultPtr,
+			valuePtr);
+		if (result != TCL_OK) {
+		    Tcl_DecrRefCount(namePtr); /* free unneeded name obj */
+		    return result;
+		}
+	    }
+	    break;
+	}
+        case ARRAY_NAMES: {
+	    Tcl_HashSearch search;
+	    Var *varPtr2;
+	    char *pattern = NULL;
+	    char *name;
+	    Tcl_Obj *namePtr;
+	    
+	    if ((objc != 3) && (objc != 4)) {
+  	        Tcl_WrongNumArgs(interp, 2, objv, "arrayName ?pattern?");
+		return TCL_ERROR;
+	    }
+	    if (notArray) {
+	        return TCL_OK;
+	    }
+	    if (objc == 4) {
+	        pattern = Tcl_GetStringFromObj(objv[3], (int *) NULL);
+	    }
+	    for (hPtr = Tcl_FirstHashEntry(varPtr->value.tablePtr, &search);
+		 hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+	        varPtr2 = (Var *) Tcl_GetHashValue(hPtr);
+		if (TclIsVarUndefined(varPtr2)) {
+		    continue;
+		}
+		name = Tcl_GetHashKey(varPtr->value.tablePtr, hPtr);
+		if ((objc == 4) && !Tcl_StringMatch(name, pattern)) {
+ 		    continue;	/* element name doesn't match pattern */
+		}
+		
+		namePtr = Tcl_NewStringObj(name, -1);
+		result = Tcl_ListObjAppendElement(interp, resultPtr, namePtr);
+		if (result != TCL_OK) {
+		    Tcl_DecrRefCount(namePtr); /* free unneeded name object */
+		    return result;
+		}
+	    }
+	    break;
+	}
+        case ARRAY_NEXTELEMENT: {
+	    ArraySearch *searchPtr;
+	    char *searchId;
+	    Tcl_HashEntry *hPtr;
+	    
+	    if (objc != 4) {
+	        Tcl_WrongNumArgs(interp, 2, objv, 
+                        "arrayName searchId");
+		return TCL_ERROR;
+	    }
+	    if (notArray) {
+  	        goto error;
+	    }
+	    searchId = Tcl_GetStringFromObj(objv[3], (int *) NULL);
+	    searchPtr = ParseSearchId(interp, varPtr, varName, searchId);
+	    if (searchPtr == NULL) {
+	        return TCL_ERROR;
+	    }
+	    while (1) {
+	        Var *varPtr2;
+
+		hPtr = searchPtr->nextEntry;
+		if (hPtr == NULL) {
+		    hPtr = Tcl_NextHashEntry(&searchPtr->search);
+		    if (hPtr == NULL) {
+		        return TCL_OK;
+		    }
+		} else {
+		    searchPtr->nextEntry = NULL;
+		}
+		varPtr2 = (Var *) Tcl_GetHashValue(hPtr);
+		if (!TclIsVarUndefined(varPtr2)) {
+		    break;
+		}
+	    }
+	    Tcl_SetStringObj(resultPtr,
+	            Tcl_GetHashKey(varPtr->value.tablePtr, hPtr), -1);
+	    break;
+	}
+        case ARRAY_SET: {
+	    Tcl_Obj **elemPtrs;
+	    int listLen, i, result;
+	    
+	    if (objc != 4) {
+	        Tcl_WrongNumArgs(interp, 2, objv, "arrayName list");
+		return TCL_ERROR;
+	    }
+	    result = Tcl_ListObjGetElements(interp, objv[3], &listLen, 
+                    &elemPtrs);
+	    if (result != TCL_OK) {
+	        return result;
+	    }
+	    if (listLen & 1) {
+	        Tcl_ResetResult(interp);
+		Tcl_AppendToObj(Tcl_GetObjResult(interp),
+                        "list must have an even number of elements", -1);
+		return TCL_ERROR;
+	    }
+	    if (listLen > 0) {
+		for (i = 0;  i < listLen;  i += 2) {
+		    if (Tcl_ObjSetVar2(interp, objv[2], elemPtrs[i],
+			    elemPtrs[i+1], TCL_LEAVE_ERR_MSG) == NULL) {
+			result = TCL_ERROR;
+			break;
+		    }
+		}
+		return result;
+	    }
+  
+	    /*
+	     * The list is empty make sure we have an array, or create
+	     * one if necessary.
+	     */
+	    
+	    if (varPtr != NULL) {
+		if (!TclIsVarUndefined(varPtr) && TclIsVarArray(varPtr)) {
+		    /*
+		     * Already an array, done.
+		     */
+		    
+		    return TCL_OK;
+                }
+		if (TclIsVarArrayElement(varPtr) ||
+			!TclIsVarUndefined(varPtr)) {
+		    /*
+		     * Either an array element, or a scalar: lose!
+		     */
+		    
+		    VarErrMsg(interp, varName, (char *)NULL, "array set",
+                            needArray);
+		    return TCL_ERROR;
+                }
+	    } else {
+		/*
+		 * Create variable for new array.
+		 */
+		
+		varPtr = TclLookupVar(interp, varName, (char *) NULL, 0, 0,
+			/*createPart1*/ 1, /*createPart2*/ 0,
+			&arrayPtr);
+	    }
+	    TclSetVarArray(varPtr);
+	    TclClearVarUndefined(varPtr);
+	    varPtr->value.tablePtr =
+		(Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
+	    Tcl_InitHashTable(varPtr->value.tablePtr, TCL_STRING_KEYS);
+	    return TCL_OK;
+	}
+        case ARRAY_SIZE: {
+	    Tcl_HashSearch search;
+	    Var *varPtr2;
+	    int size;
+
+	    if (objc != 3) {
+	        Tcl_WrongNumArgs(interp, 2, objv, "arrayName");
+		return TCL_ERROR;
+	    }
+	    size = 0;
+	    if (!notArray) {
+	        for (hPtr = Tcl_FirstHashEntry(varPtr->value.tablePtr, 
+                        &search);
+		     hPtr != NULL;  hPtr = Tcl_NextHashEntry(&search)) {
+		    varPtr2 = (Var *) Tcl_GetHashValue(hPtr);
+		    if (TclIsVarUndefined(varPtr2)) {
+		        continue;
+		    }
+		    size++;
+		}
+	    }
+	    Tcl_SetIntObj(resultPtr, size);
+	    break;
+	}
+        case ARRAY_STARTSEARCH: {
+	    ArraySearch *searchPtr;
+
+	    if (objc != 3) {
+	        Tcl_WrongNumArgs(interp, 2, objv, "arrayName");
+		return TCL_ERROR;
+	    }
+	    if (notArray) {
+	        goto error;
+	    }
+	    searchPtr = (ArraySearch *) ckalloc(sizeof(ArraySearch));
+	    if (varPtr->searchPtr == NULL) {
+	        searchPtr->id = 1;
+		Tcl_AppendStringsToObj(resultPtr, "s-1-", varName,
+		        (char *) NULL);
+	    } else {
+	        char string[20];
+
+		searchPtr->id = varPtr->searchPtr->id + 1;
+		TclFormatInt(string, searchPtr->id);
+		Tcl_AppendStringsToObj(resultPtr, "s-", string, "-", varName,
+			(char *) NULL);
+	    }
+	    searchPtr->varPtr = varPtr;
+	    searchPtr->nextEntry = Tcl_FirstHashEntry(varPtr->value.tablePtr,
+		    &searchPtr->search);
+	    searchPtr->nextPtr = varPtr->searchPtr;
+	    varPtr->searchPtr = searchPtr;
+	    break;
+	}
+    }
+    return TCL_OK;
+
+    error:
+    Tcl_AppendStringsToObj(resultPtr, "\"", varName, "\" isn't an array",
+	    (char *) NULL);
+    return TCL_ERROR;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MakeUpvar --
+ *
+ *	This procedure does all of the work of the "global" and "upvar"
+ *	commands.
+ *
+ * Results:
+ *	A standard Tcl completion code. If an error occurs then an
+ *	error message is left in iPtr->result.
+ *
+ * Side effects:
+ *	The variable given by myName is linked to the variable in framePtr
+ *	given by otherP1 and otherP2, so that references to myName are
+ *	redirected to the other variable like a symbolic link.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+MakeUpvar(iPtr, framePtr, otherP1, otherP2, otherFlags, myName, myFlags)
+    Interp *iPtr;		/* Interpreter containing variables. Used
+				 * for error messages, too. */
+    CallFrame *framePtr;	/* Call frame containing "other" variable.
+				 * NULL means use global :: context. */
+    char *otherP1, *otherP2;	/* Two-part name of variable in framePtr. */
+    int otherFlags;		/* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY:
+				 * indicates scope of "other" variable. */
+    char *myName;		/* Name of variable which will refer to
+				 * otherP1/otherP2. Must be a scalar. */
+    int myFlags;		/* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY:
+				 * indicates scope of myName. */
+{
+    Tcl_HashEntry *hPtr;
+    Var *otherPtr, *varPtr, *arrayPtr;
+    CallFrame *varFramePtr;
+    CallFrame *savedFramePtr = NULL;  /* Init. to avoid compiler warning. */
+    Tcl_HashTable *tablePtr;
+    Namespace *nsPtr, *altNsPtr, *dummyNsPtr;
+    char *tail;
+    int new;
+
+    /*
+     * Find "other" in "framePtr". If not looking up other in just the
+     * current namespace, temporarily replace the current var frame
+     * pointer in the interpreter in order to use TclLookupVar.
+     */
+
+    if (!(otherFlags & TCL_NAMESPACE_ONLY)) {
+	savedFramePtr = iPtr->varFramePtr;
+	iPtr->varFramePtr = framePtr;
+    }
+    otherPtr = TclLookupVar((Tcl_Interp *) iPtr, otherP1, otherP2,
+	    (otherFlags | TCL_LEAVE_ERR_MSG), "access",
+            /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
+    if (!(otherFlags & TCL_NAMESPACE_ONLY)) {
+	iPtr->varFramePtr = savedFramePtr;
+    }
+    if (otherPtr == NULL) {
+	return TCL_ERROR;
+    }
+
+    /*
+     * Now create a hashtable entry for "myName". Create it as either a
+     * namespace variable or as a local variable in a procedure call
+     * frame. Interpret myName as a namespace variable if:
+     *    1) so requested by a TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY flag,
+     *    2) there is no active frame (we're at the global :: scope),
+     *    3) the active frame was pushed to define the namespace context
+     *       for a "namespace eval" or "namespace inscope" command,
+     *    4) the name has namespace qualifiers ("::"s).
+     * If creating myName in the active procedure, look first in the
+     * frame's array of compiler-allocated local variables, then in its
+     * hashtable for runtime-created local variables. Create that
+     * procedure's local variable hashtable if necessary.
+     */
+
+    varFramePtr = iPtr->varFramePtr;
+    if ((myFlags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY))
+	    || (varFramePtr == NULL)
+	    || !varFramePtr->isProcCallFrame
+	    || (strstr(myName, "::") != NULL)) {
+	TclGetNamespaceForQualName((Tcl_Interp *) iPtr, myName,
+		(Namespace *) NULL, myFlags, &nsPtr, &altNsPtr, &dummyNsPtr, &tail);
+
+        if (nsPtr == NULL) {
+            nsPtr = altNsPtr;
+        }
+        if (nsPtr == NULL) {
+	    Tcl_AppendResult((Tcl_Interp *) iPtr, "bad variable name \"",
+		    myName, "\": unknown namespace", (char *) NULL);
+            return TCL_ERROR;
+        }
+	
+	/*
+	 * Check that we are not trying to create a namespace var linked to
+	 * a local variable in a procedure. If we allowed this, the local
+	 * variable in the shorter-lived procedure frame could go away
+	 * leaving the namespace var's reference invalid.
+	 */
+
+	if ((otherP2 ? arrayPtr->nsPtr : otherPtr->nsPtr) == NULL) {
+	    Tcl_AppendResult((Tcl_Interp *) iPtr, "bad variable name \"",
+                    myName, "\": upvar won't create namespace variable that refers to procedure variable",
+		    (char *) NULL);
+            return TCL_ERROR;
+        }
+	
+	hPtr = Tcl_CreateHashEntry(&nsPtr->varTable, tail, &new);
+	if (new) {
+	    varPtr = NewVar();
+	    Tcl_SetHashValue(hPtr, varPtr);
+	    varPtr->hPtr = hPtr;
+            varPtr->nsPtr = nsPtr;
+	} else {
+	    varPtr = (Var *) Tcl_GetHashValue(hPtr);
+	}
+    } else {			/* look in the call frame */
+	Proc *procPtr = varFramePtr->procPtr;
+	int localCt = procPtr->numCompiledLocals;
+	CompiledLocal *localPtr = procPtr->firstLocalPtr;
+	Var *localVarPtr = varFramePtr->compiledLocals;
+	int nameLen = strlen(myName);
+	int i;
+
+	varPtr = NULL;
+	for (i = 0;  i < localCt;  i++) {
+	    if (!TclIsVarTemporary(localPtr)) {
+		char *localName = localVarPtr->name;
+		if ((myName[0] == localName[0])
+		        && (nameLen == localPtr->nameLength)
+		        && (strcmp(myName, localName) == 0)) {
+		    varPtr = localVarPtr;
+		    new = 0;
+		    break;
+		}
+	    }
+	    localVarPtr++;
+	    localPtr = localPtr->nextPtr;
+	}
+	if (varPtr == NULL) {	/* look in frame's local var hashtable */
+	    tablePtr = varFramePtr->varTablePtr;
+	    if (tablePtr == NULL) {
+		tablePtr = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
+		Tcl_InitHashTable(tablePtr, TCL_STRING_KEYS);
+		varFramePtr->varTablePtr = tablePtr;
+	    }
+	    hPtr = Tcl_CreateHashEntry(tablePtr, myName, &new);
+	    if (new) {
+		varPtr = NewVar();
+		Tcl_SetHashValue(hPtr, varPtr);
+		varPtr->hPtr = hPtr;
+                varPtr->nsPtr = varFramePtr->nsPtr;
+	    } else {
+		varPtr = (Var *) Tcl_GetHashValue(hPtr);
+	    }
+	}
+    }
+
+    if (!new) {
+	/*
+	 * The variable already exists. Make sure this variable "varPtr"
+	 * isn't the same as "otherPtr" (avoid circular links). Also, if
+	 * it's not an upvar then it's an error. If it is an upvar, then
+	 * just disconnect it from the thing it currently refers to.
+	 */
+
+	if (varPtr == otherPtr) {
+	    Tcl_SetResult((Tcl_Interp *) iPtr,
+		    "can't upvar from variable to itself", TCL_STATIC);
+	    return TCL_ERROR;
+	}
+	if (TclIsVarLink(varPtr)) {
+	    Var *linkPtr = varPtr->value.linkPtr;
+	    if (linkPtr == otherPtr) {
+		return TCL_OK;
+	    }
+	    linkPtr->refCount--;
+	    if (TclIsVarUndefined(linkPtr)) {
+		CleanupVar(linkPtr, (Var *) NULL);
+	    }
+	} else if (!TclIsVarUndefined(varPtr)) {
+	    Tcl_AppendResult((Tcl_Interp *) iPtr, "variable \"", myName,
+		    "\" already exists", (char *) NULL);
+	    return TCL_ERROR;
+	} else if (varPtr->tracePtr != NULL) {
+	    Tcl_AppendResult((Tcl_Interp *) iPtr, "variable \"", myName,
+		    "\" has traces: can't use for upvar", (char *) NULL);
+	    return TCL_ERROR;
+	}
+    }
+    TclSetVarLink(varPtr);
+    TclClearVarUndefined(varPtr);
+    varPtr->value.linkPtr = otherPtr;
+    otherPtr->refCount++;
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_UpVar --
+ *
+ *	This procedure links one variable to another, just like
+ *	the "upvar" command.
+ *
+ * Results:
+ *	A standard Tcl completion code.  If an error occurs then
+ *	an error message is left in interp->result.
+ *
+ * Side effects:
+ *	The variable in frameName whose name is given by varName becomes
+ *	accessible under the name localName, so that references to
+ *	localName are redirected to the other variable like a symbolic
+ *	link.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_UpVar(interp, frameName, varName, localName, flags)
+    Tcl_Interp *interp;		/* Command interpreter in which varName is
+				 * to be looked up. */
+    char *frameName;		/* Name of the frame containing the source
+				 * variable, such as "1" or "#0". */
+    char *varName;		/* Name of a variable in interp to link to.
+				 * May be either a scalar name or an
+				 * element in an array. */
+    char *localName;		/* Name of link variable. */
+    int flags;			/* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY:
+				 * indicates scope of localName. */
+{
+    int result;
+    CallFrame *framePtr;
+    register char *p;
+
+    result = TclGetFrame(interp, frameName, &framePtr);
+    if (result == -1) {
+	return TCL_ERROR;
+    }
+
+    /*
+     * Figure out whether varName is an array reference, then call
+     * MakeUpvar to do all the real work.
+     */
+
+    for (p = varName;  *p != '\0';  p++) {
+	if (*p == '(') {
+	    char *openParen = p;
+	    do {
+		p++;
+	    } while (*p != '\0');
+	    p--;
+	    if (*p != ')') {
+		goto scalar;
+	    }
+	    *openParen = '\0';
+	    *p = '\0';
+	    result = MakeUpvar((Interp *) interp, framePtr, varName,
+		    openParen+1, 0, localName, flags);
+	    *openParen = '(';
+	    *p = ')';
+	    return result;
+	}
+    }
+
+    scalar:
+    return MakeUpvar((Interp *) interp, framePtr, varName, (char *) NULL,
+	    0, localName, flags);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_UpVar2 --
+ *
+ *	This procedure links one variable to another, just like
+ *	the "upvar" command.
+ *
+ * Results:
+ *	A standard Tcl completion code.  If an error occurs then
+ *	an error message is left in interp->result.
+ *
+ * Side effects:
+ *	The variable in frameName whose name is given by part1 and
+ *	part2 becomes accessible under the name localName, so that
+ *	references to localName are redirected to the other variable
+ *	like a symbolic link.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_UpVar2(interp, frameName, part1, part2, localName, flags)
+    Tcl_Interp *interp;		/* Interpreter containing variables.  Used
+				 * for error messages too. */
+    char *frameName;		/* Name of the frame containing the source
+				 * variable, such as "1" or "#0". */
+    char *part1, *part2;	/* Two parts of source variable name to
+				 * link to. */
+    char *localName;		/* Name of link variable. */
+    int flags;			/* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY:
+				 * indicates scope of localName. */
+{
+    int result;
+    CallFrame *framePtr;
+
+    result = TclGetFrame(interp, frameName, &framePtr);
+    if (result == -1) {
+	return TCL_ERROR;
+    }
+    return MakeUpvar((Interp *) interp, framePtr, part1, part2, 0,
+	    localName, flags);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetVariableFullName --
+ *
+ *	Given a Tcl_Var token returned by Tcl_FindNamespaceVar, this
+ *	procedure appends to an object the namespace variable's full
+ *	name, qualified by a sequence of parent namespace names.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      The variable's fully-qualified name is appended to the string
+ *	representation of objPtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_GetVariableFullName(interp, variable, objPtr)
+    Tcl_Interp *interp;	        /* Interpreter containing the variable. */
+    Tcl_Var variable;		/* Token for the variable returned by a
+				 * previous call to Tcl_FindNamespaceVar. */
+    Tcl_Obj *objPtr;		/* Points to the object onto which the
+				 * variable's full name is appended. */
+{
+    Interp *iPtr = (Interp *) interp;
+    register Var *varPtr = (Var *) variable;
+    char *name;
+
+    /*
+     * Add the full name of the containing namespace (if any), followed by
+     * the "::" separator, then the variable name.
+     */
+
+    if (varPtr != NULL) {
+	if (!TclIsVarArrayElement(varPtr)) {
+	    if (varPtr->nsPtr != NULL) {
+		Tcl_AppendToObj(objPtr, varPtr->nsPtr->fullName, -1);
+		if (varPtr->nsPtr != iPtr->globalNsPtr) {
+		    Tcl_AppendToObj(objPtr, "::", 2);
+		}
+	    }
+	    if (varPtr->name != NULL) {
+		Tcl_AppendToObj(objPtr, varPtr->name, -1);
+	    } else if (varPtr->hPtr != NULL) {
+		name = Tcl_GetHashKey(varPtr->hPtr->tablePtr, varPtr->hPtr);
+		Tcl_AppendToObj(objPtr, name, -1);
+	    }
+	}
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GlobalObjCmd --
+ *
+ *	This object-based procedure is invoked to process the "global" Tcl
+ *	command. See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result value.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GlobalObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Interp *iPtr = (Interp *) interp;
+    register Tcl_Obj *objPtr;
+    char *varName;
+    register char *tail;
+    int result, i;
+
+    if (objc < 2) {
+	Tcl_WrongNumArgs(interp, 1, objv, "varName ?varName ...?");
+	return TCL_ERROR;
+    }
+
+    /*
+     * If we are not executing inside a Tcl procedure, just return.
+     */
+    
+    if ((iPtr->varFramePtr == NULL)
+	    || !iPtr->varFramePtr->isProcCallFrame) {
+	return TCL_OK;
+    }
+
+    for (i = 1;  i < objc;  i++) {
+	/*
+	 * Make a local variable linked to its counterpart in the global ::
+	 * namespace.
+	 */
+	
+	objPtr = objv[i];
+	varName = Tcl_GetStringFromObj(objPtr, (int *) NULL);
+
+	/*
+	 * The variable name might have a scope qualifier, but the name for
+         * the local "link" variable must be the simple name at the tail.
+	 */
+
+	for (tail = varName;  *tail != '\0';  tail++) {
+	    /* empty body */
+	}
+        while ((tail > varName) && ((*tail != ':') || (*(tail-1) != ':'))) {
+            tail--;
+	}
+        if (*tail == ':') {
+            tail++;
+	}
+
+	/*
+	 * Link to the variable "varName" in the global :: namespace.
+	 */
+	
+	result = MakeUpvar(iPtr, (CallFrame *) NULL,
+		varName, (char *) NULL, /*otherFlags*/ TCL_GLOBAL_ONLY,
+	        /*myName*/ tail, /*myFlags*/ 0);
+	if (result != TCL_OK) {
+	    return result;
+	}
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_VariableObjCmd --
+ *
+ *	Invoked to implement the "variable" command that creates one or more
+ *	global variables. Handles the following syntax:
+ *
+ *	    variable ?name value...? name ?value?
+ *
+ *	One or more variables can be created. The variables are initialized
+ *	with the specified values. The value for the last variable is
+ *	optional.
+ *
+ *	If the variable does not exist, it is created and given the optional
+ *	value. If it already exists, it is simply set to the optional
+ *	value. Normally, "name" is an unqualified name, so it is created in
+ *	the current namespace. If it includes namespace qualifiers, it can
+ *	be created in another namespace.
+ *
+ *	If the variable command is executed inside a Tcl procedure, it
+ *	creates a local variable linked to the newly-created namespace
+ *	variable.
+ *
+ * Results:
+ *	Returns TCL_OK if the variable is found or created. Returns
+ *	TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ *	If anything goes wrong, this procedure returns an error message
+ *	as the result in the interpreter's result object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_VariableObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    Interp *iPtr = (Interp *) interp;
+    char *varName, *tail, *cp;
+    Var *varPtr, *arrayPtr;
+    Tcl_Obj *varValuePtr;
+    int i, result;
+
+    for (i = 1;  i < objc;  i = i+2) {
+	/*
+	 * Look up each variable in the current namespace context, creating
+	 * it if necessary.
+	 */
+	
+	varName = Tcl_GetStringFromObj(objv[i], (int *) NULL);
+	varPtr = TclLookupVar(interp, varName, (char *) NULL,
+                (TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "define",
+                /*createPart1*/ 1, /*createPart2*/ 0, &arrayPtr);
+	if (varPtr == NULL) {
+	    return TCL_ERROR;
+	}
+
+	/*
+	 * Mark the variable as a namespace variable and increment its 
+	 * reference count so that it will persist until its namespace is
+	 * destroyed or until the variable is unset.
+	 */
+
+	if (!(varPtr->flags & VAR_NAMESPACE_VAR)) {
+	    varPtr->flags |= VAR_NAMESPACE_VAR;
+	    varPtr->refCount++;
+	}
+
+	/*
+	 * If a value was specified, set the variable to that value.
+	 * Otherwise, if the variable is new, leave it undefined.
+	 * (If the variable already exists and no value was specified,
+	 * leave its value unchanged; just create the local link if
+	 * we're in a Tcl procedure).
+	 */
+
+	if (i+1 < objc) {	/* a value was specified */
+	    varValuePtr = Tcl_ObjSetVar2(interp, objv[i], (Tcl_Obj *) NULL,
+		    objv[i+1], (TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG));
+	    if (varValuePtr == NULL) {
+		return TCL_ERROR;
+	    }
+	}
+
+	/*
+	 * If we are executing inside a Tcl procedure, create a local
+	 * variable linked to the new namespace variable "varName".
+	 */
+
+	if ((iPtr->varFramePtr != NULL)
+	        && iPtr->varFramePtr->isProcCallFrame) {
+	    /*
+	     * varName might have a scope qualifier, but the name for the
+	     * local "link" variable must be the simple name at the tail.
+	     *
+	     * Locate tail in one pass: drop any prefix after two *or more*
+	     * consecutive ":" characters).
+	     */
+
+	    for (tail = cp = varName;  *cp != '\0'; ) {
+		if (*cp++ == ':') {
+		    while (*cp++ == ':') {
+			tail = cp;
+		    }
+		}
+	    }
+	    
+	    /*
+	     * Create a local link "tail" to the variable "varName" in the
+	     * current namespace.
+	     */
+	    
+	    result = MakeUpvar(iPtr, (CallFrame *) NULL,
+		    /*otherP1*/ varName, /*otherP2*/ (char *) NULL,
+                    /*otherFlags*/ TCL_NAMESPACE_ONLY,
+		    /*myName*/ tail, /*myFlags*/ 0);
+	    if (result != TCL_OK) {
+		return result;
+	    }
+	}
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_UpvarObjCmd --
+ *
+ *	This object-based procedure is invoked to process the "upvar"
+ *	Tcl command. See the user documentation for details on what it does.
+ *
+ * Results:
+ *	A standard Tcl object result value.
+ *
+ * Side effects:
+ *	See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+	/* ARGSUSED */
+int
+Tcl_UpvarObjCmd(dummy, interp, objc, objv)
+    ClientData dummy;		/* Not used. */
+    Tcl_Interp *interp;		/* Current interpreter. */
+    int objc;			/* Number of arguments. */
+    Tcl_Obj *CONST objv[];	/* Argument objects. */
+{
+    register Interp *iPtr = (Interp *) interp;
+    CallFrame *framePtr;
+    char *frameSpec, *otherVarName, *myVarName;
+    register char *p;
+    int result;
+
+    if (objc < 3) {
+	upvarSyntax:
+	Tcl_WrongNumArgs(interp, 1, objv,
+		"?level? otherVar localVar ?otherVar localVar ...?");
+	return TCL_ERROR;
+    }
+
+    /*
+     * Find the call frame containing each of the "other variables" to be
+     * linked to. FAILS IF objv[1]'s STRING REP CONTAINS NULLS.
+     */
+
+    frameSpec = Tcl_GetStringFromObj(objv[1], (int *) NULL);
+    result = TclGetFrame(interp, frameSpec, &framePtr);
+    if (result == -1) {
+	return TCL_ERROR;
+    }
+    objc -= result+1;
+    if ((objc & 1) != 0) {
+	goto upvarSyntax;
+    }
+    objv += result+1;
+
+    /*
+     * Iterate over each (other variable, local variable) pair.
+     * Divide the other variable name into two parts, then call
+     * MakeUpvar to do all the work of linking it to the local variable.
+     */
+
+    for ( ;  objc > 0;  objc -= 2, objv += 2) {
+	myVarName = Tcl_GetStringFromObj(objv[1], (int *) NULL);
+	otherVarName = Tcl_GetStringFromObj(objv[0], (int *) NULL);
+	for (p = otherVarName;  *p != 0;  p++) {
+	    if (*p == '(') {
+		char *openParen = p;
+
+		do {
+		    p++;
+		} while (*p != '\0');
+		p--;
+		if (*p != ')') {
+		    goto scalar;
+		}
+		*openParen = '\0';
+		*p = '\0';
+		result = MakeUpvar(iPtr, framePtr,
+		        otherVarName, openParen+1, /*otherFlags*/ 0,
+			myVarName, /*flags*/ 0);
+		*openParen = '(';
+		*p = ')';
+		goto checkResult;
+	    }
+	}
+	scalar:
+	result = MakeUpvar(iPtr, framePtr, otherVarName, (char *) NULL, 0,
+	        myVarName, /*flags*/ 0);
+
+	checkResult:
+	if (result != TCL_OK) {
+	    return TCL_ERROR;
+	}
+    }
+    return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CallTraces --
+ *
+ *	This procedure is invoked to find and invoke relevant
+ *	trace procedures associated with a particular operation on
+ *	a variable. This procedure invokes traces both on the
+ *	variable and on its containing array (where relevant).
+ *
+ * Results:
+ *	The return value is NULL if no trace procedures were invoked, or
+ *	if all the invoked trace procedures returned successfully.
+ *	The return value is non-NULL if a trace procedure returned an
+ *	error (in this case no more trace procedures were invoked after
+ *	the error was returned). In this case the return value is a
+ *	pointer to a static string describing the error.
+ *
+ * Side effects:
+ *	Almost anything can happen, depending on trace; this procedure
+ *	itself doesn't have any side effects.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+CallTraces(iPtr, arrayPtr, varPtr, part1, part2, flags)
+    Interp *iPtr;		/* Interpreter containing variable. */
+    register Var *arrayPtr;	/* Pointer to array variable that contains
+				 * the variable, or NULL if the variable
+				 * isn't an element of an array. */
+    Var *varPtr;		/* Variable whose traces are to be
+				 * invoked. */
+    char *part1, *part2;	/* Variable's two-part name. */
+    int flags;			/* Flags passed to trace procedures:
+				 * indicates what's happening to variable,
+				 * plus other stuff like TCL_GLOBAL_ONLY,
+				 * TCL_NAMESPACE_ONLY, and
+				 * TCL_INTERP_DESTROYED. May also contain
+				 * TCL_PARSE_PART1, which should not be
+				 * passed through to callbacks. */
+{
+    register VarTrace *tracePtr;
+    ActiveVarTrace active;
+    char *result, *openParen, *p;
+    Tcl_DString nameCopy;
+    int copiedName;
+
+    /*
+     * If there are already similar trace procedures active for the
+     * variable, don't call them again.
+     */
+
+    if (varPtr->flags & VAR_TRACE_ACTIVE) {
+	return NULL;
+    }
+    varPtr->flags |= VAR_TRACE_ACTIVE;
+    varPtr->refCount++;
+
+    /*
+     * If the variable name hasn't been parsed into array name and
+     * element, do it here.  If there really is an array element,
+     * make a copy of the original name so that NULLs can be
+     * inserted into it to separate the names (can't modify the name
+     * string in place, because the string might get used by the
+     * callbacks we invoke).
+     */
+
+    copiedName = 0;
+    if (flags & TCL_PARSE_PART1) {
+	for (p = part1; ; p++) {
+	    if (*p == 0) {
+		break;
+	    }
+	    if (*p == '(') {
+		openParen = p;
+		do {
+		    p++;
+		} while (*p != '\0');
+		p--;
+		if (*p == ')') {
+		    Tcl_DStringInit(&nameCopy);
+		    Tcl_DStringAppend(&nameCopy, part1, (p-part1));
+		    part2 = Tcl_DStringValue(&nameCopy)
+			+ (openParen + 1 - part1);
+		    part2[-1] = 0;
+		    part1 = Tcl_DStringValue(&nameCopy);
+		    copiedName = 1;
+		}
+		break;
+	    }
+	}
+    }
+    flags &= ~TCL_PARSE_PART1;
+
+    /*
+     * Invoke traces on the array containing the variable, if relevant.
+     */
+
+    result = NULL;
+    active.nextPtr = iPtr->activeTracePtr;
+    iPtr->activeTracePtr = &active;
+    if (arrayPtr != NULL) {
+	arrayPtr->refCount++;
+	active.varPtr = arrayPtr;
+	for (tracePtr = arrayPtr->tracePtr;  tracePtr != NULL;
+	     tracePtr = active.nextTracePtr) {
+	    active.nextTracePtr = tracePtr->nextPtr;
+	    if (!(tracePtr->flags & flags)) {
+		continue;
+	    }
+	    result = (*tracePtr->traceProc)(tracePtr->clientData,
+		    (Tcl_Interp *) iPtr, part1, part2, flags);
+	    if (result != NULL) {
+		if (flags & TCL_TRACE_UNSETS) {
+		    result = NULL;
+		} else {
+		    goto done;
+		}
+	    }
+	}
+    }
+
+    /*
+     * Invoke traces on the variable itself.
+     */
+
+    if (flags & TCL_TRACE_UNSETS) {
+	flags |= TCL_TRACE_DESTROYED;
+    }
+    active.varPtr = varPtr;
+    for (tracePtr = varPtr->tracePtr; tracePtr != NULL;
+	 tracePtr = active.nextTracePtr) {
+	active.nextTracePtr = tracePtr->nextPtr;
+	if (!(tracePtr->flags & flags)) {
+	    continue;
+	}
+	result = (*tracePtr->traceProc)(tracePtr->clientData,
+		(Tcl_Interp *) iPtr, part1, part2, flags);
+	if (result != NULL) {
+	    if (flags & TCL_TRACE_UNSETS) {
+		result = NULL;
+	    } else {
+		goto done;
+	    }
+	}
+    }
+
+    /*
+     * Restore the variable's flags, remove the record of our active
+     * traces, and then return.
+     */
+
+    done:
+    if (arrayPtr != NULL) {
+	arrayPtr->refCount--;
+    }
+    if (copiedName) {
+	Tcl_DStringFree(&nameCopy);
+    }
+    varPtr->flags &= ~VAR_TRACE_ACTIVE;
+    varPtr->refCount--;
+    iPtr->activeTracePtr = active.nextPtr;
+    return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NewVar --
+ *
+ *	Create a new heap-allocated variable that will eventually be
+ *	entered into a hashtable.
+ *
+ * Results:
+ *	The return value is a pointer to the new variable structure. It is
+ *	marked as a scalar variable (and not a link or array variable). Its
+ *	value initially is NULL. The variable is not part of any hash table
+ *	yet. Since it will be in a hashtable and not in a call frame, its
+ *	name field is set NULL. It is initially marked as undefined.
+ *
+ * Side effects:
+ *	Storage gets allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Var *
+NewVar()
+{
+    register Var *varPtr;
+
+    varPtr = (Var *) ckalloc(sizeof(Var));
+    varPtr->value.objPtr = NULL;
+    varPtr->name = NULL;
+    varPtr->nsPtr = NULL;
+    varPtr->hPtr = NULL;
+    varPtr->refCount = 0;
+    varPtr->tracePtr = NULL;
+    varPtr->searchPtr = NULL;
+    varPtr->flags = (VAR_SCALAR | VAR_UNDEFINED | VAR_IN_HASHTABLE);
+    return varPtr;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ParseSearchId --
+ *
+ *	This procedure translates from a string to a pointer to an
+ *	active array search (if there is one that matches the string).
+ *
+ * Results:
+ *	The return value is a pointer to the array search indicated
+ *	by string, or NULL if there isn't one.  If NULL is returned,
+ *	interp->result contains an error message.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static ArraySearch *
+ParseSearchId(interp, varPtr, varName, string)
+    Tcl_Interp *interp;		/* Interpreter containing variable. */
+    Var *varPtr;		/* Array variable search is for. */
+    char *varName;		/* Name of array variable that search is
+				 * supposed to be for. */
+    char *string;		/* String containing id of search. Must have
+				 * form "search-num-var" where "num" is a
+				 * decimal number and "var" is a variable
+				 * name. */
+{
+    char *end;
+    int id;
+    ArraySearch *searchPtr;
+
+    /*
+     * Parse the id into the three parts separated by dashes.
+     */
+
+    if ((string[0] != 's') || (string[1] != '-')) {
+	syntax:
+	Tcl_AppendResult(interp, "illegal search identifier \"", string,
+		"\"", (char *) NULL);
+	return NULL;
+    }
+    id = strtoul(string+2, &end, 10);
+    if ((end == (string+2)) || (*end != '-')) {
+	goto syntax;
+    }
+    if (strcmp(end+1, varName) != 0) {
+	Tcl_AppendResult(interp, "search identifier \"", string,
+		"\" isn't for variable \"", varName, "\"", (char *) NULL);
+	return NULL;
+    }
+
+    /*
+     * Search through the list of active searches on the interpreter
+     * to see if the desired one exists.
+     */
+
+    for (searchPtr = varPtr->searchPtr; searchPtr != NULL;
+	 searchPtr = searchPtr->nextPtr) {
+	if (searchPtr->id == id) {
+	    return searchPtr;
+	}
+    }
+    Tcl_AppendResult(interp, "couldn't find search \"", string, "\"",
+	    (char *) NULL);
+    return NULL;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteSearches --
+ *
+ *	This procedure is called to free up all of the searches
+ *	associated with an array variable.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Memory is released to the storage allocator.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DeleteSearches(arrayVarPtr)
+    register Var *arrayVarPtr;		/* Variable whose searches are
+					 * to be deleted. */
+{
+    ArraySearch *searchPtr;
+
+    while (arrayVarPtr->searchPtr != NULL) {
+	searchPtr = arrayVarPtr->searchPtr;
+	arrayVarPtr->searchPtr = searchPtr->nextPtr;
+	ckfree((char *) searchPtr);
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclDeleteVars --
+ *
+ *	This procedure is called to recycle all the storage space
+ *	associated with a table of variables. For this procedure
+ *	to work correctly, it must not be possible for any of the
+ *	variables in the table to be accessed from Tcl commands
+ *	(e.g. from trace procedures).
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Variables are deleted and trace procedures are invoked, if
+ *	any are declared.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclDeleteVars(iPtr, tablePtr)
+    Interp *iPtr;		/* Interpreter to which variables belong. */
+    Tcl_HashTable *tablePtr;	/* Hash table containing variables to
+				 * delete. */
+{
+    Tcl_Interp *interp = (Tcl_Interp *) iPtr;
+    Tcl_HashSearch search;
+    Tcl_HashEntry *hPtr;
+    register Var *varPtr;
+    Var *linkPtr;
+    int flags;
+    ActiveVarTrace *activePtr;
+    Tcl_Obj *objPtr;
+    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+
+    /*
+     * Determine what flags to pass to the trace callback procedures.
+     */
+
+    flags = TCL_TRACE_UNSETS;
+    if (tablePtr == &iPtr->globalNsPtr->varTable) {
+	flags |= (TCL_INTERP_DESTROYED | TCL_GLOBAL_ONLY);
+    } else if (tablePtr == &currNsPtr->varTable) {
+	flags |= TCL_NAMESPACE_ONLY;
+    }
+
+    for (hPtr = Tcl_FirstHashEntry(tablePtr, &search);  hPtr != NULL;
+	 hPtr = Tcl_NextHashEntry(&search)) {
+	varPtr = (Var *) Tcl_GetHashValue(hPtr);
+
+	/*
+	 * For global/upvar variables referenced in procedures, decrement
+	 * the reference count on the variable referred to, and free
+	 * the referenced variable if it's no longer needed. Don't delete
+	 * the hash entry for the other variable if it's in the same table
+	 * as us: this will happen automatically later on.
+	 */
+
+	if (TclIsVarLink(varPtr)) {
+	    linkPtr = varPtr->value.linkPtr;
+	    linkPtr->refCount--;
+	    if ((linkPtr->refCount == 0) && TclIsVarUndefined(linkPtr)
+		    && (linkPtr->tracePtr == NULL)
+		    && (linkPtr->flags & VAR_IN_HASHTABLE)) {
+		if (linkPtr->hPtr == NULL) {
+		    ckfree((char *) linkPtr);
+		} else if (linkPtr->hPtr->tablePtr != tablePtr) {
+		    Tcl_DeleteHashEntry(linkPtr->hPtr);
+		    ckfree((char *) linkPtr);
+		}
+	    }
+	}
+
+	/*
+	 * Invoke traces on the variable that is being deleted, then
+	 * free up the variable's space (no need to free the hash entry
+	 * here, unless we're dealing with a global variable: the
+	 * hash entries will be deleted automatically when the whole
+	 * table is deleted). Note that we give CallTraces the variable's
+	 * fully-qualified name so that any called trace procedures can
+	 * refer to these variables being deleted.
+	 */
+
+	if (varPtr->tracePtr != NULL) {
+	    objPtr = Tcl_NewObj();
+	    Tcl_IncrRefCount(objPtr); /* until done with traces */
+	    Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr, objPtr);
+	    (void) CallTraces(iPtr, (Var *) NULL, varPtr,
+		    Tcl_GetStringFromObj(objPtr, (int *) NULL),
+		    (char *) NULL, flags);
+	    Tcl_DecrRefCount(objPtr); /* free no longer needed obj */
+
+	    while (varPtr->tracePtr != NULL) {
+		VarTrace *tracePtr = varPtr->tracePtr;
+		varPtr->tracePtr = tracePtr->nextPtr;
+		ckfree((char *) tracePtr);
+	    }
+	    for (activePtr = iPtr->activeTracePtr; activePtr != NULL;
+		 activePtr = activePtr->nextPtr) {
+		if (activePtr->varPtr == varPtr) {
+		    activePtr->nextTracePtr = NULL;
+		}
+	    }
+	}
+	    
+	if (TclIsVarArray(varPtr)) {
+	    DeleteArray(iPtr, Tcl_GetHashKey(tablePtr, hPtr), varPtr,
+	            flags);
+	    varPtr->value.tablePtr = NULL;
+	}
+	if (TclIsVarScalar(varPtr) && (varPtr->value.objPtr != NULL)) {
+	    objPtr = varPtr->value.objPtr;
+	    TclDecrRefCount(objPtr);
+	    varPtr->value.objPtr = NULL;
+	}
+	varPtr->hPtr = NULL;
+	varPtr->tracePtr = NULL;
+	TclSetVarUndefined(varPtr);
+	TclSetVarScalar(varPtr);
+
+	/*
+	 * If the variable was a namespace variable, decrement its 
+	 * reference count. We are in the process of destroying its
+	 * namespace so that namespace will no longer "refer" to the
+	 * variable.
+	 */
+
+	if (varPtr->flags & VAR_NAMESPACE_VAR) {
+	    varPtr->flags &= ~VAR_NAMESPACE_VAR;
+	    varPtr->refCount--;
+	}
+
+	/*
+	 * Recycle the variable's memory space if there aren't any upvar's
+	 * pointing to it. If there are upvars to this variable, then the
+	 * variable will get freed when the last upvar goes away.
+	 */
+
+	if (varPtr->refCount == 0) {
+	    ckfree((char *) varPtr); /* this Var must be VAR_IN_HASHTABLE */
+	}
+    }
+    Tcl_DeleteHashTable(tablePtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclDeleteCompiledLocalVars --
+ *
+ *	This procedure is called to recycle storage space associated with
+ *	the compiler-allocated array of local variables in a procedure call
+ *	frame. This procedure resembles TclDeleteVars above except that each
+ *	variable is stored in a call frame and not a hash table. For this
+ *	procedure to work correctly, it must not be possible for any of the
+ *	variable in the table to be accessed from Tcl commands (e.g. from
+ *	trace procedures).
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Variables are deleted and trace procedures are invoked, if
+ *	any are declared.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclDeleteCompiledLocalVars(iPtr, framePtr)
+    Interp *iPtr;		/* Interpreter to which variables belong. */
+    CallFrame *framePtr;	/* Procedure call frame containing
+				 * compiler-assigned local variables to
+				 * delete. */
+{
+    register Var *varPtr;
+    int flags;			/* Flags passed to trace procedures. */
+    Var *linkPtr;
+    ActiveVarTrace *activePtr;
+    int numLocals, i;
+
+    flags = TCL_TRACE_UNSETS;
+    numLocals = framePtr->numCompiledLocals;
+    varPtr = framePtr->compiledLocals;
+    for (i = 0;  i < numLocals;  i++) {
+	/*
+	 * For global/upvar variables referenced in procedures, decrement
+	 * the reference count on the variable referred to, and free
+	 * the referenced variable if it's no longer needed. Don't delete
+	 * the hash entry for the other variable if it's in the same table
+	 * as us: this will happen automatically later on.
+	 */
+
+	if (TclIsVarLink(varPtr)) {
+	    linkPtr = varPtr->value.linkPtr;
+	    linkPtr->refCount--;
+	    if ((linkPtr->refCount == 0) && TclIsVarUndefined(linkPtr)
+		    && (linkPtr->tracePtr == NULL)
+		    && (linkPtr->flags & VAR_IN_HASHTABLE)) {
+		if (linkPtr->hPtr == NULL) {
+		    ckfree((char *) linkPtr);
+		} else {
+		    Tcl_DeleteHashEntry(linkPtr->hPtr);
+		    ckfree((char *) linkPtr);
+		}
+	    }
+	}
+
+	/*
+	 * Invoke traces on the variable that is being deleted. Then delete
+	 * the variable's trace records.
+	 */
+
+	if (varPtr->tracePtr != NULL) {
+	    (void) CallTraces(iPtr, (Var *) NULL, varPtr,
+		    varPtr->name, (char *) NULL, flags);
+	    while (varPtr->tracePtr != NULL) {
+		VarTrace *tracePtr = varPtr->tracePtr;
+		varPtr->tracePtr = tracePtr->nextPtr;
+		ckfree((char *) tracePtr);
+	    }
+	    for (activePtr = iPtr->activeTracePtr; activePtr != NULL;
+		 activePtr = activePtr->nextPtr) {
+		if (activePtr->varPtr == varPtr) {
+		    activePtr->nextTracePtr = NULL;
+		}
+	    }
+	}
+
+        /*
+	 * Now if the variable is an array, delete its element hash table.
+	 * Otherwise, if it's a scalar variable, decrement the ref count
+	 * of its value.
+	 */
+	    
+	if (TclIsVarArray(varPtr) && (varPtr->value.tablePtr != NULL)) {
+	    DeleteArray(iPtr, varPtr->name, varPtr, flags);
+	}
+	if (TclIsVarScalar(varPtr) && (varPtr->value.objPtr != NULL)) {
+	    TclDecrRefCount(varPtr->value.objPtr);
+	    varPtr->value.objPtr = NULL;
+	}
+	varPtr->hPtr = NULL;
+	varPtr->tracePtr = NULL;
+	TclSetVarUndefined(varPtr);
+	TclSetVarScalar(varPtr);
+	varPtr++;
+    }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteArray --
+ *
+ *	This procedure is called to free up everything in an array
+ *	variable.  It's the caller's responsibility to make sure
+ *	that the array is no longer accessible before this procedure
+ *	is called.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	All storage associated with varPtr's array elements is deleted
+ *	(including the array's hash table). Deletion trace procedures for
+ *	array elements are invoked, then deleted. Any pending traces for
+ *	array elements are also deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DeleteArray(iPtr, arrayName, varPtr, flags)
+    Interp *iPtr;			/* Interpreter containing array. */
+    char *arrayName;			/* Name of array (used for trace
+					 * callbacks). */
+    Var *varPtr;			/* Pointer to variable structure. */
+    int flags;				/* Flags to pass to CallTraces:
+					 * TCL_TRACE_UNSETS and sometimes
+					 * TCL_INTERP_DESTROYED,
+					 * TCL_NAMESPACE_ONLY, or
+					 * TCL_GLOBAL_ONLY. */
+{
+    Tcl_HashSearch search;
+    register Tcl_HashEntry *hPtr;
+    register Var *elPtr;
+    ActiveVarTrace *activePtr;
+    Tcl_Obj *objPtr;
+
+    DeleteSearches(varPtr);
+    for (hPtr = Tcl_FirstHashEntry(varPtr->value.tablePtr, &search);
+	 hPtr != NULL;  hPtr = Tcl_NextHashEntry(&search)) {
+	elPtr = (Var *) Tcl_GetHashValue(hPtr);
+	if (TclIsVarScalar(elPtr) && (elPtr->value.objPtr != NULL)) {
+	    objPtr = elPtr->value.objPtr;
+	    TclDecrRefCount(objPtr);
+	    elPtr->value.objPtr = NULL;
+	}
+	elPtr->hPtr = NULL;
+	if (elPtr->tracePtr != NULL) {
+	    elPtr->flags &= ~VAR_TRACE_ACTIVE;
+	    (void) CallTraces(iPtr, (Var *) NULL, elPtr, arrayName,
+		    Tcl_GetHashKey(varPtr->value.tablePtr, hPtr), flags);
+	    while (elPtr->tracePtr != NULL) {
+		VarTrace *tracePtr = elPtr->tracePtr;
+		elPtr->tracePtr = tracePtr->nextPtr;
+		ckfree((char *) tracePtr);
+	    }
+	    for (activePtr = iPtr->activeTracePtr; activePtr != NULL;
+		 activePtr = activePtr->nextPtr) {
+		if (activePtr->varPtr == elPtr) {
+		    activePtr->nextTracePtr = NULL;
+		}
+	    }
+	}
+	TclSetVarUndefined(elPtr);
+	TclSetVarScalar(elPtr);
+	if (elPtr->refCount == 0) {
+	    ckfree((char *) elPtr); /* element Vars are VAR_IN_HASHTABLE */
+	}
+    }
+    Tcl_DeleteHashTable(varPtr->value.tablePtr);
+    ckfree((char *) varPtr->value.tablePtr);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CleanupVar --
+ *
+ *	This procedure is called when it looks like it may be OK to free up
+ *	a variable's storage. If the variable is in a hashtable, its Var
+ *	structure and hash table entry will be freed along with those of its
+ *	containing array, if any. This procedure is called, for example,
+ *	when a trace on a variable deletes a variable.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	If the variable (or its containing array) really is dead and in a
+ *	hashtable, then its Var structure, and possibly its hash table
+ *	entry, is freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CleanupVar(varPtr, arrayPtr)
+    Var *varPtr;		/* Pointer to variable that may be a
+				 * candidate for being expunged. */
+    Var *arrayPtr;		/* Array that contains the variable, or
+				 * NULL if this variable isn't an array
+				 * element. */
+{
+    if (TclIsVarUndefined(varPtr) && (varPtr->refCount == 0)
+	    && (varPtr->tracePtr == NULL)
+	    && (varPtr->flags & VAR_IN_HASHTABLE)) {
+	if (varPtr->hPtr != NULL) {
+	    Tcl_DeleteHashEntry(varPtr->hPtr);
+	}
+	ckfree((char *) varPtr);
+    }
+    if (arrayPtr != NULL) {
+	if (TclIsVarUndefined(arrayPtr) && (arrayPtr->refCount == 0)
+		&& (arrayPtr->tracePtr == NULL)
+	        && (arrayPtr->flags & VAR_IN_HASHTABLE)) {
+	    if (arrayPtr->hPtr != NULL) {
+		Tcl_DeleteHashEntry(arrayPtr->hPtr);
+	    }
+	    ckfree((char *) arrayPtr);
+	}
+    }
+}
+/*
+ *----------------------------------------------------------------------
+ *
+ * VarErrMsg --
+ *
+ *      Generate a reasonable error message describing why a variable
+ *      operation failed.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      Interp->result is reset to hold a message identifying the
+ *      variable given by part1 and part2 and describing why the
+ *      variable operation failed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+VarErrMsg(interp, part1, part2, operation, reason)
+    Tcl_Interp *interp;         /* Interpreter in which to record message. */
+    char *part1, *part2;        /* Variable's two-part name. */
+    char *operation;            /* String describing operation that failed,
+                                 * e.g. "read", "set", or "unset". */
+    char *reason;               /* String describing why operation failed. */
+{
+    Tcl_ResetResult(interp);
+    Tcl_AppendResult(interp, "can't ", operation, " \"", part1,
+	    (char *) NULL);
+    if (part2 != NULL) {
+        Tcl_AppendResult(interp, "(", part2, ")", (char *) NULL);
+    }
+    Tcl_AppendResult(interp, "\": ", reason, (char *) NULL);
+}
Index: trunk/Delphes/Delphes-3.0.9/modules/BTagging.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/BTagging.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/BTagging.cc	(revision 5)
@@ -0,0 +1,210 @@
+
+/** \class BTagging
+ *
+ *  Determines origin of jet,
+ *  applies b-tagging efficiency (miss identification rate) formulas
+ *  and sets b-tagging flags 
+ *
+ *  $Date: 2013-04-26 12:39:14 +0200 (Fri, 26 Apr 2013) $
+ *  $Revision: 1099 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/BTagging.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm> 
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+class BTaggingPartonClassifier : public ExRootClassifier
+{
+public:
+
+  BTaggingPartonClassifier() {}
+
+  Int_t GetCategory(TObject *object);
+  
+  Double_t fEtaMax, fPTMin;
+};
+
+//------------------------------------------------------------------------------
+
+Int_t BTaggingPartonClassifier::GetCategory(TObject *object)
+{
+  Candidate *parton = static_cast<Candidate*>(object);
+  const TLorentzVector &momentum = parton->Momentum;
+  Int_t pdgCode;
+
+  if(momentum.Pt() <= fPTMin || TMath::Abs(momentum.Eta()) > fEtaMax) return -1;
+  
+  pdgCode = TMath::Abs(parton->PID);
+  if(pdgCode != 21 && pdgCode > 5) return -1;
+
+  return 0;
+}
+
+//------------------------------------------------------------------------------
+
+BTagging::BTagging() :
+  fClassifier(0), fFilter(0),
+  fItPartonInputArray(0), fItJetInputArray(0)
+{
+  fClassifier = new BTaggingPartonClassifier;
+}
+
+//------------------------------------------------------------------------------
+
+BTagging::~BTagging()
+{
+  if(fClassifier) delete fClassifier;
+}
+
+//------------------------------------------------------------------------------
+
+void BTagging::Init()
+{
+  map< Int_t, DelphesFormula * >::iterator itEfficiencyMap;
+  ExRootConfParam param;
+  DelphesFormula *formula;
+  Int_t i, size;
+
+  fBitNumber = GetInt("BitNumber", 0);
+
+  fDeltaR = GetDouble("DeltaR", 0.5);
+
+  fClassifier->fPTMin = GetDouble("PartonPTMin", 1.0);
+  fClassifier->fEtaMax = GetDouble("PartonEtaMax", 2.5);
+
+  // read efficiency formulas
+  param = GetParam("EfficiencyFormula");
+  size = param.GetSize();
+  
+  fEfficiencyMap.clear();
+  for(i = 0; i < size/2; ++i)
+  {
+    formula = new DelphesFormula;
+    formula->Compile(param[i*2 + 1].GetString());
+
+    fEfficiencyMap[param[i*2].GetInt()] = formula;
+  }
+
+  // set default efficiency formula
+  itEfficiencyMap = fEfficiencyMap.find(0);
+  if(itEfficiencyMap == fEfficiencyMap.end())
+  {
+    formula = new DelphesFormula;
+    formula->Compile("0.0");
+
+    fEfficiencyMap[0] = formula;
+  }
+
+  // import input array(s)
+
+  fPartonInputArray = ImportArray(GetString("PartonInputArray", "Delphes/partons"));
+  fItPartonInputArray = fPartonInputArray->MakeIterator();
+
+  fFilter = new ExRootFilter(fPartonInputArray);
+  
+  fJetInputArray = ImportArray(GetString("JetInputArray", "FastJetFinder/jets"));
+  fItJetInputArray = fJetInputArray->MakeIterator();
+}
+
+//------------------------------------------------------------------------------
+
+void BTagging::Finish()
+{
+  map< Int_t, DelphesFormula * >::iterator itEfficiencyMap;
+  DelphesFormula *formula;
+
+  if(fFilter) delete fFilter;
+  if(fItJetInputArray) delete fItJetInputArray;
+  if(fItPartonInputArray) delete fItPartonInputArray;
+
+  for(itEfficiencyMap = fEfficiencyMap.begin(); itEfficiencyMap != fEfficiencyMap.end(); ++itEfficiencyMap)
+  {
+    formula = itEfficiencyMap->second;
+    if(formula) delete formula;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void BTagging::Process()
+{
+  Candidate *jet, *parton;
+  Double_t pt, eta, phi;
+  TObjArray *partonArray;
+  map< Int_t, DelphesFormula * >::iterator itEfficiencyMap;
+  DelphesFormula *formula;
+  Int_t pdgCode, pdgCodeMax;
+
+  // select quark and gluons
+  fFilter->Reset();
+  partonArray = fFilter->GetSubArray(fClassifier, 0);
+  
+  if(partonArray == 0) return;
+
+  TIter itPartonArray(partonArray);
+  
+  // loop over all input jets
+  fItJetInputArray->Reset();
+  while((jet = static_cast<Candidate*>(fItJetInputArray->Next())))
+  {
+    const TLorentzVector &jetMomentum = jet->Momentum;
+    pdgCodeMax = -1;
+    eta = jetMomentum.Eta();
+    phi = jetMomentum.Phi();
+    pt = jetMomentum.Pt();
+
+    // loop over all input partons
+    itPartonArray.Reset();
+    while((parton = static_cast<Candidate*>(itPartonArray.Next())))
+    {
+      pdgCode = TMath::Abs(parton->PID);
+      if(pdgCode == 21) pdgCode = 0;
+      if(jetMomentum.DeltaR(parton->Momentum) <= fDeltaR)
+      {
+        if(pdgCodeMax < pdgCode) pdgCodeMax = pdgCode;
+      }
+    }
+    if(pdgCodeMax == 0) pdgCodeMax = 21;
+    if(pdgCodeMax == -1) pdgCodeMax = 0;
+
+    // find an efficency formula
+    itEfficiencyMap = fEfficiencyMap.find(pdgCodeMax);
+    if(itEfficiencyMap == fEfficiencyMap.end())
+    {
+      itEfficiencyMap = fEfficiencyMap.find(0);
+    }
+    formula = itEfficiencyMap->second;
+
+    // apply an efficency formula
+    jet->BTag |= (gRandom->Uniform() <= formula->Eval(pt, eta)) << fBitNumber;
+  }
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/BTagging.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/BTagging.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/BTagging.h	(revision 5)
@@ -0,0 +1,62 @@
+#ifndef BTagging_h
+#define BTagging_h
+
+/** \class BTagging
+ *
+ *  Determines origin of jet,
+ *  applies b-tagging efficiency (miss identification rate) formulas
+ *  and sets b-tagging flags 
+ *
+ *  $Date: 2013-04-26 12:39:14 +0200 (Fri, 26 Apr 2013) $
+ *  $Revision: 1099 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+#include <map>
+
+class TObjArray;
+class DelphesFormula;
+
+class ExRootFilter;
+class BTaggingPartonClassifier;
+
+class BTagging: public DelphesModule
+{
+public:
+
+  BTagging();
+  ~BTagging();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  Int_t fBitNumber;
+
+  Double_t fDeltaR;
+
+  std::map< Int_t, DelphesFormula * > fEfficiencyMap; //!
+  
+  BTaggingPartonClassifier *fClassifier; //!
+  
+  ExRootFilter *fFilter;
+
+  TIterator *fItPartonInputArray; //!
+  
+  TIterator *fItJetInputArray; //!
+
+  const TObjArray *fPartonInputArray; //!
+  
+  const TObjArray *fJetInputArray; //!
+
+  ClassDef(BTagging, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/Calorimeter.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/Calorimeter.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/Calorimeter.cc	(revision 5)
@@ -0,0 +1,469 @@
+
+/** \class Calorimeter
+ *
+ *  Fills calorimeter towers, performs calorimeter resolution smearing,
+ *  preselects towers hit by photons and creates energy flow objects.
+ *
+ *  $Date: 2013-04-09 18:05:58 +0200 (Tue, 09 Apr 2013) $
+ *  $Revision: 1086 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/Calorimeter.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm>
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+Calorimeter::Calorimeter() :
+  fECalResolutionFormula(0), fHCalResolutionFormula(0),
+  fItParticleInputArray(0), fItTrackInputArray(0),
+  fTowerTrackArray(0), fItTowerTrackArray(0),
+  fTowerPhotonArray(0), fItTowerPhotonArray(0)
+{
+  fECalResolutionFormula = new DelphesFormula;
+  fHCalResolutionFormula = new DelphesFormula;
+  fTowerTrackArray = new TObjArray;
+  fItTowerTrackArray = fTowerTrackArray->MakeIterator();
+  fTowerPhotonArray = new TObjArray;
+  fItTowerPhotonArray = fTowerPhotonArray->MakeIterator();
+}
+
+//------------------------------------------------------------------------------
+
+Calorimeter::~Calorimeter()
+{
+  if(fECalResolutionFormula) delete fECalResolutionFormula;
+  if(fHCalResolutionFormula) delete fHCalResolutionFormula;
+  if(fTowerTrackArray) delete fTowerTrackArray;
+  if(fItTowerTrackArray) delete fItTowerTrackArray;
+  if(fTowerPhotonArray) delete fTowerPhotonArray;
+  if(fItTowerPhotonArray) delete fItTowerPhotonArray;
+}
+
+//------------------------------------------------------------------------------
+
+void Calorimeter::Init()
+{
+  ExRootConfParam param, paramEtaBins, paramPhiBins, paramFractions;
+  Long_t i, j, k, size, sizeEtaBins, sizePhiBins, sizeFractions;
+  Double_t ecalFraction, hcalFraction;
+  TBinMap::iterator itEtaBin;
+  set< Double_t >::iterator itPhiBin;
+  vector< Double_t > *phiBins;
+
+  // read eta and phi bins
+  param = GetParam("EtaPhiBins");
+  size = param.GetSize();
+  fBinMap.clear();
+  fEtaBins.clear();
+  fPhiBins.clear();
+  for(i = 0; i < size/2; ++i)
+  {
+    paramEtaBins = param[i*2];
+    sizeEtaBins = paramEtaBins.GetSize();
+    paramPhiBins = param[i*2 + 1];
+    sizePhiBins = paramPhiBins.GetSize();
+
+    for(j = 0; j < sizeEtaBins; ++j)
+    {
+      for(k = 0; k < sizePhiBins; ++k)
+      {
+        fBinMap[paramEtaBins[j].GetDouble()].insert(paramPhiBins[k].GetDouble());
+      }
+    }
+  }
+
+  // for better performance we transform map of sets to parallel vectors:
+  // vector< double > and vector< vector< double >* >
+  for(itEtaBin = fBinMap.begin(); itEtaBin != fBinMap.end(); ++itEtaBin)
+  {
+    fEtaBins.push_back(itEtaBin->first);
+    phiBins = new vector< double >(itEtaBin->second.size());
+    fPhiBins.push_back(phiBins);
+    phiBins->clear();
+    for(itPhiBin = itEtaBin->second.begin(); itPhiBin != itEtaBin->second.end(); ++itPhiBin)
+    {
+      phiBins->push_back(*itPhiBin);
+    }
+  }
+
+  // read energy fractions for different particles
+  param = GetParam("EnergyFraction");
+  size = param.GetSize();
+
+  // set default energy fractions values
+  fFractionMap.clear();
+  fFractionMap[0] = make_pair(0.0, 1.0);
+
+  for(i = 0; i < size/2; ++i)
+  {
+    paramFractions = param[i*2 + 1];
+    sizeFractions = paramFractions.GetSize();
+
+    ecalFraction = paramFractions[0].GetDouble();
+    hcalFraction = paramFractions[1].GetDouble();
+
+    fFractionMap[param[i*2].GetInt()] = make_pair(ecalFraction, hcalFraction);
+  }
+/*
+  TFractionMap::iterator itFractionMap;
+  for(itFractionMap = fFractionMap.begin(); itFractionMap != fFractionMap.end(); ++itFractionMap)
+  {
+    cout << itFractionMap->first << "   " << itFractionMap->second.first  << "   " << itFractionMap->second.second << endl;
+  }
+*/
+  // read resolution formulas
+  fECalResolutionFormula->Compile(GetString("ECalResolutionFormula", "0"));
+  fHCalResolutionFormula->Compile(GetString("HCalResolutionFormula", "0"));
+
+  // import array with output from other modules
+  fParticleInputArray = ImportArray(GetString("ParticleInputArray", "ParticlePropagator/particles"));
+  fItParticleInputArray = fParticleInputArray->MakeIterator();
+
+  fTrackInputArray = ImportArray(GetString("TrackInputArray", "ParticlePropagator/tracks"));
+  fItTrackInputArray = fTrackInputArray->MakeIterator();
+
+  // create output arrays
+  fTowerOutputArray = ExportArray(GetString("TowerOutputArray", "towers"));
+  fPhotonOutputArray = ExportArray(GetString("PhotonOutputArray", "photons"));
+
+  fEFlowTrackOutputArray = ExportArray(GetString("EFlowTrackOutputArray", "eflowTracks"));
+  fEFlowTowerOutputArray = ExportArray(GetString("EFlowTowerOutputArray", "eflowTowers"));
+}
+
+//------------------------------------------------------------------------------
+
+void Calorimeter::Finish()
+{
+  vector< vector< Double_t>* >::iterator itPhiBin;
+  if(fItParticleInputArray) delete fItParticleInputArray;
+  if(fItTrackInputArray) delete fItTrackInputArray;
+  for(itPhiBin = fPhiBins.begin(); itPhiBin != fPhiBins.end(); ++itPhiBin)
+  {
+    delete *itPhiBin;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void Calorimeter::Process()
+{
+  Candidate *particle, *track;
+  TLorentzVector position, momentum;
+  Short_t etaBin, phiBin, flags;
+  Int_t number;
+  Long64_t towerHit, towerEtaPhi, hitEtaPhi;
+  Double_t ecalFraction, hcalFraction;
+  Double_t ecalEnergy, hcalEnergy;
+  Int_t pdgCode;
+
+  TFractionMap::iterator itFractionMap;
+
+  vector< Double_t >::iterator itEtaBin;
+  vector< Double_t >::iterator itPhiBin;
+  vector< Double_t > *phiBins;
+
+  vector< Long64_t >::iterator itTowerHits;
+
+  DelphesFactory *factory = GetFactory();
+  fTowerHits.clear();
+  fECalFractions.clear();
+  fHCalFractions.clear();
+
+  // loop over all particles
+  fItParticleInputArray->Reset();
+  number = -1;
+  while((particle = static_cast<Candidate*>(fItParticleInputArray->Next())))
+  {
+    const TLorentzVector &particlePosition = particle->Position;
+    ++number;
+
+    pdgCode = TMath::Abs(particle->PID);
+
+    itFractionMap = fFractionMap.find(pdgCode);
+    if(itFractionMap == fFractionMap.end())
+    {
+      itFractionMap = fFractionMap.find(0);
+    }
+
+    ecalFraction = itFractionMap->second.first;
+    hcalFraction = itFractionMap->second.second;
+
+    fECalFractions.push_back(ecalFraction);
+    fHCalFractions.push_back(hcalFraction);
+
+    if(ecalFraction < 1.0E-9 && hcalFraction < 1.0E-9) continue;
+
+    // find eta bin [1, fEtaBins.size - 1]
+    itEtaBin = lower_bound(fEtaBins.begin(), fEtaBins.end(), particlePosition.Eta());
+    if(itEtaBin == fEtaBins.begin() || itEtaBin == fEtaBins.end()) continue;
+    etaBin = distance(fEtaBins.begin(), itEtaBin);
+
+    // phi bins for given eta bin
+    phiBins = fPhiBins[etaBin];
+
+    // find phi bin [1, phiBins.size - 1]
+    itPhiBin = lower_bound(phiBins->begin(), phiBins->end(), particlePosition.Phi());
+    if(itPhiBin == phiBins->begin() || itPhiBin == phiBins->end()) continue;
+    phiBin = distance(phiBins->begin(), itPhiBin);
+
+    flags = (particle->Charge == 0);
+    flags |= (pdgCode == 22) << 1;
+    flags |= (pdgCode == 11) << 2;
+
+    // make tower hit {16-bits for eta bin number, 16-bits for phi bin number, 8-bits for flags, 24-bits for particle number}
+    towerHit = (Long64_t(etaBin) << 48) | (Long64_t(phiBin) << 32) | (Long64_t(flags) << 24) | Long64_t(number);
+
+    fTowerHits.push_back(towerHit);
+  }
+
+  // loop over all tracks
+  fItTrackInputArray->Reset();
+  number = -1;
+  while((track = static_cast<Candidate*>(fItTrackInputArray->Next())))
+  {
+    const TLorentzVector &trackPosition = track->Position;
+    ++number;
+
+    // find eta bin [1, fEtaBins.size - 1]
+    itEtaBin = lower_bound(fEtaBins.begin(), fEtaBins.end(), trackPosition.Eta());
+    if(itEtaBin == fEtaBins.begin() || itEtaBin == fEtaBins.end()) continue;
+    etaBin = distance(fEtaBins.begin(), itEtaBin);
+
+    // phi bins for given eta bin
+    phiBins = fPhiBins[etaBin];
+
+    // find phi bin [1, phiBins.size - 1]
+    itPhiBin = lower_bound(phiBins->begin(), phiBins->end(), trackPosition.Phi());
+    if(itPhiBin == phiBins->begin() || itPhiBin == phiBins->end()) continue;
+    phiBin = distance(phiBins->begin(), itPhiBin);
+
+    // make tower hit {16-bits for eta bin number, 16-bits for phi bin number, 8-bits for flags, 24-bits for track number}
+    towerHit = (Long64_t(etaBin) << 48) | (Long64_t(phiBin) << 32) | (Long64_t(1) << 27) | Long64_t(number);
+
+    fTowerHits.push_back(towerHit);
+  }
+
+  // all hits are sorted first by eta bin number, then by phi bin number,
+  // then by flags and then by particle or track number
+  sort(fTowerHits.begin(), fTowerHits.end());
+
+  // loop over all hits
+  towerEtaPhi = 0;
+  fTower = 0;
+  for(itTowerHits = fTowerHits.begin(); itTowerHits != fTowerHits.end(); ++itTowerHits)
+  {
+    towerHit = (*itTowerHits);
+    flags = (towerHit >> 24) & 0x00000000000000FFLL;
+    number = (towerHit) & 0x0000000000FFFFFFLL;
+    hitEtaPhi = towerHit >> 32;
+
+    if(towerEtaPhi != hitEtaPhi)
+    {
+      // switch to next tower
+      towerEtaPhi = hitEtaPhi;
+
+      // finalize previous tower
+      FinalizeTower();
+
+      // create new tower
+      fTower = factory->NewCandidate();
+
+      phiBin = (towerHit >> 32) & 0x000000000000FFFFLL;
+      etaBin = (towerHit >> 48) & 0x000000000000FFFFLL;
+
+      // phi bins for given eta bin
+      phiBins = fPhiBins[etaBin];
+
+      // calculate eta and phi of the tower's center
+      fTowerEta = 0.5*(fEtaBins[etaBin - 1] + fEtaBins[etaBin]);
+      fTowerPhi = 0.5*((*phiBins)[phiBin - 1] + (*phiBins)[phiBin]);
+
+      fTowerEdges[0] = fEtaBins[etaBin - 1];
+      fTowerEdges[1] = fEtaBins[etaBin];
+      fTowerEdges[2] = (*phiBins)[phiBin - 1];
+      fTowerEdges[3] = (*phiBins)[phiBin];
+
+      fTowerECalEnergy = 0.0;
+      fTowerHCalEnergy = 0.0;
+
+      fTowerECalNeutralEnergy = 0.0;
+      fTowerHCalNeutralEnergy = 0.0;
+
+      fTowerNeutralHits = 0;
+      fTowerPhotonHits = 0;
+      fTowerElectronHits = 0;
+      fTowerTrackHits = 0;
+      fTowerAllHits = 0;
+
+      fTowerTrackArray->Clear();
+      fTowerPhotonArray->Clear();
+    }
+
+    // check for track hits
+    if(flags & 8)
+    {
+      ++fTowerTrackHits;
+      track = static_cast<Candidate*>(fTrackInputArray->At(number));
+      fTowerTrackArray->Add(track);
+      continue;
+    }
+
+    particle = static_cast<Candidate*>(fParticleInputArray->At(number));
+    momentum = particle->Momentum;
+
+    // fill current tower
+    ecalEnergy = momentum.E() * fECalFractions[number];
+    hcalEnergy = momentum.E() * fHCalFractions[number];
+
+    fTowerECalEnergy += ecalEnergy;
+    fTowerHCalEnergy += hcalEnergy;
+
+    ++fTowerAllHits;
+    fTower->AddCandidate(particle);
+
+    // check for neutral hits in current tower
+    if(flags & 1) ++fTowerNeutralHits;
+
+    // check for photon hits in current tower
+    if(flags & 2)
+    {
+      ++fTowerPhotonHits;
+      fTowerPhotonArray->Add(particle);
+    }
+
+    // check for electron hits in current tower
+    if(flags & 4) ++fTowerElectronHits;
+  }
+
+  // finalize last tower
+  FinalizeTower();
+}
+
+//------------------------------------------------------------------------------
+
+void Calorimeter::FinalizeTower()
+{
+  Candidate *particle, *track, *tower;
+  Double_t energy, pt, eta, phi;
+  Double_t ecalEnergy, hcalEnergy;
+
+  if(!fTower) return;
+
+  ecalEnergy = gRandom->Gaus(fTowerECalEnergy, fECalResolutionFormula->Eval(0.0, fTowerEta, 0.0, fTowerECalEnergy));
+  if(ecalEnergy < 0.0) ecalEnergy = 0.0;
+
+  hcalEnergy = gRandom->Gaus(fTowerHCalEnergy, fHCalResolutionFormula->Eval(0.0, fTowerEta, 0.0, fTowerHCalEnergy));
+  if(hcalEnergy < 0.0) hcalEnergy = 0.0;
+
+  energy = ecalEnergy + hcalEnergy;
+
+  // eta = fTowerEta;
+  // phi = fTowerPhi;
+
+  eta = gRandom->Uniform(fTowerEdges[0], fTowerEdges[1]);
+  phi = gRandom->Uniform(fTowerEdges[2], fTowerEdges[3]);
+
+  pt = energy / TMath::CosH(eta);
+
+  fTower->Position.SetPtEtaPhiE(1.0, eta, phi, 0.0);
+  fTower->Momentum.SetPtEtaPhiE(pt, eta, phi, energy);
+  fTower->Eem = ecalEnergy;
+  fTower->Ehad = hcalEnergy;
+
+  fTower->Edges[0] = fTowerEdges[0];
+  fTower->Edges[1] = fTowerEdges[1];
+  fTower->Edges[2] = fTowerEdges[2];
+  fTower->Edges[3] = fTowerEdges[3];
+
+  // fill calorimeter towers and photon candidates
+  if(energy > 0.0)
+  {
+    if((fTowerPhotonHits > 0 || fTowerElectronHits > 0) &&
+        fTowerTrackHits == 0)
+    {
+      fPhotonOutputArray->Add(fTower);
+    }
+
+    fTowerOutputArray->Add(fTower);
+  }
+
+  // fill energy flow candidates
+  if(fTowerTrackHits == fTowerAllHits)
+  {
+    fItTowerTrackArray->Reset();
+    while((track = static_cast<Candidate*>(fItTowerTrackArray->Next())))
+    {
+      fEFlowTrackOutputArray->Add(track);
+    }
+  }
+  else if(fTowerTrackHits > 0 &&
+          fTowerElectronHits == 0 &&
+          fTowerPhotonHits + fTowerTrackHits == fTowerAllHits)
+  {
+    fItTowerTrackArray->Reset();
+    while((track = static_cast<Candidate*>(fItTowerTrackArray->Next())))
+    {
+      fEFlowTrackOutputArray->Add(track);
+    }
+
+    if(ecalEnergy > 0.0)
+    {
+      DelphesFactory *factory = GetFactory();
+
+      // create new tower
+      tower = factory->NewCandidate();
+
+      fItTowerPhotonArray->Reset();
+      while((particle = static_cast<Candidate*>(fItTowerPhotonArray->Next())))
+      {
+        tower->AddCandidate(particle);
+      }
+
+      pt = ecalEnergy / TMath::CosH(eta);
+
+      tower->Position.SetPtEtaPhiE(1.0, eta, phi, 0.0);
+      tower->Momentum.SetPtEtaPhiE(pt, eta, phi, ecalEnergy);
+      tower->Eem = ecalEnergy;
+      tower->Ehad = 0.0;
+
+      tower->Edges[0] = fTowerEdges[0];
+      tower->Edges[1] = fTowerEdges[1];
+      tower->Edges[2] = fTowerEdges[2];
+      tower->Edges[3] = fTowerEdges[3];
+
+      fEFlowTowerOutputArray->Add(tower);
+    }
+  }
+  else if(energy > 0.0)
+  {
+    fEFlowTowerOutputArray->Add(fTower);
+  }
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/Calorimeter.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/Calorimeter.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/Calorimeter.h	(revision 5)
@@ -0,0 +1,86 @@
+#ifndef Calorimeter_h
+#define Calorimeter_h
+
+/** \class Calorimeter
+ *
+ *  Fills calorimeter towers, performs calorimeter resolution smearing,
+ *  preselects towers hit by photons and creates energy flow objects.
+ *
+ *  $Date: 2013-02-24 00:54:18 +0100 (Sun, 24 Feb 2013) $
+ *  $Revision: 938 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+class TObjArray;
+class DelphesFormula;
+class Candidate;
+
+class Calorimeter: public DelphesModule
+{
+public:
+
+  Calorimeter();
+  ~Calorimeter();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  typedef std::map< Long64_t, std::pair< Double_t, Double_t > > TFractionMap; //!
+  typedef std::map< Double_t, std::set< Double_t > > TBinMap; //!
+
+  Candidate *fTower;
+  Double_t fTowerEta, fTowerPhi, fTowerEdges[4];
+  Double_t fTowerECalEnergy, fTowerHCalEnergy;
+  Double_t fTowerECalNeutralEnergy, fTowerHCalNeutralEnergy;
+  Int_t fTowerNeutralHits, fTowerPhotonHits, fTowerElectronHits, fTowerTrackHits, fTowerAllHits;
+
+  TFractionMap fFractionMap; //!
+  TBinMap fBinMap; //!
+
+  std::vector < Double_t > fEtaBins;
+  std::vector < std::vector < Double_t >* > fPhiBins;
+
+  std::vector < Long64_t > fTowerHits;
+
+  std::vector < Double_t > fECalFractions;
+  std::vector < Double_t > fHCalFractions;
+
+  DelphesFormula *fECalResolutionFormula; //!
+  DelphesFormula *fHCalResolutionFormula; //!
+
+  TIterator *fItParticleInputArray; //!
+  TIterator *fItTrackInputArray; //!
+
+  const TObjArray *fParticleInputArray; //!
+  const TObjArray *fTrackInputArray; //!
+
+  TObjArray *fTowerOutputArray; //!
+  TObjArray *fPhotonOutputArray; //!
+
+  TObjArray *fEFlowTrackOutputArray; //!
+  TObjArray *fEFlowTowerOutputArray; //!
+
+  TObjArray *fTowerTrackArray; //!
+  TIterator *fItTowerTrackArray; //!
+
+  TObjArray *fTowerPhotonArray; //!
+  TIterator *fItTowerPhotonArray; //!
+
+  void FinalizeTower();
+  
+  ClassDef(Calorimeter, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/Cloner.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/Cloner.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/Cloner.cc	(revision 5)
@@ -0,0 +1,82 @@
+
+/** \class Clone
+ *
+ *  Clone candidate array
+ *
+ *  $Date: 2013-04-26 12:42:11 +0200 (Fri, 26 Apr 2013) $
+ *  $Revision: 1100 $
+ *
+ *  \author M. Selvaggi - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/Cloner.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include <algorithm>
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+Cloner::Cloner() :
+  fItInputArray(0)
+{
+
+}
+
+//------------------------------------------------------------------------------
+
+Cloner::~Cloner()
+{
+
+}
+
+//------------------------------------------------------------------------------
+
+void Cloner::Init()
+{
+  // import input array(s)
+
+  fInputArray = ImportArray(GetString("InputArray", "FastJetFinder/jets"));
+  fItInputArray = fInputArray->MakeIterator();
+
+  // create output array(s)
+
+  fOutputArray = ExportArray(GetString("OutputArray", "jets"));
+
+}
+
+//------------------------------------------------------------------------------
+
+void Cloner::Finish()
+{
+  if(fItInputArray) delete fItInputArray;
+}
+
+//------------------------------------------------------------------------------
+
+void Cloner::Process()
+{
+  Candidate *candidate;
+ 
+ // loop over all input candidates
+  fItInputArray->Reset();
+  while((candidate = static_cast<Candidate*>(fItInputArray->Next())))
+  {
+    candidate = static_cast<Candidate*>(candidate->Clone());
+    fOutputArray->Add(candidate);
+  }
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/Cloner.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/Cloner.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/Cloner.h	(revision 5)
@@ -0,0 +1,43 @@
+#ifndef Clone_h
+#define Clone_h
+
+/** \class Clone
+ *
+ *  Clone candidate array
+ *
+ *  $Date: 2013-04-26 12:42:11 +0200 (Fri, 26 Apr 2013) $
+ *  $Revision: 1100 $
+ *
+ *  \author M. Selvaggi - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+#include <deque>
+
+class TObjArray;
+class DelphesFormula;
+
+class Cloner: public DelphesModule
+{
+public:
+
+  Cloner();
+  ~Cloner();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  TIterator *fItInputArray; //!
+
+  const TObjArray *fInputArray; //!
+  TObjArray *fOutputArray; //!
+
+  ClassDef(Cloner, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/ConstituentFilter.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/ConstituentFilter.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/ConstituentFilter.cc	(revision 5)
@@ -0,0 +1,157 @@
+
+/** \class ConstituentFilter
+ *
+ *  Drops all input objects that are not constituents of any jet.
+ *
+ *  $Date: 2013-04-05 10:19:17 +0200 (Fri, 05 Apr 2013) $
+ *  $Revision: 1075 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/ConstituentFilter.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm>
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+ConstituentFilter::ConstituentFilter()
+{
+}
+
+//------------------------------------------------------------------------------
+
+ConstituentFilter::~ConstituentFilter()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void ConstituentFilter::Init()
+{
+  ExRootConfParam param;
+  Long_t i, size;
+  const TObjArray *array;
+  TIterator *iterator;
+
+  fJetPTMin = GetDouble("JetPTMin", 0.0);
+
+  // import input array(s)
+
+  param = GetParam("JetInputArray");
+  size = param.GetSize();
+  for(i = 0; i < size; ++i)
+  {
+    array = ImportArray(param[i].GetString());
+    iterator = array->MakeIterator();
+
+    fInputList.push_back(iterator);
+  }
+
+  param = GetParam("ConstituentInputArray");
+  size = param.GetSize();
+  for(i = 0; i < size/2; ++i)
+  {
+    array = ImportArray(param[i*2].GetString());
+    iterator = array->MakeIterator();
+
+    fInputMap[iterator] = ExportArray(param[i*2 + 1].GetString());;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void ConstituentFilter::Finish()
+{
+  map< TIterator *, TObjArray * >::iterator itInputMap;
+  vector< TIterator * >::iterator itInputList;
+  TIterator *iterator;
+
+  for(itInputList = fInputList.begin(); itInputList != fInputList.end(); ++itInputList)
+  {
+    iterator = *itInputList;
+    if(iterator) delete iterator;
+  }
+
+  for(itInputMap = fInputMap.begin(); itInputMap != fInputMap.end(); ++itInputMap)
+  {
+    iterator = itInputMap->first;
+    if(iterator) delete iterator;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void ConstituentFilter::Process()
+{
+  Candidate *jet, *constituent;
+  map< TIterator *, TObjArray * >::iterator itInputMap;
+  vector< TIterator * >::iterator itInputList;
+  TIterator *iterator;
+  TObjArray *array;
+
+  // loop over all jet input arrays
+  for(itInputList = fInputList.begin(); itInputList != fInputList.end(); ++itInputList)
+  {
+    iterator = *itInputList;
+
+    // loop over all jets
+    iterator->Reset();
+    while((jet = static_cast<Candidate*>(iterator->Next())))
+    {
+      TIter itConstituents(jet->GetCandidates());
+
+      if(jet->Momentum.Pt() <= fJetPTMin) continue;
+
+      // loop over all constituents
+      while((constituent = static_cast<Candidate*>(itConstituents.Next())))
+      {
+        // set the IsConstituent flag
+        constituent->IsConstituent = 1;
+      }
+    }
+  }
+
+  // loop over all constituent input arrays
+  for(itInputMap = fInputMap.begin(); itInputMap != fInputMap.end(); ++itInputMap)
+  {
+    iterator = itInputMap->first;
+    array = itInputMap->second;
+
+    // loop over all constituents
+    iterator->Reset();
+    while((constituent = static_cast<Candidate*>(iterator->Next())))
+    {
+      // check the IsConstituent flag
+      if(constituent->IsConstituent)
+      {
+        array->Add(constituent);
+      }
+    }
+  }
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/ConstituentFilter.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/ConstituentFilter.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/ConstituentFilter.h	(revision 5)
@@ -0,0 +1,48 @@
+#ifndef ConstituentFilter_h
+#define ConstituentFilter_h
+
+/** \class ConstituentFilter
+ *
+ *  Drops all input objects that are not constituents of any jet.
+ *
+ *  $Date: 2013-04-05 10:19:17 +0200 (Fri, 05 Apr 2013) $
+ *  $Revision: 1075 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+#include <vector>
+#include <map>
+
+class TIterator;
+class TObjArray;
+
+class ConstituentFilter: public DelphesModule
+{
+public:
+
+  ConstituentFilter();
+  ~ConstituentFilter();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  Double_t fJetPTMin;
+
+  std::vector< TIterator * > fInputList; //!
+
+  std::map< TIterator *, TObjArray * > fInputMap; //!
+
+  TObjArray *fOutputArray; //!
+
+  ClassDef(ConstituentFilter, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/Delphes.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/Delphes.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/Delphes.cc	(revision 5)
@@ -0,0 +1,141 @@
+
+/** \class Delphes
+ *
+ *  Main Delphes module.
+ *  Controls execution of all other modules.
+ *
+ *  $Date: 2012-11-18 13:59:48 +0100 (Sun, 18 Nov 2012) $
+ *  $Revision: 813 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/Delphes.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+#include "ExRootAnalysis/ExRootConfReader.h"
+#include "ExRootAnalysis/ExRootTreeWriter.h"
+
+#include "TROOT.h"
+#include "TMath.h"
+#include "TFolder.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm> 
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+#include <string.h>
+#include <stdio.h>
+
+using namespace std;
+
+Delphes::Delphes(const char *name) :
+  fFactory(0)
+{
+  TFolder *folder = new TFolder(name, "");
+  fFactory = new DelphesFactory("ObjectFactory");
+
+  SetName(name);
+  SetFolder(folder);
+
+  folder->Add(this);
+  folder->Add(fFactory);
+
+  gROOT->GetListOfBrowsables()->Add(folder);
+}
+
+//------------------------------------------------------------------------------
+
+Delphes::~Delphes()
+{
+  if(fFactory) delete fFactory;
+  TFolder *folder = GetFolder();
+  if(folder)
+  {
+    folder->Clear();
+    delete folder;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void Delphes::Clear()
+{
+  if(fFactory) fFactory->Clear();
+}
+
+//------------------------------------------------------------------------------
+
+void Delphes::SetTreeWriter(ExRootTreeWriter *treeWriter)
+{
+  treeWriter->SetName("TreeWriter");
+  GetFolder()->Add(treeWriter);
+}
+
+//------------------------------------------------------------------------------
+
+void Delphes::Init()
+{
+  stringstream message;
+  ExRootConfReader *confReader = GetConfReader();
+  confReader->SetName("ConfReader");
+  GetFolder()->Add(confReader);
+
+  TString name;
+  ExRootTask *task;
+  const ExRootConfReader::ExRootTaskMap *modules = confReader->GetModules();
+  ExRootConfReader::ExRootTaskMap::const_iterator itModules;
+
+  ExRootConfParam param = confReader->GetParam("::ExecutionPath");
+  Long_t i, size = param.GetSize();
+
+  for(i = 0; i < size; ++i)
+  {
+    name = param[i].GetString();
+    itModules = modules->find(name);
+    if(itModules != modules->end())
+    {
+      task = NewTask(itModules->second, itModules->first);
+      if(task)
+      {
+        task->SetFolder(GetFolder());
+        Add(task);
+      }
+    }
+    else
+    {
+      message << "module '" << name;
+      message << "' is specified in ExecutionPath but not configured.";
+      throw runtime_error(message.str());
+    }
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void Delphes::Process()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void Delphes::Finish()
+{
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/Delphes.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/Delphes.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/Delphes.h	(revision 5)
@@ -0,0 +1,51 @@
+#ifndef Delphes_h
+#define Delphes_h
+
+/** \class Delphes
+ *
+ *  Main Delphes module.
+ *  Controls execution of all other modules.
+ *
+ *  $Date: 2012-11-18 13:59:48 +0100 (Sun, 18 Nov 2012) $
+ *  $Revision: 813 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+class TFolder;
+class TObjArray;
+
+class ExRootTreeWriter;
+
+class DelphesFactory;
+
+class Delphes: public DelphesModule
+{
+public:
+
+  Delphes(const char *name = "Delphes");
+  ~Delphes();
+
+  void SetTreeWriter(ExRootTreeWriter *treeWriter);
+  
+  DelphesFactory *GetFactory() const { return fFactory; }
+
+  void Clear();
+
+  virtual void Init();
+  virtual void Process();
+  virtual void Finish();
+
+private:
+
+  DelphesFactory *fFactory;
+
+  ClassDef(Delphes, 1)
+};
+
+#endif /* Delphes_h */
+
Index: trunk/Delphes/Delphes-3.0.9/modules/Efficiency.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/Efficiency.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/Efficiency.cc	(revision 5)
@@ -0,0 +1,102 @@
+
+/** \class Efficiency
+ *
+ *  Selects candidates from the InputArray according to the efficiency formula.
+ *
+ *  $Date: 2013-02-12 14:57:44 +0100 (Tue, 12 Feb 2013) $
+ *  $Revision: 905 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/Efficiency.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm> 
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+Efficiency::Efficiency() :
+  fFormula(0), fItInputArray(0)
+{
+  fFormula = new DelphesFormula;
+}
+
+//------------------------------------------------------------------------------
+
+Efficiency::~Efficiency()
+{
+  if(fFormula) delete fFormula;
+}
+
+//------------------------------------------------------------------------------
+
+void Efficiency::Init()
+{
+  // read efficiency formula
+
+  fFormula->Compile(GetString("EfficiencyFormula", "1.0"));
+
+  // import input array
+
+  fInputArray = ImportArray(GetString("InputArray", "ParticlePropagator/stableParticles"));
+  fItInputArray = fInputArray->MakeIterator();
+
+  // create output array
+
+  fOutputArray = ExportArray(GetString("OutputArray", "stableParticles"));
+}
+
+//------------------------------------------------------------------------------
+
+void Efficiency::Finish()
+{
+  if(fItInputArray) delete fItInputArray;
+}
+
+//------------------------------------------------------------------------------
+
+void Efficiency::Process()
+{ 
+  Candidate *candidate;
+  Double_t pt, eta, phi;
+
+  fItInputArray->Reset();
+  while((candidate = static_cast<Candidate*>(fItInputArray->Next())))
+  {
+    const TLorentzVector &candidatePosition = candidate->Position;
+    const TLorentzVector &candidateMomentum = candidate->Momentum;
+    eta = candidatePosition.Eta();
+    phi = candidatePosition.Phi();
+    pt = candidateMomentum.Pt();
+
+    // apply an efficency formula
+    if(gRandom->Uniform() > fFormula->Eval(pt, eta)) continue;
+    
+    fOutputArray->Add(candidate);
+  }
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/Efficiency.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/Efficiency.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/Efficiency.h	(revision 5)
@@ -0,0 +1,46 @@
+#ifndef Efficiency_h
+#define Efficiency_h
+
+/** \class Efficiency
+ *
+ *  Selects candidates from the InputArray according to the efficiency formula.
+ *
+ *  $Date: 2013-02-12 14:57:44 +0100 (Tue, 12 Feb 2013) $
+ *  $Revision: 905 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+class TIterator;
+class TObjArray;
+class DelphesFormula;
+
+class Efficiency: public DelphesModule
+{
+public:
+
+  Efficiency();
+  ~Efficiency();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  DelphesFormula *fFormula; //!
+
+  TIterator *fItInputArray; //!
+
+  const TObjArray *fInputArray; //!
+
+  TObjArray *fOutputArray; //!
+
+  ClassDef(Efficiency, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/EnergySmearing.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/EnergySmearing.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/EnergySmearing.cc	(revision 5)
@@ -0,0 +1,111 @@
+
+/** \class EnergySmearing
+ *
+ *  Performs energy resolution smearing.
+ *
+ *  $Date: 2013-02-22 12:03:12 +0100 (Fri, 22 Feb 2013) $
+ *  $Revision: 927 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/EnergySmearing.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm> 
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+EnergySmearing::EnergySmearing() :
+  fFormula(0), fItInputArray(0)
+{
+  fFormula = new DelphesFormula;
+}
+
+//------------------------------------------------------------------------------
+
+EnergySmearing::~EnergySmearing()
+{
+  if(fFormula) delete fFormula;
+}
+
+//------------------------------------------------------------------------------
+
+void EnergySmearing::Init()
+{
+  // read resolution formula
+
+  fFormula->Compile(GetString("ResolutionFormula", "0.0"));
+
+  // import input array
+
+  fInputArray = ImportArray(GetString("InputArray", "ParticlePropagator/stableParticles"));
+  fItInputArray = fInputArray->MakeIterator();
+
+  // create output array
+
+  fOutputArray = ExportArray(GetString("OutputArray", "stableParticles"));
+}
+
+//------------------------------------------------------------------------------
+
+void EnergySmearing::Finish()
+{  
+  if(fItInputArray) delete fItInputArray;
+}
+
+//------------------------------------------------------------------------------
+
+void EnergySmearing::Process()
+{
+  Candidate *candidate, *mother;
+  Double_t energy, eta, phi;
+
+  fItInputArray->Reset();
+  while((candidate = static_cast<Candidate*>(fItInputArray->Next())))
+  {
+    const TLorentzVector &candidatePosition = candidate->Position;
+    const TLorentzVector &candidateMomentum = candidate->Momentum;
+    eta = candidatePosition.Eta();
+    phi = candidatePosition.Phi();
+    energy = candidateMomentum.E();
+ 
+    // apply smearing formula
+    energy = gRandom->Gaus(energy, fFormula->Eval(0.0, eta, 0.0, energy));
+     
+    if(energy <= 0.0) continue;
+ 
+    mother = candidate;
+    candidate = static_cast<Candidate*>(candidate->Clone());
+    eta = candidateMomentum.Eta();
+    phi = candidateMomentum.Phi();
+    candidate->Momentum.SetPtEtaPhiE(energy/TMath::CosH(eta), eta, phi, energy);
+    candidate->AddCandidate(mother);
+ 
+    fOutputArray->Add(candidate);
+  }
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/EnergySmearing.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/EnergySmearing.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/EnergySmearing.h	(revision 5)
@@ -0,0 +1,46 @@
+#ifndef EnergySmearing_h
+#define EnergySmearing_h
+
+/** \class EnergySmearing
+ *
+ *  Performs energy resolution smearing.
+ *
+ *  $Date: 2013-02-12 14:57:44 +0100 (Tue, 12 Feb 2013) $
+ *  $Revision: 905 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+class TIterator;
+class TObjArray;
+class DelphesFormula;
+
+class EnergySmearing: public DelphesModule
+{
+public:
+
+  EnergySmearing();
+  ~EnergySmearing();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  DelphesFormula *fFormula; //!
+
+  TIterator *fItInputArray; //!
+
+  const TObjArray *fInputArray; //!
+  
+  TObjArray *fOutputArray; //!
+
+  ClassDef(EnergySmearing, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/ExampleModule.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/ExampleModule.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/ExampleModule.cc	(revision 5)
@@ -0,0 +1,116 @@
+
+/** \class ExampleModule
+ *
+ *  Selects candidates from the InputArray according to the efficiency formula.
+ *
+ *  $Date: 2013-02-12 14:57:44 +0100 (Tue, 12 Feb 2013) $
+ *  $Revision: 905 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/ExampleModule.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm> 
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+ExampleModule::ExampleModule() :
+  fFormula(0), fItInputArray(0)
+{
+  fFormula = new DelphesFormula;
+}
+
+//------------------------------------------------------------------------------
+
+ExampleModule::~ExampleModule()
+{
+  if(fFormula) delete fFormula;
+}
+
+//------------------------------------------------------------------------------
+
+void ExampleModule::Init()
+{
+  // read parameters
+
+  fIntParam = GetInt("IntParam", 10);
+
+  fDoubleParam = GetDouble("DoubleParam", 1.0);
+
+  fFormula->Compile(GetString("EfficiencyFormula", "0.4"));
+
+  ExRootConfParam param = GetParam("ArrayParam");
+  Long_t i, size;
+  fArrayParam.clear();
+
+  size = param.GetSize();
+  for(i = 0; i < size; ++i)
+  {
+    fArrayParam.push_back(param[i].GetDouble());
+  }
+  
+  // import input array(s)
+
+  fInputArray = ImportArray(GetString("InputArray", "FastJetFinder/jets"));
+  fItInputArray = fInputArray->MakeIterator();
+
+  // create output array(s)
+
+  fOutputArray = ExportArray(GetString("OutputArray", "jets"));
+
+}
+
+//------------------------------------------------------------------------------
+
+void ExampleModule::Finish()
+{
+  if(fItInputArray) delete fItInputArray;
+}
+
+//------------------------------------------------------------------------------
+
+void ExampleModule::Process()
+{
+  Candidate *candidate;
+  TLorentzVector candidatePosition, candidateMomentum;
+
+  // loop over all input candidates
+  fItInputArray->Reset();
+  while((candidate = static_cast<Candidate*>(fItInputArray->Next())))
+  {
+    candidatePosition = candidate->Position;
+    candidateMomentum = candidate->Momentum;
+
+    // apply an efficency formula
+    if(gRandom->Uniform() <= fFormula->Eval(candidateMomentum.Pt(), candidatePosition.Eta()))
+    {
+      fOutputArray->Add(candidate);
+    }
+  }
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/ExampleModule.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/ExampleModule.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/ExampleModule.h	(revision 5)
@@ -0,0 +1,52 @@
+#ifndef ExampleModule_h
+#define ExampleModule_h
+
+/** \class ExampleModule
+ *
+ *  Selects candidates from the InputArray according to the efficiency formula.
+ *
+ *  $Date: 2012-11-18 15:57:08 +0100 (Sun, 18 Nov 2012) $
+ *  $Revision: 814 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+#include <deque>
+
+class TObjArray;
+class DelphesFormula;
+
+class ExampleModule: public DelphesModule
+{
+public:
+
+  ExampleModule();
+  ~ExampleModule();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  Int_t fIntParam;
+  Double_t fDoubleParam;
+  
+  std::deque <Double_t> fArrayParam;
+  
+  DelphesFormula *fFormula; //!
+
+  TIterator *fItInputArray; //!
+
+  const TObjArray *fInputArray; //!
+
+  TObjArray *fOutputArray; //!
+
+  ClassDef(ExampleModule, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/FastJetFinder.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/FastJetFinder.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/FastJetFinder.cc	(revision 5)
@@ -0,0 +1,267 @@
+
+/** \class FastJetFinder
+ *
+ *  Finds jets using FastJet library.
+ *
+ *  $Date: 2013-05-24 01:26:33 +0200 (Fri, 24 May 2013) $
+ *  $Revision: 1122 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/FastJetFinder.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm> 
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/JetDefinition.hh"
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/Selector.hh"
+#include "fastjet/ClusterSequenceArea.hh"
+#include "fastjet/tools/JetMedianBackgroundEstimator.hh"
+
+#include "fastjet/plugins/SISCone/fastjet/SISConePlugin.hh"
+#include "fastjet/plugins/CDFCones/fastjet/CDFMidPointPlugin.hh"
+#include "fastjet/plugins/CDFCones/fastjet/CDFJetCluPlugin.hh"
+
+using namespace std;
+using namespace fastjet;
+
+//------------------------------------------------------------------------------
+
+FastJetFinder::FastJetFinder() :
+  fPlugin(0), fDefinition(0), fAreaDefinition(0), fItInputArray(0)
+{
+
+}
+
+//------------------------------------------------------------------------------
+
+FastJetFinder::~FastJetFinder()
+{
+
+}
+
+//------------------------------------------------------------------------------
+
+void FastJetFinder::Init()
+{
+  JetDefinition::Plugin *plugin = NULL;
+
+  // define algorithm
+
+  fJetAlgorithm = GetInt("JetAlgorithm", 6);
+  fParameterR = GetDouble("ParameterR", 0.5);
+
+  fConeRadius = GetDouble("ConeRadius", 0.5);
+  fSeedThreshold = GetDouble("SeedThreshold", 1.0);
+  fConeAreaFraction = GetDouble("ConeAreaFraction", 1.0);
+  fMaxIterations = GetInt("MaxIterations", 100);
+  fMaxPairSize = GetInt("MaxPairSize", 2);
+  fIratch = GetInt("Iratch", 1);
+  fAdjacencyCut = GetDouble("AdjacencyCut", 2.0);
+  fOverlapThreshold = GetDouble("OverlapThreshold", 0.75);
+
+  fJetPTMin = GetDouble("JetPTMin", 10.0);
+
+  // ---  Jet Area Parameters ---
+  fAreaAlgorithm = GetInt("AreaAlgorithm", 0);
+  fComputeRho = GetBool("ComputeRho", false);
+  fRhoEtaMax = GetDouble("RhoEtaMax", 5.0);
+  // - ghost based areas -
+  fGhostEtaMax = GetDouble("GhostEtaMax", 5.0);
+  fRepeat = GetInt("Repeat", 1);
+  fGhostArea = GetDouble("GhostArea", 0.01);
+  fGridScatter = GetDouble("GridScatter", 1.0);
+  fPtScatter = GetDouble("PtScatter", 0.1);
+  fMeanGhostPt = GetDouble("MeanGhostPt", 1.0E-100);
+  // - voronoi based areas -
+  fEffectiveRfact = GetDouble("EffectiveRfact", 1.0);
+
+  switch(fAreaAlgorithm)
+  {
+    case 1:
+      fAreaDefinition = new fastjet::AreaDefinition(active_area_explicit_ghosts, GhostedAreaSpec(fGhostEtaMax, fRepeat, fGhostArea, fGridScatter, fPtScatter, fMeanGhostPt));
+      break;
+    case 2:
+      fAreaDefinition = new fastjet::AreaDefinition(one_ghost_passive_area, GhostedAreaSpec(fGhostEtaMax, fRepeat, fGhostArea, fGridScatter, fPtScatter, fMeanGhostPt));
+      break;
+    case 3:
+      fAreaDefinition = new fastjet::AreaDefinition(passive_area, GhostedAreaSpec(fGhostEtaMax, fRepeat, fGhostArea, fGridScatter, fPtScatter, fMeanGhostPt));
+      break;
+    case 4:
+      fAreaDefinition = new fastjet::AreaDefinition(VoronoiAreaSpec(fEffectiveRfact));
+      break;
+    case 5:
+      fAreaDefinition = new fastjet::AreaDefinition(active_area, GhostedAreaSpec(fGhostEtaMax, fRepeat, fGhostArea, fGridScatter, fPtScatter, fMeanGhostPt));
+      break;
+    default:
+    case 0:
+      fAreaDefinition = 0;
+      break;
+  }
+
+  switch(fJetAlgorithm)
+  {
+    case 1: 
+      plugin = new fastjet::CDFJetCluPlugin(fSeedThreshold, fConeRadius, fAdjacencyCut, fMaxIterations, fIratch, fOverlapThreshold);
+      fDefinition = new fastjet::JetDefinition(plugin);
+      break;
+    case 2:
+      plugin = new fastjet::CDFMidPointPlugin(fSeedThreshold, fConeRadius, fConeAreaFraction, fMaxPairSize, fMaxIterations, fOverlapThreshold);
+      fDefinition = new fastjet::JetDefinition(plugin);
+      break;
+    case 3:
+      plugin = new fastjet::SISConePlugin(fConeRadius, fOverlapThreshold, fMaxIterations, fJetPTMin);
+      fDefinition = new fastjet::JetDefinition(plugin);
+      break;
+    case 4:
+      fDefinition = new fastjet::JetDefinition(fastjet::kt_algorithm, fParameterR);
+      break;
+    case 5:
+      fDefinition = new fastjet::JetDefinition(fastjet::cambridge_algorithm, fParameterR);
+      break;
+    default:
+    case 6:
+      fDefinition = new fastjet::JetDefinition(fastjet::antikt_algorithm, fParameterR);
+      break;
+  }
+  
+  fPlugin = plugin;
+
+  ClusterSequence::print_banner();
+  
+  // import input array
+
+  fInputArray = ImportArray(GetString("InputArray", "Calorimeter/towers"));
+  fItInputArray = fInputArray->MakeIterator();
+
+  // create output arrays
+
+  fOutputArray = ExportArray(GetString("OutputArray", "jets"));
+  fRhoOutputArray = ExportArray(GetString("RhoOutputArray", "rho"));
+}
+
+//------------------------------------------------------------------------------
+
+void FastJetFinder::Finish()
+{
+  if(fItInputArray) delete fItInputArray;
+  if(fDefinition) delete fDefinition;
+  if(fAreaDefinition) delete fAreaDefinition;
+  if(fPlugin) delete static_cast<JetDefinition::Plugin*>(fPlugin);
+}
+
+//------------------------------------------------------------------------------
+
+void FastJetFinder::Process()
+{
+  Candidate *candidate, *constituent;
+  TLorentzVector momentum;
+  Double_t deta, dphi, detaMax, dphiMax;
+  Int_t number;
+  Double_t rho = 0;
+  PseudoJet jet, area;
+  vector<PseudoJet> inputList, outputList;
+  ClusterSequence *sequence;
+
+  DelphesFactory *factory = GetFactory();
+
+  inputList.clear();
+
+  // loop over input objects
+  fItInputArray->Reset();
+  number = 0;
+  while((candidate = static_cast<Candidate*>(fItInputArray->Next())))
+  {   
+    momentum = candidate->Momentum;
+    jet = PseudoJet(momentum.Px(), momentum.Py(), momentum.Pz(), momentum.E());
+    jet.set_user_index(number);
+    inputList.push_back(jet);
+    ++number;
+  }
+   
+  // construct jets 
+  if(fAreaDefinition)
+  {
+    sequence = new ClusterSequenceArea(inputList, *fDefinition, *fAreaDefinition);
+  }
+  else
+  {
+    sequence = new ClusterSequence(inputList, *fDefinition);
+  } 
+
+  // compute rho and store it
+  if(fComputeRho && fAreaDefinition)
+  {
+    Selector select_rapidity = SelectorAbsRapMax(fRhoEtaMax);
+    JetMedianBackgroundEstimator estimator(select_rapidity, *fDefinition, *fAreaDefinition);
+    estimator.set_particles(inputList);
+    rho = estimator.rho();
+
+    candidate = factory->NewCandidate();
+    candidate->Momentum.SetPtEtaPhiE(rho, 0.0, 0.0, rho); 
+    fRhoOutputArray->Add(candidate);
+  }
+  
+  outputList.clear();
+  outputList = sorted_by_pt(sequence->inclusive_jets(fJetPTMin));
+
+  // loop over all jets and export them
+  detaMax = 0.0;
+  dphiMax = 0.0;
+  vector<PseudoJet>::iterator itInputList, itOutputList;
+  for(itOutputList = outputList.begin(); itOutputList != outputList.end(); ++itOutputList)
+  {
+    momentum.SetPxPyPzE(itOutputList->px(), itOutputList->py(), itOutputList->pz(), itOutputList->E());
+    area.reset(0.0, 0.0, 0.0, 0.0);
+    if(fAreaDefinition) area = itOutputList->area_4vector();
+
+    candidate = factory->NewCandidate();
+
+    inputList.clear();
+    inputList = sequence->constituents(*itOutputList);
+    for(itInputList = inputList.begin(); itInputList != inputList.end(); ++itInputList)
+    {
+      constituent = static_cast<Candidate*>(fInputArray->At(itInputList->user_index()));
+
+      deta = TMath::Abs(momentum.Eta() - constituent->Momentum.Eta());
+      dphi = TMath::Abs(momentum.DeltaPhi(constituent->Momentum));
+      if(deta > detaMax) detaMax = deta;
+      if(dphi > dphiMax) dphiMax = dphi;
+
+      candidate->AddCandidate(constituent);
+    }
+
+    candidate->Momentum = momentum;
+    candidate->Area.SetPxPyPzE(area.px(), area.py(), area.pz(), area.E());
+
+    candidate->DeltaEta = detaMax;
+    candidate->DeltaPhi = dphiMax;
+
+    fOutputArray->Add(candidate);
+  }
+  delete sequence;
+}
Index: trunk/Delphes/Delphes-3.0.9/modules/FastJetFinder.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/FastJetFinder.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/FastJetFinder.h	(revision 5)
@@ -0,0 +1,86 @@
+#ifndef FastJetFinder_h
+#define FastJetFinder_h
+
+/** \class FastJetFinder
+ *
+ *  Finds jets using FastJet library.
+ *
+ *  $Date: 2013-03-06 18:06:55 +0100 (Wed, 06 Mar 2013) $
+ *  $Revision: 1031 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+#include <vector>
+
+class TObjArray;
+class TIterator;
+
+namespace fastjet {
+  class JetDefinition;
+  class AreaDefinition;
+  class Selector;
+}
+
+class FastJetFinder: public DelphesModule
+{
+public:
+
+  FastJetFinder();
+  ~FastJetFinder();
+
+  void Init();
+  void Process();
+  void Finish();
+  
+private:
+
+  void *fPlugin; //!
+  fastjet::JetDefinition *fDefinition; //!
+   
+  Int_t fJetAlgorithm;
+  Double_t fParameterR;
+  Double_t fJetPTMin;
+  Double_t fConeRadius;
+  Double_t fSeedThreshold;
+  Double_t fConeAreaFraction;
+  Int_t fMaxIterations;
+  Int_t fMaxPairSize;
+  Int_t fIratch;
+  Double_t fAdjacencyCut;
+  Double_t fOverlapThreshold;
+  
+  // --- FastJet Area method --------
+  
+  fastjet::AreaDefinition *fAreaDefinition;
+  Int_t fAreaAlgorithm;  
+  Bool_t  fComputeRho; 
+  Double_t fRhoEtaMax;
+  
+  // -- ghost based areas --
+  Double_t fGhostEtaMax;
+  Int_t fRepeat;
+  Double_t fGhostArea;
+  Double_t fGridScatter;
+  Double_t fPtScatter;
+  Double_t fMeanGhostPt; 
+  
+  // -- voronoi areas --
+  Double_t fEffectiveRfact;
+  
+  
+  TIterator *fItInputArray; //!
+
+  const TObjArray *fInputArray; //!
+
+  TObjArray *fOutputArray; //!
+  TObjArray *fRhoOutputArray; //!
+
+  ClassDef(FastJetFinder, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/Isolation.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/Isolation.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/Isolation.cc	(revision 5)
@@ -0,0 +1,184 @@
+
+/** \class Isolation
+ *
+ *  Sums transverse momenta of isolation objects (tracks, calorimeter towers, etc)
+ *  within a DeltaR cone around a candidate and calculates fraction of this sum
+ *  to the candidate's transverse momentum. outputs candidates that have
+ *  the transverse momenta fraction within (PTRatioMin, PTRatioMax].
+ *
+ *  $Date: 2013-03-06 18:11:35 +0100 (Wed, 06 Mar 2013) $
+ *  $Revision: 1033 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/Isolation.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm>
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+class IsolationClassifier : public ExRootClassifier
+{
+public:
+
+  IsolationClassifier() {}
+
+  Int_t GetCategory(TObject *object);
+
+  Double_t fPTMin;
+};
+
+//------------------------------------------------------------------------------
+
+Int_t IsolationClassifier::GetCategory(TObject *object)
+{
+  Candidate *track = static_cast<Candidate*>(object);
+  const TLorentzVector &momentum = track->Momentum;
+
+  if(momentum.Pt() < fPTMin) return -1;
+
+  return 0;
+}
+
+//------------------------------------------------------------------------------
+
+Isolation::Isolation() :
+  fClassifier(0), fFilter(0),
+  fItIsolationInputArray(0), fItCandidateInputArray(0)
+{
+  fClassifier = new IsolationClassifier;
+}
+
+//------------------------------------------------------------------------------
+
+Isolation::~Isolation()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void Isolation::Init()
+{
+  const char *rhoInputArrayName;
+
+  fDeltaRMax = GetDouble("DeltaRMax", 0.5);
+
+  fPTRatioMax = GetDouble("PTRatioMax", 0.1);
+
+  fClassifier->fPTMin = GetDouble("PTMin", 0.5);
+
+  // import input array(s)
+
+  fIsolationInputArray = ImportArray(GetString("IsolationInputArray", "Delphes/partons"));
+  fItIsolationInputArray = fIsolationInputArray->MakeIterator();
+
+  fFilter = new ExRootFilter(fIsolationInputArray);
+
+  fCandidateInputArray = ImportArray(GetString("CandidateInputArray", "Calorimeter/electrons"));
+  fItCandidateInputArray = fCandidateInputArray->MakeIterator();
+
+  rhoInputArrayName = GetString("RhoInputArray", "");
+  if(rhoInputArrayName[0] != '\0')
+  {
+    fRhoInputArray = ImportArray(rhoInputArrayName);
+  }
+  else
+  {
+    fRhoInputArray = 0;
+  }
+
+  // create output array
+
+  fOutputArray = ExportArray(GetString("OutputArray", "electrons"));
+}
+
+//------------------------------------------------------------------------------
+
+void Isolation::Finish()
+{
+  if(fFilter) delete fFilter;
+  if(fItCandidateInputArray) delete fItCandidateInputArray;
+  if(fItIsolationInputArray) delete fItIsolationInputArray;
+}
+
+//------------------------------------------------------------------------------
+
+void Isolation::Process()
+{
+  Candidate *candidate, *isolation;
+  TObjArray *isolationArray;
+  Double_t sumPT, ratio;
+  Int_t counter;
+  Double_t rho = 0.0;
+
+  if(fRhoInputArray && fRhoInputArray->GetEntriesFast() > 0)
+  {
+    candidate = static_cast<Candidate*>(fRhoInputArray->At(0));
+    rho = candidate->Momentum.Pt();
+  }
+
+  // select isolation objects
+  fFilter->Reset();
+  isolationArray = fFilter->GetSubArray(fClassifier, 0);
+
+  if(isolationArray == 0) return;
+
+  TIter itIsolationArray(isolationArray);
+
+  // loop over all input jets
+  fItCandidateInputArray->Reset();
+  while((candidate = static_cast<Candidate*>(fItCandidateInputArray->Next())))
+  {
+    const TLorentzVector &candidateMomentum = candidate->Momentum;
+
+    // loop over all input tracks
+    sumPT = 0.0;
+    counter = 0;
+    itIsolationArray.Reset();
+    while((isolation = static_cast<Candidate*>(itIsolationArray.Next())))
+    {
+      const TLorentzVector &isolationMomentum = isolation->Momentum;
+
+      if(candidateMomentum.DeltaR(isolationMomentum) <= fDeltaRMax &&
+         !candidate->Overlaps(isolation))
+      {
+        sumPT += isolationMomentum.Pt();
+        ++counter;
+      }
+    }
+
+    // correct sumPT for pile-up contamination
+    sumPT = sumPT - rho*fDeltaRMax*fDeltaRMax*TMath::Pi();  
+
+    ratio = sumPT/candidateMomentum.Pt();
+    if(ratio > fPTRatioMax) continue;
+
+    fOutputArray->Add(candidate);
+  }
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/Isolation.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/Isolation.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/Isolation.h	(revision 5)
@@ -0,0 +1,62 @@
+#ifndef Isolation_h
+#define Isolation_h
+
+/** \class Isolation
+ *
+ *  Sums transverse momenta of isolation objects (tracks, calorimeter towers, etc)
+ *  within a DeltaR cone around a candidate and calculates fraction of this sum
+ *  to the candidate's transverse momentum. outputs candidates that have
+ *  the transverse momenta fraction within (PTRatioMin, PTRatioMax].
+ *
+ *  $Date: 2013-03-06 17:53:27 +0100 (Wed, 06 Mar 2013) $
+ *  $Revision: 1028 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+class TObjArray;
+
+class ExRootFilter;
+class IsolationClassifier;
+
+class Isolation: public DelphesModule
+{
+public:
+
+  Isolation();
+  ~Isolation();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  Double_t fDeltaRMax;
+
+  Double_t fPTRatioMax;
+
+  IsolationClassifier *fClassifier; //!
+
+  ExRootFilter *fFilter;
+
+  TIterator *fItIsolationInputArray; //!
+
+  TIterator *fItCandidateInputArray; //!
+
+  const TObjArray *fIsolationInputArray; //!
+
+  const TObjArray *fCandidateInputArray; //!
+
+  const TObjArray *fRhoInputArray; //!
+
+  TObjArray *fOutputArray; //!
+
+  ClassDef(Isolation, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/JetPileUpSubtractor.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/JetPileUpSubtractor.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/JetPileUpSubtractor.cc	(revision 5)
@@ -0,0 +1,114 @@
+
+/** \class JetPileUpSubtractor
+ *
+ *  Subtract pile-up contribution from jets using the fastjet area method
+ *
+ *  $Date: 2012-11-18 15:57:08 +0100 (Sun, 18 Nov 2012) $
+ *  $Revision: 814 $
+ *
+ *  \author M. Selvaggi - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/JetPileUpSubtractor.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm>
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+JetPileUpSubtractor::JetPileUpSubtractor() :
+  fItJetInputArray(0)
+{
+
+}
+
+//------------------------------------------------------------------------------
+
+JetPileUpSubtractor::~JetPileUpSubtractor()
+{
+
+}
+
+//------------------------------------------------------------------------------
+
+void JetPileUpSubtractor::Init()
+{
+  fJetPTMin = GetDouble("JetPTMin", 20.0);
+
+  // import input array(s)
+
+  fJetInputArray = ImportArray(GetString("JetInputArray", "FastJetFinder/jets"));
+  fItJetInputArray = fJetInputArray->MakeIterator();
+
+  fRhoInputArray = ImportArray(GetString("RhoInputArray", "Rho/rho"));
+
+  // create output array(s)
+
+  fOutputArray = ExportArray(GetString("OutputArray", "jets"));
+
+}
+
+//------------------------------------------------------------------------------
+
+void JetPileUpSubtractor::Finish()
+{
+  if(fItJetInputArray) delete fItJetInputArray;
+}
+
+//------------------------------------------------------------------------------
+
+void JetPileUpSubtractor::Process()
+{
+  Candidate *candidate;
+  TLorentzVector momentum, area;
+  Double_t rho = 0.0;
+
+  if(fRhoInputArray && fRhoInputArray->GetEntriesFast() > 0)
+  {
+    candidate = static_cast<Candidate*>(fRhoInputArray->At(0));
+    rho = candidate->Momentum.Pt();
+  }
+
+  // loop over all input candidates
+  fItJetInputArray->Reset();
+  while((candidate = static_cast<Candidate*>(fItJetInputArray->Next())))
+  {
+    momentum = candidate->Momentum;
+    area = candidate->Area;
+
+    // apply pile-up correction
+    if(momentum.Pt() <= rho * area.Pt()) continue;
+
+    momentum -= rho * area;
+  
+    if(momentum.Pt() <= fJetPTMin) continue;
+
+    candidate = static_cast<Candidate*>(candidate->Clone());
+    candidate->Momentum = momentum;
+
+    fOutputArray->Add(candidate);
+  }
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/JetPileUpSubtractor.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/JetPileUpSubtractor.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/JetPileUpSubtractor.h	(revision 5)
@@ -0,0 +1,47 @@
+#ifndef JetPileUpSubtractor_h
+#define JetPileUpSubtractor_h
+
+/** \class JetPileUpSubtractor
+ *
+ *  Subtract pile-up contribution from jets using the fastjet area method
+ *
+ *  $Date: 2012-11-18 15:57:08 +0100 (Sun, 18 Nov 2012) $
+ *  $Revision: 814 $
+ *
+ *  \author M. Selvaggi - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+#include <deque>
+
+class TObjArray;
+class DelphesFormula;
+
+class JetPileUpSubtractor: public DelphesModule
+{
+public:
+
+  JetPileUpSubtractor();
+  ~JetPileUpSubtractor();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  Double_t fJetPTMin;
+
+  TIterator *fItJetInputArray; //!
+
+  const TObjArray *fJetInputArray; //!
+  const TObjArray *fRhoInputArray; //!
+
+  TObjArray *fOutputArray; //!
+
+  ClassDef(JetPileUpSubtractor, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/LeptonDressing.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/LeptonDressing.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/LeptonDressing.cc	(revision 5)
@@ -0,0 +1,115 @@
+
+/** \class LeptonDressing
+ *
+ *
+ *  
+ *
+ *
+ *  \author P. Demin && A. Mertens - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/LeptonDressing.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm> 
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+LeptonDressing::LeptonDressing() :
+ fItDressingInputArray(0), fItCandidateInputArray(0)
+{
+}
+
+//------------------------------------------------------------------------------
+
+LeptonDressing::~LeptonDressing()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void LeptonDressing::Init()
+{
+  fDeltaR = GetDouble("DeltaRMax", 0.4);
+
+  // import input array(s)
+
+  fDressingInputArray = ImportArray(GetString("DressingInputArray", "Calorimeter/photons"));
+  fItDressingInputArray = fDressingInputArray->MakeIterator();
+  
+  fCandidateInputArray = ImportArray(GetString("CandidateInputArray", "UniqueObjectFinder/electrons"));
+  fItCandidateInputArray = fCandidateInputArray->MakeIterator();
+  
+  // create output array
+
+  fOutputArray = ExportArray(GetString("OutputArray", "electrons"));
+}
+
+//------------------------------------------------------------------------------
+
+void LeptonDressing::Finish()
+{
+  if(fItCandidateInputArray) delete fItCandidateInputArray;
+  if(fItDressingInputArray) delete fItDressingInputArray;
+}
+
+//------------------------------------------------------------------------------
+
+void LeptonDressing::Process()
+{
+  Candidate *candidate, *dressing, *mother;
+  TLorentzVector momentum;
+  
+  // loop over all input candidate
+  fItCandidateInputArray->Reset();
+  while((candidate = static_cast<Candidate*>(fItCandidateInputArray->Next())))
+  {
+    const TLorentzVector &candidateMomentum = candidate->Momentum;
+
+    // loop over all input tracks
+    fItDressingInputArray->Reset();
+    momentum.SetPxPyPzE(0.0, 0.0, 0.0, 0.0);
+    while((dressing = static_cast<Candidate*>(fItDressingInputArray->Next())))
+    {
+      const TLorentzVector &dressingMomentum = dressing->Momentum;
+      if (dressingMomentum.Pt() > 0.1)
+      {
+        if(candidateMomentum.DeltaR(dressingMomentum) <= fDeltaR)
+        {
+          momentum += dressingMomentum;
+        }
+      }
+    }
+
+    mother = candidate;
+    candidate = static_cast<Candidate*>(candidate->Clone());
+
+    candidate->Momentum += momentum;
+    candidate->AddCandidate(mother);
+    
+    fOutputArray->Add(candidate);
+  }
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/LeptonDressing.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/LeptonDressing.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/LeptonDressing.h	(revision 5)
@@ -0,0 +1,44 @@
+#ifndef LeptonDressing_h
+#define LeptonDressing_h
+
+/** \class LeptonDressing
+ *
+ *
+ *  \author P. Demin && A. Mertens - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+class TIterator;
+class TObjArray;
+
+class LeptonDressing: public DelphesModule
+{
+public:
+
+  LeptonDressing();
+  ~LeptonDressing();
+  
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  Double_t fDeltaR;
+  
+  TIterator *fItDressingInputArray; //!
+  
+  TIterator *fItCandidateInputArray; //!
+
+  const TObjArray *fDressingInputArray; //!
+  
+  const TObjArray *fCandidateInputArray; //!
+
+  TObjArray *fOutputArray; //!
+
+  ClassDef(LeptonDressing, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/Merger.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/Merger.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/Merger.cc	(revision 5)
@@ -0,0 +1,145 @@
+
+/** \class Merger
+ *
+ *  Merges multiple input arrays into one output array
+ *  and sums transverse momenta of all input objects.
+ *
+ *  $Date: 2013-04-26 12:39:14 +0200 (Fri, 26 Apr 2013) $
+ *  $Revision: 1099 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/Merger.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm> 
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+Merger::Merger()
+{
+}
+
+//------------------------------------------------------------------------------
+
+Merger::~Merger()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void Merger::Init()
+{
+  // import arrays with output from other modules
+
+  ExRootConfParam param = GetParam("InputArray");
+  Long_t i, size;
+  const TObjArray *array;
+  TIterator *iterator;
+
+  size = param.GetSize();
+  for(i = 0; i < size; ++i)
+  {
+    array = ImportArray(param[i].GetString());
+    iterator = array->MakeIterator();
+
+    fInputList.push_back(iterator);
+  }
+
+  // create output arrays
+
+  fOutputArray = ExportArray(GetString("OutputArray", "candidates"));
+
+  fMomentumOutputArray = ExportArray(GetString("MomentumOutputArray", "momentum"));
+  
+  fEnergyOutputArray = ExportArray(GetString("EnergyOutputArray", "energy"));
+}
+
+//------------------------------------------------------------------------------
+
+void Merger::Finish()
+{
+  vector< TIterator * >::iterator itInputList;
+  TIterator *iterator;
+
+  for(itInputList = fInputList.begin(); itInputList != fInputList.end(); ++itInputList)
+  {
+    iterator = *itInputList;
+    if(iterator) delete iterator;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void Merger::Process()
+{
+  Candidate *candidate;
+  TLorentzVector momentum;
+  Double_t sumPT, sumE;  
+  vector< TIterator * >::iterator itInputList;
+  TIterator *iterator;
+
+  DelphesFactory *factory = GetFactory();
+  
+  momentum.SetPxPyPzE(0.0, 0.0, 0.0, 0.0);
+  sumPT = 0;
+  sumE = 0;
+
+  // loop over all input arrays
+  for(itInputList = fInputList.begin(); itInputList != fInputList.end(); ++itInputList)
+  {
+    iterator = *itInputList;
+
+    // loop over all candidates
+    iterator->Reset();
+    while((candidate = static_cast<Candidate*>(iterator->Next())))
+    {
+      const TLorentzVector &candidateMomentum = candidate->Momentum;
+
+      momentum += candidateMomentum;
+      sumPT += candidateMomentum.Pt();
+      sumE += candidateMomentum.E();
+
+      fOutputArray->Add(candidate);
+    }
+  }
+
+  candidate = factory->NewCandidate();
+  
+  candidate->Position.SetXYZT(0.0, 0.0, 0.0, 0.0);
+  candidate->Momentum = momentum;
+  
+  fMomentumOutputArray->Add(candidate);
+
+  candidate = factory->NewCandidate();
+  
+  candidate->Position.SetXYZT(0.0, 0.0, 0.0, 0.0);
+  candidate->Momentum.SetPtEtaPhiE(sumPT, 0.0, 0.0, sumE);
+  
+  fEnergyOutputArray->Add(candidate);
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/Merger.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/Merger.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/Merger.h	(revision 5)
@@ -0,0 +1,47 @@
+#ifndef Merger_h
+#define Merger_h
+
+/** \class Merger
+ *
+ *  Merges multiple input arrays into one output array
+ *  and sums transverse momenta of all input objects.
+ *
+ *  $Date: 2013-02-09 18:32:10 +0100 (Sat, 09 Feb 2013) $
+ *  $Revision: 894 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+#include <vector>
+
+class TIterator;
+class TObjArray;
+class DelphesFormula;
+
+class Merger: public DelphesModule
+{
+public:
+
+  Merger();
+  ~Merger();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  std::vector< TIterator * > fInputList; //!
+
+  TObjArray *fOutputArray; //!
+  TObjArray *fMomentumOutputArray; //!
+  TObjArray *fEnergyOutputArray; //!
+
+  ClassDef(Merger, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/ModulesLinkDef.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/ModulesLinkDef.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/ModulesLinkDef.h	(revision 5)
@@ -0,0 +1,66 @@
+
+/** \class
+ *
+ *  Lists classes to be included in cint dicitonary
+ *
+ *  $Date: 2013-04-26 12:39:14 +0200 (Fri, 26 Apr 2013) $
+ *  $Revision: 1099 $
+ *
+ *  
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/Delphes.h"
+ 
+#include "modules/FastJetFinder.h"
+#include "modules/ParticlePropagator.h"
+#include "modules/Efficiency.h"
+#include "modules/EnergySmearing.h"
+#include "modules/MomentumSmearing.h"
+#include "modules/Calorimeter.h"
+#include "modules/Isolation.h"
+#include "modules/UniqueObjectFinder.h"
+#include "modules/BTagging.h"
+#include "modules/TauTagging.h"
+#include "modules/TreeWriter.h"
+#include "modules/Merger.h"
+#include "modules/LeptonDressing.h"
+#include "modules/PileUpMerger.h"
+#include "modules/JetPileUpSubtractor.h"
+#include "modules/TrackPileUpSubtractor.h"
+#include "modules/ConstituentFilter.h"
+#include "modules/StatusPidFilter.h"
+#include "modules/Cloner.h"
+#include "modules/ExampleModule.h"
+
+#ifdef __CINT__
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+#pragma link C++ class Delphes+;
+
+#pragma link C++ class FastJetFinder+;
+#pragma link C++ class ParticlePropagator+;
+#pragma link C++ class Efficiency+;
+#pragma link C++ class EnergySmearing+;
+#pragma link C++ class MomentumSmearing+;
+#pragma link C++ class Calorimeter+;
+#pragma link C++ class Isolation+;
+#pragma link C++ class UniqueObjectFinder+;
+#pragma link C++ class BTagging+;
+#pragma link C++ class TauTagging+;
+#pragma link C++ class TreeWriter+;
+#pragma link C++ class Merger+;
+#pragma link C++ class LeptonDressing+;
+#pragma link C++ class PileUpMerger+;
+#pragma link C++ class JetPileUpSubtractor+;
+#pragma link C++ class TrackPileUpSubtractor+;
+#pragma link C++ class ConstituentFilter+;
+#pragma link C++ class StatusPidFilter+;
+#pragma link C++ class Cloner+;
+#pragma link C++ class ExampleModule+;
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/MomentumSmearing.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/MomentumSmearing.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/MomentumSmearing.cc	(revision 5)
@@ -0,0 +1,111 @@
+
+/** \class MomentumSmearing
+ *
+ *  Performs transverse momentum resolution smearing.
+ *
+ *  $Date: 2013-02-13 16:58:53 +0100 (Wed, 13 Feb 2013) $
+ *  $Revision: 911 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/MomentumSmearing.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm> 
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+MomentumSmearing::MomentumSmearing() :
+  fFormula(0), fItInputArray(0)
+{
+  fFormula = new DelphesFormula;
+}
+
+//------------------------------------------------------------------------------
+
+MomentumSmearing::~MomentumSmearing()
+{
+  if(fFormula) delete fFormula;
+}
+
+//------------------------------------------------------------------------------
+
+void MomentumSmearing::Init()
+{
+  // read resolution formula
+
+  fFormula->Compile(GetString("ResolutionFormula", "0.0"));
+
+  // import input array
+
+  fInputArray = ImportArray(GetString("InputArray", "ParticlePropagator/stableParticles"));
+  fItInputArray = fInputArray->MakeIterator();
+
+  // create output array
+
+  fOutputArray = ExportArray(GetString("OutputArray", "stableParticles"));
+}
+
+//------------------------------------------------------------------------------
+
+void MomentumSmearing::Finish()
+{
+  if(fItInputArray) delete fItInputArray;
+}
+
+//------------------------------------------------------------------------------
+
+void MomentumSmearing::Process()
+{
+  Candidate *candidate, *mother;
+  Double_t pt, eta, phi;
+
+  fItInputArray->Reset();
+  while((candidate = static_cast<Candidate*>(fItInputArray->Next())))
+  {
+    const TLorentzVector &candidatePosition = candidate->Position;
+    const TLorentzVector &candidateMomentum = candidate->Momentum;
+    eta = candidatePosition.Eta();
+    phi = candidatePosition.Phi();
+    pt = candidateMomentum.Pt();
+
+    // apply smearing formula
+    pt = gRandom->Gaus(pt, fFormula->Eval(pt, eta) * pt);
+    
+    if(pt <= 0.0) continue;
+
+    mother = candidate;
+    candidate = static_cast<Candidate*>(candidate->Clone());
+    eta = candidateMomentum.Eta();
+    phi = candidateMomentum.Phi();
+    candidate->Momentum.SetPtEtaPhiE(pt, eta, phi, pt*TMath::CosH(eta));
+    candidate->AddCandidate(mother);
+        
+    fOutputArray->Add(candidate);
+  }
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/MomentumSmearing.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/MomentumSmearing.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/MomentumSmearing.h	(revision 5)
@@ -0,0 +1,46 @@
+#ifndef MomentumSmearing_h
+#define MomentumSmearing_h
+
+/** \class MomentumSmearing
+ *
+ *  Performs transverse momentum resolution smearing.
+ *
+ *  $Date: 2013-02-12 14:57:44 +0100 (Tue, 12 Feb 2013) $
+ *  $Revision: 905 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+class TIterator;
+class TObjArray;
+class DelphesFormula;
+
+class MomentumSmearing: public DelphesModule
+{
+public:
+
+  MomentumSmearing();
+  ~MomentumSmearing();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  DelphesFormula *fFormula; //!
+
+  TIterator *fItInputArray; //!
+
+  const TObjArray *fInputArray; //!
+  
+  TObjArray *fOutputArray; //!
+
+  ClassDef(MomentumSmearing, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/ParticlePropagator.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/ParticlePropagator.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/ParticlePropagator.cc	(revision 5)
@@ -0,0 +1,288 @@
+
+/** \class ParticlePropagator
+ *
+ *  Propagates charged and neutral particles
+ *  from a given vertex to a cylinder defined by its radius, 
+ *  its half-length, centered at (0,0,0) and with its axis
+ *  oriented along the z-axis.
+ *
+ *  $Date: 2013-02-12 15:13:59 +0100 (Tue, 12 Feb 2013) $
+ *  $Revision: 907 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/ParticlePropagator.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm> 
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+ParticlePropagator::ParticlePropagator() :
+  fItInputArray(0)
+{
+}
+
+//------------------------------------------------------------------------------
+
+ParticlePropagator::~ParticlePropagator()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void ParticlePropagator::Init()
+{
+  fRadius = GetDouble("Radius", 1.0);
+  fRadius2 = fRadius*fRadius;
+  fHalfLength = GetDouble("HalfLength", 3.0);
+  fBz = GetDouble("Bz", 0.0);
+  if(fRadius < 1.0E-2)
+  { 
+    cout << "ERROR: magnetic field radius is too low\n";
+    return;
+  }
+  if(fHalfLength < 1.0E-2)
+  {
+    cout << "ERROR: magnetic field length is too low\n";
+    return;
+  }
+
+  // import array with output from filter/classifier module
+
+  fInputArray = ImportArray(GetString("InputArray", "Delphes/stableParticles"));
+  fItInputArray = fInputArray->MakeIterator();
+
+  // create output arrays
+
+  fOutputArray = ExportArray(GetString("OutputArray", "stableParticles"));
+  fChargedHadronOutputArray = ExportArray(GetString("ChargedHadronOutputArray", "chargedHadrons"));
+  fElectronOutputArray = ExportArray(GetString("ElectronOutputArray", "electrons"));
+  fMuonOutputArray = ExportArray(GetString("MuonOutputArray", "muons"));
+}
+
+//------------------------------------------------------------------------------
+
+void ParticlePropagator::Finish()
+{
+  if(fItInputArray) delete fItInputArray;
+}
+
+//------------------------------------------------------------------------------
+
+void ParticlePropagator::Process()
+{
+  Candidate *candidate, *mother;
+  TLorentzVector candidatePosition, candidateMomentum;
+  Double_t px, py, pz, pt, pt2, e, q;
+  Double_t x, y, z, t, r, phi;
+  Double_t x_c, y_c, r_c, phi_c, phi_0;
+  Double_t x_t, y_t, z_t, r_t;
+  Double_t t1, t2, t3, t4, t5, t6;
+  Double_t t_z, t_r, t_ra, t_rb;
+  Double_t tmp, discr, discr2;
+  Double_t delta, gammam, omega, asinrho;
+  
+  const Double_t c_light = 2.99792458E8;
+    
+  fItInputArray->Reset();
+  while((candidate = static_cast<Candidate*>(fItInputArray->Next())))
+  {
+    candidatePosition = candidate->Position;
+    candidateMomentum = candidate->Momentum;
+    x = candidatePosition.X()*1.0E-3;
+    y = candidatePosition.Y()*1.0E-3;
+    z = candidatePosition.Z()*1.0E-3;
+    q = candidate->Charge;
+
+    // check that particle position is inside the cylinder
+    if(TMath::Hypot(x, y) > fRadius || TMath::Abs(z) > fHalfLength)
+    {
+      continue;
+    }
+
+    px = candidateMomentum.Px();
+    py = candidateMomentum.Py();
+    pz = candidateMomentum.Pz();
+    pt = candidateMomentum.Pt();
+    pt2 = candidateMomentum.Perp2();
+    e = candidateMomentum.E();
+
+    if(pt2 < 1.0E-9)
+    {
+      continue;
+    }
+
+    if(TMath::Abs(q) < 1.0E-9 || TMath::Abs(fBz) < 1.0E-9)
+    {
+      // solve pt2*t^2 + 2*(px*x + py*y)*t + (fRadius2 - x*x - y*y) = 0
+      tmp = px*y - py*x;
+      discr2 = pt2*fRadius2 - tmp*tmp;
+      
+      if(discr2 < 0)
+      {
+        // no solutions
+        continue;
+      }
+
+      tmp = px*x + py*y;
+      discr = TMath::Sqrt(discr2);
+      t1 = (-tmp + discr)/pt2;
+      t2 = (-tmp - discr)/pt2;
+      t = (t1 < 0) ? t2 : t1; 
+
+      z_t = z + pz*t;
+      if(TMath::Abs(z_t) > fHalfLength)
+      {
+        t3 = (+fHalfLength - z) / pz;
+        t4 = (-fHalfLength - z) / pz;
+        t = (t3 < 0) ? t4 : t3; 
+      }
+
+      x_t = x + px*t;
+      y_t = y + py*t;
+      z_t = z + pz*t;
+
+      mother = candidate;
+      candidate = static_cast<Candidate*>(candidate->Clone());
+
+      candidate->Position.SetXYZT(x_t*1.0E3, y_t*1.0E3, z_t*1.0E3, 0.0);
+
+      candidate->Momentum = candidateMomentum;
+      candidate->AddCandidate(mother);
+      
+      fOutputArray->Add(candidate);
+      if(TMath::Abs(q) > 1.0E-9) 
+      {
+        switch(TMath::Abs(candidate->PID))
+        {
+          case 11:
+            fElectronOutputArray->Add(candidate);
+            break;
+          case 13:
+            fMuonOutputArray->Add(candidate);
+            break;
+          default:
+            fChargedHadronOutputArray->Add(candidate);
+        }
+      }
+    }
+    else
+    {
+
+      // 1.  initial transverse momentum p_{T0} : Part->pt
+      //     initial transverse momentum direction \phi_0 = -atan(p_X0/p_Y0) 
+      //     relativistic gamma : gamma = E/mc² ; gammam = gamma \times m
+      //     giration frequency \omega = q/(gamma m) fBz
+      //     helix radius r = p_T0 / (omega gamma m)
+
+      gammam = e*1.0E9 / (c_light*c_light);      // gammam in [eV/c²]
+      omega = q * fBz / (gammam);                // omega is here in [ 89875518 / s]  
+      r = pt / (q * fBz) * 1.0E9/c_light;        // in [m]  
+
+      phi_0 = TMath::ATan2(py, px); // [rad] in [-pi; pi]
+
+      // 2. helix axis coordinates
+      x_c = x + r*TMath::Sin(phi_0);
+      y_c = y - r*TMath::Cos(phi_0);
+      r_c = TMath::Hypot(x_c, y_c);
+      phi_c = TMath::ATan2(y_c, x_c);
+      phi = phi_c;
+      if(x_c < 0.0) phi += TMath::Pi();
+
+      // 3. time evaluation t = TMath::Min(t_r, t_z)
+      //    t_r : time to exit from the sides
+      //    t_z : time to exit from the front or the back
+      t_r = 0.0; // in [ns]
+      int sign_pz = (pz > 0.0) ? 1 : -1;
+      if(pz == 0.0) t_z = 1.0E99;
+      else t_z = gammam / (pz*1.0E9/c_light) * (-z + fHalfLength*sign_pz);
+
+      if(r_c + TMath::Abs(r)  < fRadius)
+      {
+        // helix does not cross the cylinder sides
+        t = t_z;
+      }
+      else
+      {
+        asinrho = TMath::ASin( (fRadius*fRadius - r_c*r_c - r*r) / (2*TMath::Abs(r)*r_c)  );
+        delta = phi_0 - phi;
+        if(delta <-TMath::Pi()) delta += 2*TMath::Pi();
+        if(delta > TMath::Pi()) delta -= 2*TMath::Pi();
+        t1 = (delta + asinrho) / omega;
+        t2 = (delta + TMath::Pi() - asinrho) / omega;
+        t3 = (delta + TMath::Pi() + asinrho) / omega;
+        t4 = (delta - asinrho) / omega;
+        t5 = (delta - TMath::Pi() - asinrho) / omega;
+        t6 = (delta - TMath::Pi() + asinrho) / omega;
+
+        if(t1 < 0) t1 = 1.0E99;
+        if(t2 < 0) t2 = 1.0E99;
+        if(t3 < 0) t3 = 1.0E99;
+        if(t4 < 0) t4 = 1.0E99;
+        if(t5 < 0) t5 = 1.0E99;
+        if(t6 < 0) t6 = 1.0E99;
+
+        t_ra = TMath::Min(t1, TMath::Min(t2, t3));
+        t_rb = TMath::Min(t4, TMath::Min(t5, t6));
+        t_r = TMath::Min(t_ra, t_rb);
+        t = TMath::Min(t_r, t_z); 
+      }
+
+      // 4. position in terms of x(t), y(t), z(t)
+      x_t = x_c + r * TMath::Sin(omega * t - phi_0);
+      y_t = y_c + r * TMath::Cos(omega * t - phi_0);
+      z_t = z + pz*1.0E9 / c_light / gammam * t;
+      r_t = TMath::Hypot(x_t, y_t);
+
+      if(r_t > 0.0)
+      {
+        mother = candidate;
+        candidate = static_cast<Candidate*>(candidate->Clone());
+
+        candidate->Position.SetXYZT(x_t*1.0E3, y_t*1.0E3, z_t*1.0E3, 0.0);
+
+        candidate->Momentum = candidateMomentum;
+        candidate->AddCandidate(mother);
+
+        fOutputArray->Add(candidate);
+        switch(TMath::Abs(candidate->PID))
+        {
+          case 11:
+            fElectronOutputArray->Add(candidate);
+            break;
+          case 13:
+            fMuonOutputArray->Add(candidate);
+            break;
+          default:
+            fChargedHadronOutputArray->Add(candidate);
+        }
+      }
+    }
+  }
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/ParticlePropagator.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/ParticlePropagator.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/ParticlePropagator.h	(revision 5)
@@ -0,0 +1,52 @@
+#ifndef ParticlePropagator_h
+#define ParticlePropagator_h
+
+/** \class ParticlePropagator
+ *
+ *  Propagates charged and neutral particles
+ *  from a given vertex to a cylinder defined by its radius, 
+ *  its half-length, centered at (0,0,0) and with its axis
+ *  oriented along the z-axis.
+ *
+ *  $Date: 2013-02-12 14:57:44 +0100 (Tue, 12 Feb 2013) $
+ *  $Revision: 905 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+class TClonesArray;
+class TIterator;
+
+class ParticlePropagator: public DelphesModule
+{
+public:
+
+  ParticlePropagator();
+  ~ParticlePropagator();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  Double_t fRadius, fRadius2, fHalfLength;
+  Double_t fBz;
+
+  TIterator *fItInputArray; //!
+
+  const TObjArray *fInputArray; //!
+
+  TObjArray *fOutputArray; //!
+  TObjArray *fChargedHadronOutputArray; //!
+  TObjArray *fElectronOutputArray; //!
+  TObjArray *fMuonOutputArray; //!
+
+  ClassDef(ParticlePropagator, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/PileUpMerger.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/PileUpMerger.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/PileUpMerger.cc	(revision 5)
@@ -0,0 +1,146 @@
+/** \class PileUpMerger
+ *
+ *  Merges particles from pile-up sample into event
+ *
+ *
+ *  $Date: 2013-02-12 15:13:59 +0100 (Tue, 12 Feb 2013) $
+ *  $Revision: 907 $
+ *
+ *
+ *  \author M. Selvaggi - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/PileUpMerger.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+#include "classes/DelphesPileUpReader.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm>
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+PileUpMerger::PileUpMerger() :
+  fReader(0), fItInputArray(0)
+{
+}
+
+//------------------------------------------------------------------------------
+
+PileUpMerger::~PileUpMerger()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void PileUpMerger::Init()
+{
+  const char *fileName;
+
+  fMeanPileUp  = GetDouble("MeanPileUp", 10);
+  fZVertexSpread = GetDouble("ZVertexSpread", 0.05)*1.0E3;
+
+  fileName = GetString("PileUpFile", "MinBias.pileup");
+  fReader = new DelphesPileUpReader(fileName);
+
+  // import input array
+  fInputArray = ImportArray(GetString("InputArray", "Delphes/stableParticles"));
+  fItInputArray = fInputArray->MakeIterator();
+
+  // create output arrays
+  fOutputArray = ExportArray(GetString("OutputArray", "stableParticles"));
+}
+
+//------------------------------------------------------------------------------
+
+void PileUpMerger::Finish()
+{
+  if(fReader) delete fReader;
+}
+
+//------------------------------------------------------------------------------
+
+void PileUpMerger::Process()
+{
+  TDatabasePDG *pdg = TDatabasePDG::Instance();
+  TParticlePDG *pdgParticle;
+  Int_t pid;
+  Float_t x, y, z, t;
+  Float_t px, py, pz, e;
+  Double_t dz, dphi;
+  Int_t poisson, event;
+  Long64_t allEntries, entry;
+  Candidate *candidate;
+  DelphesFactory *factory;
+
+  fItInputArray->Reset();
+  while((candidate = static_cast<Candidate*>(fItInputArray->Next())))
+  {
+    fOutputArray->Add(candidate);
+  }
+
+  factory = GetFactory();
+
+  poisson = gRandom->Poisson(fMeanPileUp);
+
+  allEntries = fReader->GetEntries();
+
+  for(event = 0; event < poisson; ++event)
+  {
+    do
+    {
+      entry = TMath::Nint(gRandom->Rndm()*allEntries);
+    }
+    while(entry >= allEntries);
+
+    fReader->ReadEntry(entry);
+
+    dz = gRandom->Gaus(0.0, fZVertexSpread);
+    dphi = gRandom->Uniform(-TMath::Pi(), TMath::Pi());
+
+    while(fReader->ReadParticle(pid, x, y, z, t, px, py, pz, e))
+    {
+      candidate = factory->NewCandidate();
+
+      candidate->PID = pid;
+
+      candidate->Status = 1;
+
+      pdgParticle = pdg->GetParticle(pid);
+      candidate->Charge = pdgParticle ? Int_t(pdgParticle->Charge()/3.0) : -999;
+      candidate->Mass = pdgParticle ? pdgParticle->Mass() : -999.9;
+
+      candidate->IsPU = 1;
+
+      candidate->Momentum.SetPxPyPzE(px, py, pz, e);
+      candidate->Momentum.RotateZ(dphi);
+
+      candidate->Position.SetXYZT(x, y, z + dz, t);
+      candidate->Position.RotateZ(dphi);
+
+      fOutputArray->Add(candidate);
+    }
+  }
+}
+
+//------------------------------------------------------------------------------
+
Index: trunk/Delphes/Delphes-3.0.9/modules/PileUpMerger.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/PileUpMerger.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/PileUpMerger.h	(revision 5)
@@ -0,0 +1,49 @@
+#ifndef PileUpMerger_h
+#define PileUpMerger_h
+
+/** \class PileUpMerger
+ *
+ *  Merges particles from pile-up sample into event
+ *
+ *
+ *  $Date: 2013-02-12 15:13:59 +0100 (Tue, 12 Feb 2013) $
+ *  $Revision: 907 $
+ *
+ *
+ *  \author M. Selvaggi - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+class TObjArray;
+class DelphesPileUpReader;
+
+class PileUpMerger: public DelphesModule
+{
+public:
+
+  PileUpMerger();
+  ~PileUpMerger();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  Double_t fMeanPileUp;
+  Double_t fZVertexSpread;
+
+  DelphesPileUpReader *fReader;
+
+  TIterator *fItInputArray; //!
+
+  const TObjArray *fInputArray; //!
+
+  TObjArray *fOutputArray; //!
+
+  ClassDef(PileUpMerger, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/StatusPidFilter.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/StatusPidFilter.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/StatusPidFilter.cc	(revision 5)
@@ -0,0 +1,109 @@
+/** \class StatusPidFilter
+ *
+ *  Removes all generated particles except electrons, muons, taus,
+ *  and particles with status == 3.
+ *
+ *  $Date: 2013-05-20 22:22:07 +0200 (Mon, 20 May 2013) $
+ *  $Revision: 1118 $
+ *
+ *
+ *  \author J. Hirschauer - FNAL
+ *
+ */
+
+#include "modules/StatusPidFilter.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm>
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+StatusPidFilter::StatusPidFilter() :
+  fItInputArray(0)
+{
+}
+
+//------------------------------------------------------------------------------
+
+StatusPidFilter::~StatusPidFilter()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void StatusPidFilter::Init()
+{
+  // PT threshold
+
+  fPTMin = GetDouble("PTMin", 0.5);
+
+  // import input array
+  fInputArray = ImportArray(GetString("InputArray", "Delphes/allParticles"));
+  fItInputArray = fInputArray->MakeIterator();
+
+  // create output array
+
+  fOutputArray = ExportArray(GetString("OutputArray", "filteredParticles"));
+}
+
+//------------------------------------------------------------------------------
+
+void StatusPidFilter::Finish()
+{
+  if(fItInputArray) delete fItInputArray;
+}
+
+//------------------------------------------------------------------------------
+
+void StatusPidFilter::Process()
+{
+  Candidate *candidate;
+  Int_t status, pdgCode;
+  Bool_t pass;
+
+  fItInputArray->Reset();
+  while((candidate = static_cast<Candidate*>(fItInputArray->Next())))
+  {
+    status = candidate->Status;
+    pdgCode = TMath::Abs(candidate->PID);
+
+    pass = kFALSE;
+
+    // status == 3
+    if(status == 3) pass = kTRUE;
+
+    // electrons, muons, taus and neutrinos
+    if(pdgCode > 10 && pdgCode < 17) pass = kTRUE;
+
+    // heavy quarks
+    if(pdgCode == 5 || pdgCode == 6) pass = kTRUE;
+
+    // Gauge bosons and other fundamental bosons
+    if(pdgCode > 22 && pdgCode < 43) pass = kTRUE;
+
+    if(!pass || candidate->Momentum.Pt() <= fPTMin) continue;
+
+    fOutputArray->Add(candidate);
+  }
+}
+
Index: trunk/Delphes/Delphes-3.0.9/modules/StatusPidFilter.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/StatusPidFilter.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/StatusPidFilter.h	(revision 5)
@@ -0,0 +1,48 @@
+//------------------------------------------------------------------------------
+
+#ifndef StatusPidFilter_h
+#define StatusPidFilter_h
+
+/** \class Efficiency
+ *
+ *  Removes all generated particles except electrons, muons, taus,
+ *  and particles with status == 3.
+ *
+ *  $Date: 2013-04-07 00:12:34 +0200 (Sun, 07 Apr 2013) $
+ *  $Revision: 1079 $
+ *
+ *
+ *  \author J. Hirschauer - FNAL
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+class TIterator;
+class TObjArray;
+
+class StatusPidFilter: public DelphesModule
+{
+public:
+
+  StatusPidFilter();
+  ~StatusPidFilter();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  Double_t fPTMin; //!
+
+  TIterator *fItInputArray; //!
+
+  const TObjArray *fInputArray; //!
+
+  TObjArray *fOutputArray; //!
+
+  ClassDef(StatusPidFilter, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/TauTagging.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/TauTagging.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/TauTagging.cc	(revision 5)
@@ -0,0 +1,227 @@
+
+/** \class TauTagging
+ *
+ *  Determines origin of jet,
+ *  applies b-tagging efficiency (miss identification rate) formulas
+ *  and sets b-tagging flags
+ *
+ *  $Date: 2013-03-21 00:23:25 +0100 (Thu, 21 Mar 2013) $
+ *  $Revision: 1065 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/TauTagging.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm>
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+class TauTaggingPartonClassifier : public ExRootClassifier
+{
+public:
+
+  TauTaggingPartonClassifier(const TObjArray *array);
+
+  Int_t GetCategory(TObject *object);
+
+  Double_t fEtaMax, fPTMin;
+
+  const TObjArray *fParticleInputArray;
+};
+
+//------------------------------------------------------------------------------
+TauTaggingPartonClassifier::TauTaggingPartonClassifier(const TObjArray *array) :
+  fParticleInputArray(array)
+{
+}
+
+//------------------------------------------------------------------------------
+
+Int_t TauTaggingPartonClassifier::GetCategory(TObject *object)
+{
+  Candidate *tau = static_cast<Candidate *>(object);
+  Candidate *daughter = 0;
+  const TLorentzVector &momentum = tau->Momentum;
+  Int_t pdgCode, i;
+
+  pdgCode = TMath::Abs(tau->PID);
+  if(pdgCode != 15) return -1;
+
+  if(momentum.Pt() <= fPTMin || TMath::Abs(momentum.Eta()) > fEtaMax) return -1;
+
+  if(tau->D1 < 0) return -1;
+
+  for(i = tau->D1; i <= tau->D2; ++i)
+  {
+    daughter = static_cast<Candidate *>(fParticleInputArray->At(i));
+    pdgCode = TMath::Abs(daughter->PID);
+    if(pdgCode == 11 || pdgCode == 13 || pdgCode == 15 || pdgCode == 24) return -1;
+  }
+
+  return 0;
+}
+
+//------------------------------------------------------------------------------
+
+TauTagging::TauTagging() :
+  fClassifier(0), fFilter(0),
+  fItPartonInputArray(0), fItJetInputArray(0)
+{
+}
+
+//------------------------------------------------------------------------------
+
+TauTagging::~TauTagging()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void TauTagging::Init()
+{
+  map< Int_t, DelphesFormula * >::iterator itEfficiencyMap;
+  ExRootConfParam param;
+  DelphesFormula *formula;
+  Int_t i, size;
+
+  fDeltaR = GetDouble("DeltaR", 0.5);
+
+  // read efficiency formulas
+  param = GetParam("EfficiencyFormula");
+  size = param.GetSize();
+
+  fEfficiencyMap.clear();
+  for(i = 0; i < size/2; ++i)
+  {
+    formula = new DelphesFormula;
+    formula->Compile(param[i*2 + 1].GetString());
+
+    fEfficiencyMap[param[i*2].GetInt()] = formula;
+  }
+
+  // set default efficiency formula
+  itEfficiencyMap = fEfficiencyMap.find(0);
+  if(itEfficiencyMap == fEfficiencyMap.end())
+  {
+    formula = new DelphesFormula;
+    formula->Compile("0.0");
+
+    fEfficiencyMap[0] = formula;
+  }
+
+  // import input array(s)
+
+  fParticleInputArray = ImportArray(GetString("ParticleInputArray", "Delphes/allParticles"));
+
+  fClassifier = new TauTaggingPartonClassifier(fParticleInputArray);
+  fClassifier->fPTMin = GetDouble("TauPTMin", 1.0);
+  fClassifier->fEtaMax = GetDouble("TauEtaMax", 2.5);
+
+  fPartonInputArray = ImportArray(GetString("PartonInputArray", "Delphes/partons"));
+  fItPartonInputArray = fPartonInputArray->MakeIterator();
+
+  fFilter = new ExRootFilter(fPartonInputArray);
+
+  fJetInputArray = ImportArray(GetString("JetInputArray", "FastJetFinder/jets"));
+  fItJetInputArray = fJetInputArray->MakeIterator();
+}
+
+//------------------------------------------------------------------------------
+
+void TauTagging::Finish()
+{
+  map< Int_t, DelphesFormula * >::iterator itEfficiencyMap;
+  DelphesFormula *formula;
+
+  if(fFilter) delete fFilter;
+  if(fClassifier) delete fClassifier;
+  if(fItJetInputArray) delete fItJetInputArray;
+  if(fItPartonInputArray) delete fItPartonInputArray;
+
+  for(itEfficiencyMap = fEfficiencyMap.begin(); itEfficiencyMap != fEfficiencyMap.end(); ++itEfficiencyMap)
+  {
+    formula = itEfficiencyMap->second;
+    if(formula) delete formula;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void TauTagging::Process()
+{
+  Candidate *jet, *tau;
+  Double_t pt, eta, phi;
+  TObjArray *tauArray;
+  map< Int_t, DelphesFormula * >::iterator itEfficiencyMap;
+  DelphesFormula *formula;
+  Int_t pdgCode, charge;
+
+  // select taus
+  fFilter->Reset();
+  tauArray = fFilter->GetSubArray(fClassifier, 0);
+
+  if(tauArray == 0) return;
+
+  TIter itTauArray(tauArray);
+
+  // loop over all input jets
+  fItJetInputArray->Reset();
+  while((jet = static_cast<Candidate *>(fItJetInputArray->Next())))
+  {
+    const TLorentzVector &jetMomentum = jet->Momentum;
+    pdgCode = 0;
+    charge = gRandom->Uniform() > 0.5 ? 1 : -1;
+    eta = jetMomentum.Eta();
+    phi = jetMomentum.Phi();
+    pt = jetMomentum.Pt();
+
+    // loop over all input taus
+    itTauArray.Reset();
+    while((tau = static_cast<Candidate *>(itTauArray.Next())))
+    {
+      if(jetMomentum.DeltaR(tau->Momentum) <= fDeltaR)
+      {
+        pdgCode = 15;
+        charge = tau->Charge;
+      }
+    }
+    // find an efficency formula
+    itEfficiencyMap = fEfficiencyMap.find(pdgCode);
+    if(itEfficiencyMap == fEfficiencyMap.end())
+    {
+      itEfficiencyMap = fEfficiencyMap.find(0);
+    }
+    formula = itEfficiencyMap->second;
+
+    // apply an efficency formula
+    jet->TauTag = gRandom->Uniform() <= formula->Eval(pt, eta);
+    // set tau charge
+    jet->Charge = charge;
+  }
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/TauTagging.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/TauTagging.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/TauTagging.h	(revision 5)
@@ -0,0 +1,62 @@
+#ifndef TauTagging_h
+#define TauTagging_h
+
+/** \class TauTagging
+ *
+ *  Determines origin of jet,
+ *  applies b-tagging efficiency (miss identification rate) formulas
+ *  and sets b-tagging flags 
+ *
+ *  $Date: 2013-02-22 01:01:36 +0100 (Fri, 22 Feb 2013) $
+ *  $Revision: 926 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+#include <map>
+
+class TObjArray;
+class DelphesFormula;
+
+class ExRootFilter;
+class TauTaggingPartonClassifier;
+
+class TauTagging: public DelphesModule
+{
+public:
+
+  TauTagging();
+  ~TauTagging();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  Double_t fDeltaR;
+
+  std::map< Int_t, DelphesFormula * > fEfficiencyMap; //!
+  
+  TauTaggingPartonClassifier *fClassifier; //!
+  
+  ExRootFilter *fFilter;
+
+  TIterator *fItPartonInputArray; //!
+  
+  TIterator *fItJetInputArray; //!
+
+  const TObjArray *fParticleInputArray; //!
+
+  const TObjArray *fPartonInputArray; //!
+  
+  const TObjArray *fJetInputArray; //!
+
+  ClassDef(TauTagging, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/TrackPileUpSubtractor.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/TrackPileUpSubtractor.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/TrackPileUpSubtractor.cc	(revision 5)
@@ -0,0 +1,121 @@
+
+/** \class TrackPileUpSubtractor
+ *
+ *  Subtract pile-up contribution from tracks.
+ *
+ *  $Date: 2013-03-24 21:25:01 +0100 (Sun, 24 Mar 2013) $
+ *  $Revision: 1073 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/TrackPileUpSubtractor.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm>
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+TrackPileUpSubtractor::TrackPileUpSubtractor()
+{
+}
+
+//------------------------------------------------------------------------------
+
+TrackPileUpSubtractor::~TrackPileUpSubtractor()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void TrackPileUpSubtractor::Init()
+{
+  fZVertexResolution  = GetDouble("ZVertexResolution", 0.005)*1.0E3;
+
+  // import arrays with output from other modules
+
+  ExRootConfParam param = GetParam("InputArray");
+  Long_t i, size;
+  const TObjArray *array;
+  TIterator *iterator;
+
+  size = param.GetSize();
+  for(i = 0; i < size/2; ++i)
+  {
+    array = ImportArray(param[i*2].GetString());
+    iterator = array->MakeIterator();
+
+    fInputMap[iterator] = ExportArray(param[i*2 + 1].GetString());;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void TrackPileUpSubtractor::Finish()
+{
+  map< TIterator *, TObjArray * >::iterator itInputMap;
+  TIterator *iterator;
+
+  for(itInputMap = fInputMap.begin(); itInputMap != fInputMap.end(); ++itInputMap)
+  {
+    iterator = itInputMap->first;
+
+    if(iterator) delete iterator;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void TrackPileUpSubtractor::Process()
+{
+  Candidate *candidate, *particle;
+  map< TIterator *, TObjArray * >::iterator itInputMap;
+  TIterator *iterator;
+  TObjArray *array;
+  Double_t z;
+
+  // loop over all input arrays
+  for(itInputMap = fInputMap.begin(); itInputMap != fInputMap.end(); ++itInputMap)
+  {
+    iterator = itInputMap->first;
+    array = itInputMap->second;
+
+    // loop over all candidates
+    iterator->Reset();
+    while((candidate = static_cast<Candidate*>(iterator->Next())))
+    {
+      particle = static_cast<Candidate*>(candidate->GetCandidates()->At(0));
+      z = particle->Position.Z();
+
+      // apply pile-up subtraction
+      // assume perfect pile-up subtraction for tracks outside fZVertexResolution
+      if(candidate->IsPU && TMath::Abs(z) > fZVertexResolution) continue;
+
+      array->Add(candidate);
+    }
+  }
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/TrackPileUpSubtractor.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/TrackPileUpSubtractor.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/TrackPileUpSubtractor.h	(revision 5)
@@ -0,0 +1,43 @@
+#ifndef TrackPileUpSubtractor_h
+#define TrackPileUpSubtractor_h
+
+/** \class TrackPileUpSubtractor
+ *
+ *  Subtract pile-up contribution from tracks.
+ *
+ *  $Date: 2013-03-24 15:08:05 +0100 (Sun, 24 Mar 2013) $
+ *  $Revision: 1069 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+#include <map>
+
+class TIterator;
+class TObjArray;
+
+class TrackPileUpSubtractor: public DelphesModule
+{
+public:
+
+  TrackPileUpSubtractor();
+  ~TrackPileUpSubtractor();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  Double_t fZVertexResolution;
+
+  std::map< TIterator *, TObjArray * > fInputMap; //!
+
+  ClassDef(TrackPileUpSubtractor, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/TreeWriter.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/TreeWriter.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/TreeWriter.cc	(revision 5)
@@ -0,0 +1,557 @@
+
+/** \class TreeWriter
+ *
+ *  Fills ROOT tree branches.
+ *
+ *  $Date: 2013-05-16 16:28:38 +0200 (Thu, 16 May 2013) $
+ *  $Revision: 1115 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/TreeWriter.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+#include "ExRootAnalysis/ExRootTreeBranch.h"
+
+#include "TROOT.h"
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm>
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+TreeWriter::TreeWriter()
+{
+}
+
+//------------------------------------------------------------------------------
+
+TreeWriter::~TreeWriter()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void TreeWriter::Init()
+{
+  fClassMap[GenParticle::Class()] = &TreeWriter::ProcessParticles;
+  fClassMap[Track::Class()] = &TreeWriter::ProcessTracks;
+  fClassMap[Tower::Class()] = &TreeWriter::ProcessTowers;
+  fClassMap[Photon::Class()] = &TreeWriter::ProcessPhotons;
+  fClassMap[Electron::Class()] = &TreeWriter::ProcessElectrons;
+  fClassMap[Muon::Class()] = &TreeWriter::ProcessMuons;
+  fClassMap[Jet::Class()] = &TreeWriter::ProcessJets;
+  fClassMap[MissingET::Class()] = &TreeWriter::ProcessMissingET;
+  fClassMap[ScalarHT::Class()] = &TreeWriter::ProcessScalarHT;
+  fClassMap[Rho::Class()] = &TreeWriter::ProcessRho;
+
+  TBranchMap::iterator itBranchMap;
+  map< TClass *, TProcessMethod >::iterator itClassMap;
+
+  // read branch configuration and
+  // import array with output from filter/classifier/jetfinder modules
+
+  ExRootConfParam param = GetParam("Branch");
+  Long_t i, size;
+  TString branchName, branchClassName, branchInputArray;
+  TClass *branchClass;
+  TObjArray *array;
+  ExRootTreeBranch *branch;
+
+  size = param.GetSize();
+  for(i = 0; i < size/3; ++i)
+  {
+    branchInputArray = param[i*3].GetString();
+    branchName = param[i*3 + 1].GetString();
+    branchClassName = param[i*3 + 2].GetString();
+
+    branchClass = gROOT->GetClass(branchClassName);
+
+    if(!branchClass)
+    {
+      cout << "** ERROR: cannot find class '" << branchClassName << "'" << endl;
+      continue;
+    }
+
+    itClassMap = fClassMap.find(branchClass);
+    if(itClassMap == fClassMap.end())
+    {
+      cout << "** ERROR: cannot create branch for class '" << branchClassName << "'" << endl;
+      continue;
+    }
+
+    array = ImportArray(branchInputArray);
+    branch = NewBranch(branchName, branchClass);
+
+    fBranchMap.insert(make_pair(branch, make_pair(itClassMap->second, array)));
+  }
+
+}
+
+//------------------------------------------------------------------------------
+
+void TreeWriter::Finish()
+{
+
+}
+
+//------------------------------------------------------------------------------
+
+void TreeWriter::FillParticles(Candidate *candidate, TRefArray *array)
+{
+  TIter it1(candidate->GetCandidates());
+  it1.Reset();
+  array->Clear();
+  while((candidate = static_cast<Candidate*>(it1.Next())))
+  {
+    TIter it2(candidate->GetCandidates());
+
+    // particle
+    if(candidate->GetCandidates()->GetEntriesFast() == 0)
+    {
+      array->Add(candidate);
+      continue;
+    }
+
+    // track
+    candidate = static_cast<Candidate*>(candidate->GetCandidates()->At(0));
+    if(candidate->GetCandidates()->GetEntriesFast() == 0)
+    {
+      array->Add(candidate);
+      continue;
+    }
+
+    // tower
+    it2.Reset();
+    while((candidate = static_cast<Candidate*>(it2.Next())))
+    {
+      array->Add(candidate->GetCandidates()->At(0));
+    }
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void TreeWriter::ProcessParticles(ExRootTreeBranch *branch, TObjArray *array)
+{
+  TIter iterator(array);
+  Candidate *candidate = 0;
+  GenParticle *entry = 0;
+  Double_t pt, signPz, cosTheta, eta, rapidity;
+
+  // loop over all particles
+  iterator.Reset();
+  while((candidate = static_cast<Candidate*>(iterator.Next())))
+  {
+    const TLorentzVector &momentum = candidate->Momentum;
+    const TLorentzVector &position = candidate->Position;
+
+    entry = static_cast<GenParticle*>(branch->NewEntry());
+
+    entry->SetBit(kIsReferenced);
+    entry->SetUniqueID(candidate->GetUniqueID());
+
+    pt = momentum.Pt();
+    cosTheta = TMath::Abs(momentum.CosTheta());
+    signPz = (momentum.Pz() >= 0.0) ? 1.0 : -1.0;
+    eta = (cosTheta == 1.0 ? signPz*999.9 : momentum.Eta());
+    rapidity = (cosTheta == 1.0 ? signPz*999.9 : momentum.Rapidity());
+
+    entry->PID = candidate->PID;
+
+    entry->Status = candidate->Status;
+    entry->IsPU = candidate->IsPU;
+
+    entry->M1 = candidate->M1;
+    entry->M2 = candidate->M2;
+
+    entry->D1 = candidate->D1;
+    entry->D2 = candidate->D2;
+
+    entry->Charge = candidate->Charge;
+    entry->Mass = candidate->Mass;
+
+    entry->E = momentum.E();
+    entry->Px = momentum.Px();
+    entry->Py = momentum.Py();
+    entry->Pz = momentum.Pz();
+
+    entry->Eta = eta;
+    entry->Phi = momentum.Phi();
+    entry->PT = pt;
+
+    entry->Rapidity = rapidity;
+
+    entry->X = position.X();
+    entry->Y = position.Y();
+    entry->Z = position.Z();
+    entry->T = position.T();
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void TreeWriter::ProcessTracks(ExRootTreeBranch *branch, TObjArray *array)
+{
+  TIter iterator(array);
+  Candidate *candidate = 0;
+  Candidate *particle = 0;
+  Track *entry = 0;
+  Double_t pt, signz, cosTheta, eta, rapidity;
+
+  // loop over all jets
+  iterator.Reset();
+  while((candidate = static_cast<Candidate*>(iterator.Next())))
+  {
+    const TLorentzVector &position = candidate->Position;
+
+    cosTheta = TMath::Abs(position.CosTheta());
+    signz = (position.Pz() >= 0.0) ? 1.0 : -1.0;
+    eta = (cosTheta == 1.0 ? signz*999.9 : position.Eta());
+    rapidity = (cosTheta == 1.0 ? signz*999.9 : position.Rapidity());
+
+    entry = static_cast<Track*>(branch->NewEntry());
+
+    entry->SetBit(kIsReferenced);
+    entry->SetUniqueID(candidate->GetUniqueID());
+
+    entry->PID = candidate->PID;
+
+    entry->Charge = candidate->Charge;
+
+    entry->EtaOuter = eta;
+    entry->PhiOuter = position.Phi();
+
+    entry->XOuter = position.X();
+    entry->YOuter = position.Y();
+    entry->ZOuter = position.Z();
+
+    const TLorentzVector &momentum = candidate->Momentum;
+
+    pt = momentum.Pt();
+    cosTheta = TMath::Abs(momentum.CosTheta());
+    signz = (momentum.Pz() >= 0.0) ? 1.0 : -1.0;
+    eta = (cosTheta == 1.0 ? signz*999.9 : momentum.Eta());
+    rapidity = (cosTheta == 1.0 ? signz*999.9 : momentum.Rapidity());
+
+    entry->Eta = eta;
+    entry->Phi = momentum.Phi();
+    entry->PT = pt;
+
+    particle = static_cast<Candidate*>(candidate->GetCandidates()->At(0));
+    const TLorentzVector &initialPosition = particle->Position;
+
+    entry->X = initialPosition.X();
+    entry->Y = initialPosition.Y();
+    entry->Z = initialPosition.Z();
+
+    entry->Particle = particle;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void TreeWriter::ProcessTowers(ExRootTreeBranch *branch, TObjArray *array)
+{
+  TIter iterator(array);
+  Candidate *candidate = 0;
+  Tower *entry = 0;
+  Double_t pt, signPz, cosTheta, eta, rapidity;
+
+  // loop over all jets
+  iterator.Reset();
+  while((candidate = static_cast<Candidate*>(iterator.Next())))
+  {
+    const TLorentzVector &momentum = candidate->Momentum;
+
+    pt = momentum.Pt();
+    cosTheta = TMath::Abs(momentum.CosTheta());
+    signPz = (momentum.Pz() >= 0.0) ? 1.0 : -1.0;
+    eta = (cosTheta == 1.0 ? signPz*999.9 : momentum.Eta());
+    rapidity = (cosTheta == 1.0 ? signPz*999.9 : momentum.Rapidity());
+
+    entry = static_cast<Tower*>(branch->NewEntry());
+
+    entry->SetBit(kIsReferenced);
+    entry->SetUniqueID(candidate->GetUniqueID());
+
+    entry->Eta = eta;
+    entry->Phi = momentum.Phi();
+    entry->ET = pt;
+    entry->E = momentum.E();
+    entry->Eem = candidate->Eem;
+    entry->Ehad = candidate->Ehad;
+    entry->Edges[0] = candidate->Edges[0];
+    entry->Edges[1] = candidate->Edges[1];
+    entry->Edges[2] = candidate->Edges[2];
+    entry->Edges[3] = candidate->Edges[3];
+
+    FillParticles(candidate, &entry->Particles);
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void TreeWriter::ProcessPhotons(ExRootTreeBranch *branch, TObjArray *array)
+{
+  TIter iterator(array);
+  Candidate *candidate = 0;
+  Photon *entry = 0;
+  Double_t pt, signPz, cosTheta, eta, rapidity;
+
+  array->Sort();
+
+  // loop over all photons
+  iterator.Reset();
+  while((candidate = static_cast<Candidate*>(iterator.Next())))
+  {
+    TIter it1(candidate->GetCandidates());
+    const TLorentzVector &momentum = candidate->Momentum;
+
+    pt = momentum.Pt();
+    cosTheta = TMath::Abs(momentum.CosTheta());
+    signPz = (momentum.Pz() >= 0.0) ? 1.0 : -1.0;
+    eta = (cosTheta == 1.0 ? signPz*999.9 : momentum.Eta());
+    rapidity = (cosTheta == 1.0 ? signPz*999.9 : momentum.Rapidity());
+
+    entry = static_cast<Photon*>(branch->NewEntry());
+
+    entry->Eta = eta;
+    entry->Phi = momentum.Phi();
+    entry->PT = pt;
+    entry->E = momentum.E();
+
+    entry->EhadOverEem = candidate->Eem > 0.0 ? candidate->Ehad/candidate->Eem : 999.9;
+
+    FillParticles(candidate, &entry->Particles);
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void TreeWriter::ProcessElectrons(ExRootTreeBranch *branch, TObjArray *array)
+{
+  TIter iterator(array);
+  Candidate *candidate = 0;
+  Electron *entry = 0;
+  Double_t pt, signPz, cosTheta, eta, rapidity;
+
+  array->Sort();
+
+  // loop over all electrons
+  iterator.Reset();
+  while((candidate = static_cast<Candidate*>(iterator.Next())))
+  {
+    const TLorentzVector &momentum = candidate->Momentum;
+
+    pt = momentum.Pt();
+    cosTheta = TMath::Abs(momentum.CosTheta());
+    signPz = (momentum.Pz() >= 0.0) ? 1.0 : -1.0;
+    eta = (cosTheta == 1.0 ? signPz*999.9 : momentum.Eta());
+    rapidity = (cosTheta == 1.0 ? signPz*999.9 : momentum.Rapidity());
+
+    entry = static_cast<Electron*>(branch->NewEntry());
+
+    entry->Eta = eta;
+    entry->Phi = momentum.Phi();
+    entry->PT = pt;
+
+    entry->Charge = candidate->Charge;
+
+    entry->EhadOverEem = 0.0;
+
+    entry->Particle = candidate->GetCandidates()->At(0);
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void TreeWriter::ProcessMuons(ExRootTreeBranch *branch, TObjArray *array)
+{
+  TIter iterator(array);
+  Candidate *candidate = 0;
+  Muon *entry = 0;
+  Double_t pt, signPz, cosTheta, eta, rapidity;
+
+  array->Sort();
+
+  // loop over all muons
+  iterator.Reset();
+  while((candidate = static_cast<Candidate*>(iterator.Next())))
+  {
+    const TLorentzVector &momentum = candidate->Momentum;
+
+    pt = momentum.Pt();
+    cosTheta = TMath::Abs(momentum.CosTheta());
+    signPz = (momentum.Pz() >= 0.0) ? 1.0 : -1.0;
+    eta = (cosTheta == 1.0 ? signPz*999.9 : momentum.Eta());
+    rapidity = (cosTheta == 1.0 ? signPz*999.9 : momentum.Rapidity());
+
+    entry = static_cast<Muon*>(branch->NewEntry());
+
+    entry->SetBit(kIsReferenced);
+    entry->SetUniqueID(candidate->GetUniqueID());
+
+    entry->Eta = eta;
+    entry->Phi = momentum.Phi();
+    entry->PT = pt;
+
+    entry->Charge = candidate->Charge;
+
+    entry->Particle = candidate->GetCandidates()->At(0);
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void TreeWriter::ProcessJets(ExRootTreeBranch *branch, TObjArray *array)
+{
+  TIter iterator(array);
+  Candidate *candidate = 0, *constituent = 0;
+  Jet *entry = 0;
+  Double_t pt, signPz, cosTheta, eta, rapidity;
+  Double_t ecalEnergy, hcalEnergy;
+
+  array->Sort();
+
+  // loop over all jets
+  iterator.Reset();
+  while((candidate = static_cast<Candidate*>(iterator.Next())))
+  {
+    TIter itConstituents(candidate->GetCandidates());
+    const TLorentzVector &momentum = candidate->Momentum;
+
+    pt = momentum.Pt();
+    cosTheta = TMath::Abs(momentum.CosTheta());
+    signPz = (momentum.Pz() >= 0.0) ? 1.0 : -1.0;
+    eta = (cosTheta == 1.0 ? signPz*999.9 : momentum.Eta());
+    rapidity = (cosTheta == 1.0 ? signPz*999.9 : momentum.Rapidity());
+
+    entry = static_cast<Jet*>(branch->NewEntry());
+
+    entry->Eta = eta;
+    entry->Phi = momentum.Phi();
+    entry->PT = pt;
+
+    entry->Mass = momentum.M();
+
+    entry->DeltaEta = candidate->DeltaEta;
+    entry->DeltaPhi = candidate->DeltaPhi;
+
+    entry->BTag = candidate->BTag;
+    entry->TauTag = candidate->TauTag;
+
+    entry->Charge = candidate->Charge;
+
+    itConstituents.Reset();
+    entry->Constituents.Clear();
+    ecalEnergy = 0.0;
+    hcalEnergy = 0.0;
+    while((constituent = static_cast<Candidate*>(itConstituents.Next())))
+    {
+      entry->Constituents.Add(constituent);
+      ecalEnergy += constituent->Eem;
+      hcalEnergy += constituent->Ehad;
+    }
+
+    entry->EhadOverEem = ecalEnergy > 0.0 ? hcalEnergy/ecalEnergy : 999.9;
+
+    FillParticles(candidate, &entry->Particles);
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void TreeWriter::ProcessMissingET(ExRootTreeBranch *branch, TObjArray *array)
+{
+  Candidate *candidate = 0;
+  MissingET *entry = 0;
+
+  // get the first entry
+  if((candidate = static_cast<Candidate*>(array->At(0))))
+  {
+    const TLorentzVector &momentum = candidate->Momentum;
+
+    entry = static_cast<MissingET*>(branch->NewEntry());
+
+    entry->Phi = (-momentum).Phi();
+    entry->MET = momentum.Pt();
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void TreeWriter::ProcessScalarHT(ExRootTreeBranch *branch, TObjArray *array)
+{
+  Candidate *candidate = 0;
+  ScalarHT *entry = 0;
+
+  // get the first entry
+  if((candidate = static_cast<Candidate*>(array->At(0))))
+  {
+    const TLorentzVector &momentum = candidate->Momentum;
+
+    entry = static_cast<ScalarHT*>(branch->NewEntry());
+
+    entry->HT = momentum.Pt();
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void TreeWriter::ProcessRho(ExRootTreeBranch *branch, TObjArray *array)
+{
+  Candidate *candidate = 0;
+  Rho *entry = 0;
+
+  // get the first entry
+  if((candidate = static_cast<Candidate*>(array->At(0))))
+  {
+    const TLorentzVector &momentum = candidate->Momentum;
+
+    entry = static_cast<Rho*>(branch->NewEntry());
+
+    entry->Rho = momentum.E();
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void TreeWriter::Process()
+{
+  TBranchMap::iterator itBranchMap;
+  ExRootTreeBranch *branch;
+  TProcessMethod method;
+  TObjArray *array;
+
+  for(itBranchMap = fBranchMap.begin(); itBranchMap != fBranchMap.end(); ++itBranchMap)
+  {
+    branch = itBranchMap->first;
+    method = itBranchMap->second.first;
+    array = itBranchMap->second.second;
+
+    (this->*method)(branch, array);
+  }
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/TreeWriter.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/TreeWriter.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/TreeWriter.h	(revision 5)
@@ -0,0 +1,67 @@
+#ifndef TreeWriter_h
+#define TreeWriter_h
+
+/** \class TreeWriter
+ *
+ *  Fills ROOT tree branches.
+ *
+ *  $Date: 2013-05-16 16:25:05 +0200 (Thu, 16 May 2013) $
+ *  $Revision: 1114 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+#include <map>
+
+class TClass;
+class TObjArray;
+class TRefArray;
+
+class Candidate;
+class ExRootTreeBranch;
+
+class TreeWriter: public DelphesModule
+{
+public:
+
+  TreeWriter();
+  ~TreeWriter();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  void FillParticles(Candidate *candidate, TRefArray *array);
+
+  void ProcessParticles(ExRootTreeBranch *branch, TObjArray *array);
+  void ProcessTracks(ExRootTreeBranch *branch, TObjArray *array);
+  void ProcessTowers(ExRootTreeBranch *branch, TObjArray *array);
+  void ProcessPhotons(ExRootTreeBranch *branch, TObjArray *array);
+  void ProcessElectrons(ExRootTreeBranch *branch, TObjArray *array);
+  void ProcessMuons(ExRootTreeBranch *branch, TObjArray *array);
+  void ProcessTauJets(ExRootTreeBranch *branch, TObjArray *array);
+  void ProcessJets(ExRootTreeBranch *branch, TObjArray *array);
+  void ProcessMissingET(ExRootTreeBranch *branch, TObjArray *array);
+  void ProcessScalarHT(ExRootTreeBranch *branch, TObjArray *array);
+  void ProcessRho(ExRootTreeBranch *branch, TObjArray *array);
+
+#ifndef __CINT__
+  typedef void (TreeWriter::*TProcessMethod)(ExRootTreeBranch *, TObjArray *); //!
+
+  typedef std::map< ExRootTreeBranch *, std::pair< TProcessMethod, TObjArray * > > TBranchMap; //!
+
+  TBranchMap fBranchMap; //!
+
+  std::map< TClass *, TProcessMethod > fClassMap; //!
+#endif
+
+  ClassDef(TreeWriter, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/modules/UniqueObjectFinder.cc
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/UniqueObjectFinder.cc	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/UniqueObjectFinder.cc	(revision 5)
@@ -0,0 +1,142 @@
+
+/** \class UniqueObjectFinder
+ *
+ *  Finds uniquely identified photons, electrons and jets.
+ *
+ *  $Date: 2013-02-22 23:00:02 +0100 (Fri, 22 Feb 2013) $
+ *  $Revision: 933 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "modules/UniqueObjectFinder.h"
+
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesFormula.h"
+
+#include "ExRootAnalysis/ExRootResult.h"
+#include "ExRootAnalysis/ExRootFilter.h"
+#include "ExRootAnalysis/ExRootClassifier.h"
+
+#include "TMath.h"
+#include "TString.h"
+#include "TFormula.h"
+#include "TRandom3.h"
+#include "TObjArray.h"
+#include "TDatabasePDG.h"
+#include "TLorentzVector.h"
+
+#include <algorithm> 
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+
+UniqueObjectFinder::UniqueObjectFinder()
+{
+}
+
+//------------------------------------------------------------------------------
+
+UniqueObjectFinder::~UniqueObjectFinder()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void UniqueObjectFinder::Init()
+{
+  // import arrays with output from other modules
+
+  ExRootConfParam param = GetParam("InputArray");
+  Long_t i, size;
+  const TObjArray *array;
+  TIterator *iterator;
+
+  size = param.GetSize();
+  for(i = 0; i < size/2; ++i)
+  {
+    array = ImportArray(param[i*2].GetString());
+    iterator = array->MakeIterator();
+
+    fInputMap[iterator] = ExportArray(param[i*2 + 1].GetString());;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void UniqueObjectFinder::Finish()
+{
+  map< TIterator *, TObjArray * >::iterator itInputMap;
+  TIterator *iterator;
+
+  for(itInputMap = fInputMap.begin(); itInputMap != fInputMap.end(); ++itInputMap)
+  {
+    iterator = itInputMap->first;
+
+    if(iterator) delete iterator;
+  }
+}
+
+//------------------------------------------------------------------------------
+
+void UniqueObjectFinder::Process()
+{
+  Candidate *candidate;
+  map< TIterator *, TObjArray * >::iterator itInputMap;
+  TIterator *iterator;
+  TObjArray *array;
+
+  // loop over all input arrays
+  for(itInputMap = fInputMap.begin(); itInputMap != fInputMap.end(); ++itInputMap)
+  {
+    iterator = itInputMap->first;
+    array = itInputMap->second;
+
+    // loop over all candidates
+    iterator->Reset();
+    while((candidate = static_cast<Candidate*>(iterator->Next())))
+    {
+      if(Unique(candidate, itInputMap))
+      {
+        array->Add(candidate);
+      }
+    }
+  }
+}
+
+//------------------------------------------------------------------------------
+
+Bool_t UniqueObjectFinder::Unique(Candidate *candidate, map< TIterator *, TObjArray * >::iterator itInputMap)
+{
+  Candidate *previousCandidate;
+  map< TIterator *, TObjArray * >::iterator previousItInputMap;
+  TObjArray *array;
+
+  // loop over previous arrays
+  for(previousItInputMap = fInputMap.begin(); previousItInputMap != itInputMap; ++previousItInputMap)
+  {
+    array = previousItInputMap->second;
+    TIter iterator(array);
+
+    // loop over all candidates
+    iterator.Reset();
+    while((previousCandidate = static_cast<Candidate*>(iterator.Next())))
+    {
+      if(candidate->Overlaps(previousCandidate))
+      {
+        return kFALSE;
+      }
+    }
+  }
+
+  return kTRUE;
+}
+
+//------------------------------------------------------------------------------
Index: trunk/Delphes/Delphes-3.0.9/modules/UniqueObjectFinder.h
===================================================================
--- trunk/Delphes/Delphes-3.0.9/modules/UniqueObjectFinder.h	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/modules/UniqueObjectFinder.h	(revision 5)
@@ -0,0 +1,44 @@
+#ifndef UniqueObjectFinder_h
+#define UniqueObjectFinder_h
+
+/** \class UniqueObjectFinder
+ *
+ *  Finds uniquely identified photons, electrons, taus and jets.
+ *
+ *  $Date: 2012-11-18 15:57:08 +0100 (Sun, 18 Nov 2012) $
+ *  $Revision: 814 $
+ *
+ *
+ *  \author P. Demin - UCL, Louvain-la-Neuve
+ *
+ */
+
+#include "classes/DelphesModule.h"
+
+#include <map>
+
+class TIterator;
+class TObjArray;
+class Candidate;
+
+class UniqueObjectFinder: public DelphesModule
+{
+public:
+
+  UniqueObjectFinder();
+  ~UniqueObjectFinder();
+
+  void Init();
+  void Process();
+  void Finish();
+
+private:
+
+  Bool_t Unique(Candidate *candidate, std::map< TIterator *, TObjArray * >::iterator itInputMap);
+
+  std::map< TIterator *, TObjArray * > fInputMap; //!
+
+  ClassDef(UniqueObjectFinder, 1)
+};
+
+#endif
Index: trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/AnalysisEvent.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/AnalysisEvent.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/AnalysisEvent.py	(revision 5)
@@ -0,0 +1,277 @@
+from inspect import getargspec
+from ROOT import TLorentzVector,TVector3,TChain,TClass,TDatabasePDG
+from datetime import datetime
+from collections import Iterable
+from types import StringTypes
+from os import path
+
+class AnalysisEvent(TChain):
+   """A class that complements fwlite::Events with analysis facilities.
+      The class provides the following additional functionalities:
+        1. instrumentation for event weight
+             A set of weight classes can be defined, and the event weight
+             is computed and cached using those.
+        2. list of event products used in the analysis
+             It makes the iteration faster by only enabling required branches.
+        3. a list of "producers" of analysis high-level quantities
+             It allows to run "analysis on demand", by automatically running
+             the defined producers to fill the cache, and later use that one.
+        4. a volatile dictionary
+             It allows to use the event as an heterogenous container for
+             any analysis product. The event is properly reset when iterating 
+             to the next event.
+   """
+
+   def __init__(self, inputFiles = '', maxEvents=0):
+     """Initialize the AnalysisEvent like a standard Event, plus additional features."""
+     # initialization of base functionalities
+     TChain.__init__(self,"Delphes","Delphes")
+     if isinstance(inputFiles,Iterable) and not isinstance(inputFiles,StringTypes):
+       for thefile in inputFiles:
+         if path.isfile(thefile): 
+           self.AddFile(thefile)
+         else:
+           print "Warning: ",thefile," do not exist."
+     elif  isinstance(inputFiles,StringTypes):
+       thefile = inputFiles
+       if path.isfile(thefile): 
+         self.AddFile(thefile)
+       else:
+         print "Warning: ",thefile," do not exist."
+     else:
+       print "Warning: invalid inputFiles"
+     self.BuildIndex("Event[0].Number")
+     self.SetBranchStatus("*",0)
+     self._eventCounts        = 0
+     self._maxEvents          = maxEvents
+     # additional features:
+     # 1. instrumentation for event weight
+     self._weightCache = {}
+     self._weightEngines = {}
+     # 2. a list of event products used in the analysis
+     self._collections = {} 
+     self._branches = dict((b,False) for b in map(lambda b:b.GetName(),self.GetListOfBranches()))
+     # 3. a list of "producers" of analysis high-level quantities
+     self._producers = {}
+     # 4. volatile dictionary. User can add any quantity to the event and it will be 
+     #    properly erased in the iteration step. 
+     self.__dict__["vardict"] = {}
+     
+   def addWeight(self, name, weightClass):
+     """Declare a new class (engine) to compute the weights.
+        weightClass must have a weight() method returning a float."""
+     if name in self._weightEngines:
+       raise KeyError("%s weight engine is already declared" % name)
+     self._weightEngines[name] = weightClass
+     self._weightCache.clear()
+
+   def delWeight(self, name):
+     """Remove one weight engine from the internal list."""
+     # just to clean the dictionnary
+     del self._weightEngines[name]
+     self._weightCache.clear()
+
+   def weight(self, weightList=None, **kwargs):
+     """Return the event weight. Arguments:
+         * weightList is the list of engines to use, as a list of strings. 
+              Default: all defined engines.
+         * the other named arguments are forwarded to the engines.
+        The output is the product of the selected individual weights."""
+     # first check in the cache if the result is there already
+     if weightList is None:
+       weightList=self._weightEngines.keys()
+     kwargs["weightList"] = weightList
+     # compute the weight or use the cached value
+     myhash = self._dicthash(kwargs)
+     if not myhash in self._weightCache : 
+       w = 1.
+       for weightElement in weightList:
+         engine = self._weightEngines[weightElement]
+         engineArgs = getargspec(engine.weight).args
+         subargs = dict((k,v) for k,v in kwargs.iteritems() if k in engineArgs)
+         w *= self._weightCache.setdefault("weightElement:%s # %s" %(weightElement,self._dicthash(subargs)),engine.weight(self,**subargs))
+       self._weightCache[myhash] = w
+     return self._weightCache[myhash]
+
+   def addCollection(self, name, inputTag):
+     """Register an event collection as used by the analysis.
+        Example: addCollection("myjets","jets") 
+        Note that the direct access to the branch is still possible but unsafe."""
+     if name in self._collections:
+       raise KeyError("%r collection is already declared", name)
+     if name in self._producers:
+       raise KeyError("%r is already declared as a producer", name)
+     if hasattr(self,name):
+       raise AttributeError("%r object already has attribute %r" % (type(self).__name__, name))
+     if inputTag not in self._branches:
+       raise AttributeError("%r object has no branch %r" % (type(self).__name__, inputTag))
+     self._collections[name] = inputTag
+     self.SetBranchStatus(inputTag+"*",1)
+     self._branches[inputTag] = True
+
+   def removeCollection(self,name):
+     """Forget about the named event collection.
+        This method will delete both the product from the cache (if any) and the definition.
+        To simply clear the cache, use "del event.name" instead. """
+     self.SetBranchStatus(self._collections[name]+"*",0)
+     self._branches[self._collections[name]] = False
+     del self._collections[name]
+     if name in self.vardict:
+       delattr(self,name)
+
+   def getCollection(self,name):
+     """Retrieve the event product or return the cached collection.
+        Note that the prefered way to get the collection is instead to access the "event.name" attribute."""
+     if not name in self._collections:
+       raise AttributeError("%r object has no attribute %r" % (type(self).__name__,name))
+     if not name in self.vardict:
+       self.vardict[name] = TChain.__getattr__(self,self._collections[name])
+     return getattr(self,name)
+
+   def addProducer(self,name,producer,**kwargs):
+     """Register a producer to create new high-level analysis objects."""
+     # sanity checks
+     if name in self._producers:
+       raise KeyError("%r producer is already declared", name)
+     if name in self._collections:
+       raise KeyError("%r is already declared as a collection", name)
+     if hasattr(self,name):
+       raise AttributeError("%r object already has attribute %r" % (type(self).__name__, attr))
+     # remove name and producer from kwargs
+     if "name" in kwargs: del kwargs["name"]
+     if "producer" in kwargs: del kwargs["producer"]
+     # store
+     self._producers[name] = (producer,kwargs)
+
+   def removeProducer(self,name):
+     """Forget about the producer.
+        This method will delete both the product from the cache (if any) and the producer.
+        To simply clear the cache, use "del event.name" instead."""
+     del self._producers[name]
+     if name in self.vardict:
+       delattr(self,name)
+
+   def event(self):
+     """Event number"""
+     if self._branches["Event"]:
+       return self.Event.At(0).Number
+     else:
+       return 0
+
+   def to(self,event):
+     """Jump to some event"""
+     self.GetEntryWithIndex(event)
+ 
+   def __getitem__(self,index):
+     """Jump to some event"""
+     self.GetEntryWithIndex(index)
+     return self
+
+   def __iter__ (self):
+     """Iterator"""
+     self._eventCounts = 0
+     while self.GetEntry(self._eventCounts):
+       self.vardict.clear()
+       self._weightCache.clear()
+       yield self
+       self._eventCounts += 1
+       if self._maxEvents > 0 and self._eventCounts >= self._maxEvents:
+         break
+
+   def __getattr__(self, attr):
+     """Overloaded getter to handle properly:
+          - volatile analysis objects
+          - event collections
+          - data producers"""
+     if attr in self.__dict__["vardict"]:
+       return self.vardict[attr]
+     if attr in self._collections:
+       return self.vardict.setdefault(attr, TChain.__getattr__(self,self._collections[attr]))
+     if attr in self._producers:
+       return self.vardict.setdefault(attr, self._producers[attr][0](self, **self._producers[attr][1]))
+     return TChain.__getattr__(self,attr)
+
+   def __setattr__(self, name, value):
+     """Overloaded setter that puts any new attribute in the volatile dict."""
+     if name in self.__dict__  or not "vardict" in self.__dict__ or name[0]=='_':
+       self.__dict__[name] = value
+     else:
+       if name in self._collections or name in self._producers:
+         raise AttributeError("%r object %r attribute is read-only (event collection)" % (type(self).__name__, name))
+       self.vardict[name] = value
+
+   def __delattr__(self, name):
+     """Overloaded del method to handle the volatile internal dictionary."""
+     if name=="vardict":
+       raise AttributeError("%r object has no attribute %r" % (type(self).__name__, name))
+     if name in self.__dict__:
+       del self.__dict__[name]
+     elif name in self.vardict:
+       del self.vardict[name]
+     else:
+       raise AttributeError("%r object has no attribute %r" % (type(self).__name__, name))
+
+   def _dicthash(self,dict):
+     return (lambda d,j='=',s=';': s.join([j.join((str(k),str(v))) for k,v in d.iteritems()]))(dict)
+
+   def __str__(self):
+     """Event text dump."""
+     dictjoin = lambda d,j=' => ',s='\n': s.join([j.join((str(k),str(v))) for k,v in d.iteritems()])
+     mystring = "=================================================================\n"
+     # general information
+     if self._branches["Event"]:
+       mystring += str(self.Event.At(0))
+     else:
+       mystring += "Event %d\n" % self.GetReadEvent()
+     mystring += "-----------------------------------------------------------------\n"
+     # weights
+     if len(self._weightCache)==0: 
+       mystring += "No weight computed so far. Default weight is %f.\n" % self.weight()
+     else:
+       mystring += "Weights:\n"
+       mystring += dictjoin(self._weightCache)
+     mystring += "\n-----------------------------------------------------------------\n"
+     # list the collections
+     mystring += "Collections:\n"
+     for colname in self._collections.keys():
+       collection = self.getCollection(colname)
+       if collection.GetEntries()>0:
+         if collection.At(0).IsA()==TClass.GetClass("HepMCEvent"):
+           pass
+         else:
+           mystring += "*** %s has %d element(s)\n" % (colname,collection.GetEntries())
+           mystring += reduce(lambda a,b: a+b,map(str,collection))
+     mystring += "\n-----------------------------------------------------------------\n"
+     # list the registered producers
+     mystring += "Producers:\n"
+     mystring += dictjoin(self._producers)
+     mystring += "\n-----------------------------------------------------------------\n"
+     # list the content of vardict, excluding collections
+     mystring += "Content of the cache:\n"
+     for k, v in self.vardict.iteritems():
+       if k in self._collections.keys() : continue
+       if isinstance(v,Iterable) and not isinstance(v,StringTypes):
+         try:
+           thisstring = "%s => vector of %d objects(s)\n" % (k,len(v))
+         except:
+           mystring += "%s => %s\n"%(k,str(v))
+         else:
+           try:
+             for it,vec in enumerate(v):
+               thisstring += "%s[%d] = %s\n"%(k,it,str(vec))
+           except: 
+             mystring += "%s => %s\n"%(k,str(v))
+           else:
+             mystring += thisstring
+       else:
+         mystring += "%s => %s\n"%(k,str(v))
+     return mystring
+
+   def decayTree(self, genparticles):
+     db = TDatabasePDG()
+     theString = ""
+     for part in genparticles:
+       if part.M1==-1 and part.M2==-1:
+         theString += part.printDecay(db, genparticles)
+     return theString
+
Index: trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/BaseControlPlots.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/BaseControlPlots.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/BaseControlPlots.py	(revision 5)
@@ -0,0 +1,166 @@
+#! /usr/bin/env python
+import ROOT 
+from CPconfig import configuration
+
+def getArgSet(controlplots):
+  assert isinstance(controlplots,list)
+  merged = ROOT.RooArgSet()
+  for ctrlplot in controlplots:
+    merged.add(ctrlplot._obsSet)
+  return merged
+
+def runTest(path='../testfiles/', controlPlots=None):
+  # these modules are only needed in that function, used for debugging.
+  # so we only import them here.
+  import Delphes
+  import os
+  import AnalysisEvent
+  import EventSelection
+  assert isinstance(controlPlots, BaseControlPlots)
+  if os.path.isdir(path):
+    dirList=os.listdir(path)
+    files=[]
+    for fname in dirList:
+      files.append(path+fname)
+  elif os.path.isfile(path):
+    files=[path]
+  else:
+    files=[]
+  events = AnalysisEvent.AnalysisEvent(files)
+  EventSelection.prepareAnalysisEvent(events)
+  controlPlots.beginJob()
+  i = 0
+  for event in events:
+    if i%100==0 : print "Processing... event ", i
+    controlPlots.processEvent(event)
+    i += 1
+  controlPlots.endJob()
+
+class BaseControlPlots:
+    """A class to create control plots"""
+    
+    def __init__(self, dir=None, purpose="generic", dataset=None, mode="plots"):
+      """Initialize the ControlPlots, creating output file if needed. If no file is given, it means it is delegated."""
+      self._mode = mode
+      self._purpose = purpose
+      # for plots
+      if self._mode=="plots":
+        # create output file if needed. If no file is given, it means it is delegated
+        if dir is None:
+          self._f = ROOT.TFile(configuration.defaultFilename+".root", "RECREATE")
+          self._dir = self._f.mkdir(purpose)
+        else :
+          self._f = None
+          self._dir = dir
+        self._h_vector = { }
+      # for ntuples
+      if self._mode=="dataset":
+        self._obsSet = ROOT.RooArgSet()
+        if dataset is None:
+          self._rds = ROOT.RooDataSet(configuration.RDSname, configuration.RDSname, self._obsSet)
+	  self._ownedRDS = True
+	else:
+	  self._rds = dataset
+	  self._ownedRDS = False
+        self._rrv_vector = { }
+        self._rooCategories = { }
+    
+    def beginJob(self):
+      """Declare histograms, and for derived classes instantiate handles. Must be overloaded.""" 
+      raise NotImplementedError
+
+    def defineCategories(self, categories):
+      """Define the categories, given a list of names. Only works for datasets"""
+      if self._mode!="dataset": return
+      for i, name in enumerate(categories):
+        rc = ROOT.RooCategory("rc_"+self._purpose+"_"+str(i),name.split('/')[-1])
+	rc.defineType("not_acc",0)
+	rc.defineType("acc",1)
+	self._rooCategories[i] = rc
+	self._rds.addColumn(rc)
+	self._obsSet.add(rc)
+
+    def addHisto(self,*args):
+      """Add one histograms to the list of products. Arguments are as for TH1F."""
+      # this fills a distionnary name <-> histogram
+      self._dir.cd()
+      self._h_vector[args[0]] = ROOT.TH1F(*args)
+
+    def addVariable(self,*args):
+      """Add one variable to the list of products. Arguments are as for RooRealVar."""
+      # this fills a distionnary name <-> RooRealVar
+      self._rrv_vector[args[0]] = ROOT.RooRealVar(self._purpose+args[0],*(args[1:]))
+      self._obsSet.add(self._rrv_vector[args[0]])
+      self._rds.addColumn(self._rrv_vector[args[0]])
+    
+    def add(self, *args):
+      """Add one item to the list of products. Arguments are as for TH1F."""
+      if self._mode=="plots":
+        self.addHisto(*args)
+      else:
+        self.addVariable(*[args[i] for i in [0,1,3,4]])
+
+    def processEvent(self, event, weight = 1.):
+      """process event and fill histograms"""
+      self.fill(self.process(event),weight)
+     
+    def process(self, event):
+      """Process event data to extract histogrammables. Must be overloaded."""
+      raise NotImplementedError
+      # this is just an example, we never get there
+      # that method must return a dictionnary name <-> value that matches self._h_vector
+      result = { }
+      result["var1"] = 1.
+      result["var2"] = 2.3
+      result["var3"] = 5.711
+      return result
+
+    def setCategories(self, categories):
+      """Set the categories, given a list of booleans. Only works for datasets"""
+      if self._mode!="dataset": return
+      for c, flag in enumerate(categories):
+        if flag: self._rooCategories[c].setIndex(1)
+	else: self._rooCategories[c].setIndex(0)
+
+    def fillPlots(self, data, weight = 1.):
+      """Fills histograms with the data provided as input."""
+      for name,value in data.items():
+        if isinstance(value,list):
+          for val in value: self._h_vector[name].Fill(val,weight)
+        else:
+          self._h_vector[name].Fill(value,weight)
+
+    def fillRDS(self, data):
+      """Fills roodataset with the data provided as input."""
+      for rrv in self._rrv_vector:
+        # data is not guaranteed to contain all variables,
+        # so if we don't do this, these variables will keep the old value
+        self._rrv_vector[rrv].setVal(-1000)
+      for name,value in data.items():
+        if isinstance(value,list):
+	  #for now, we only store scalars, not vectors
+	  pass
+        else:
+	  self._rrv_vector[name].setVal(value)
+      if self._ownedRDS:
+        self._rds.add(self._obsSet)  
+
+    def fill(self, data, weight = 1.):
+      """Fills whatever must be filled in"""
+      if self._mode=="plots":
+        self.fillPlots(data, weight)
+      else:
+        self.fillRDS(data)
+
+    def endJob(self):
+      """Save and close."""
+      if self._mode=="plots":
+        self._dir.cd()
+        self._dir.Write()
+        if not self._f is None:
+          self._f.Close()
+      else:
+        if self._ownedRDS:
+          ws  = ROOT.RooWorkspace(self._purpose,self._purpose)
+          getattr(ws,'import')(self._rds) 
+          ws.writeToFile(configuration.defaultFilename+"_"+self._purpose+".root") 
Index: trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/BaseWeightClass.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/BaseWeightClass.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/BaseWeightClass.py	(revision 5)
@@ -0,0 +1,10 @@
+# Every weight class must contain a weight method, taking as first argument the event.
+# Additional methods and arguments are allowed.
+# Note that weight classes do not have to derive from BaseWeightClass.
+
+class BaseWeightClass:
+  """A class to reweight AnalysisEvents"""
+  def weight( self, event):
+     """Lepton eff weight"""
+     raise NotImplementedError
+
Index: trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/CPconfig.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/CPconfig.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/CPconfig.py	(revision 5)
@@ -0,0 +1,41 @@
+#configuration of the ControlPlot machinery
+
+from collections import namedtuple
+controlPlot     = namedtuple("controlPlot",    ["label","module","classname","kwargs"])
+eventCollection = namedtuple("eventCollection",["label","collection"])
+eventProducer   = namedtuple("eventProducer",  ["label","module","function","kwargs"])
+eventWeight     = namedtuple("eventWeight",    ["label","module","classname","kwargs"])
+
+class configuration:
+  # default I/O
+  defaultFilename = "controlPlots"
+  RDSname = "rds_delphes"
+  WSname = "workspace_ras"
+
+  # mode: plots or dataset
+  runningMode = "plots"
+
+  # event selection class
+  eventSelection = ""
+
+  # control plot classes
+  controlPlots = [ ]
+
+  # event content: lists of eventCollection, eventProducer, and eventWeight objects respectively.
+  eventCollections = [ ]
+  eventProducers   = [ ]
+  eventWeights     = [ ]
+
+class eventDumpConfig:
+  # fine-tuning of the event content for display
+  productsToPrint   = [ ] # list of product to display (use the producer label)
+  collectionsToHide = [ ] # collections used in the analysis but not printed (use the collection label) 
+
+# import the actual implementation of the configuration
+import os
+theConfig = os.getenv("DelphesAnalysisCfg")
+if theConfig is not None:
+  configImplementation = __import__(os.path.splitext(theConfig)[0])
+  configuration = configImplementation.configuration
+  eventDumpConfig = configImplementation.eventDumpConfig
+
Index: trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/ControlPlots.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/ControlPlots.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/ControlPlots.py	(revision 5)
@@ -0,0 +1,211 @@
+#!/usr/bin/env python 
+
+#######################################################################################
+###  Option parsing and main routine  #################################################
+#######################################################################################
+
+from optparse import OptionParser
+import sys
+import os
+usage="""%prog [options]"""
+description="""A simple script to generate control plots."""
+epilog="""Example:
+./ControlPlots.py -i ./ -o controlPlots_demo.root --all
+"""
+parser = OptionParser(usage=usage,add_help_option=True,description=description,epilog=epilog)
+parser.add_option("-c", "--conf", dest="conf", default=None,
+                  help="Configuration file.")
+parser.add_option("-i", "--inputPath", dest="path",
+                  help="Read input file from DIR.", metavar="DIR")
+parser.add_option("-o", "--output", dest='outputname', default=None,
+                  help="Save output as FILE.", metavar="FILE")
+parser.add_option("--all",action="store_true",dest="all",
+                  help="Process all levels.")
+parser.add_option("-l", "--level", dest="levels",
+                  help="Specify a coma-separated list of levels to be processed. No space is allowed.")
+parser.add_option("--Njobs", type="int", dest='Njobs', default="1",
+                  help="Number of jobs when splitting the processing.")
+parser.add_option("--jobNumber", type="int", dest='jobNumber', default="0",
+                  help="Number of the job is a splitted set of jobs.")
+
+(options, args) = parser.parse_args()
+
+#special treatment of the config file... the rest of the options will be parsed in main.
+if options.conf is not None:
+  try:
+    theUserConf = __import__(os.path.splitext(options.conf)[0])
+  except:
+    raise ImportError("%s is not a valid configuration file."%options.conf)
+  else:
+    os.environ["DelphesAnalysisCfg"]=options.conf
+from CPconfig import configuration
+if options.outputname is None:
+  options.outputname = configuration.defaultFilename+".root"
+
+import Delphes
+import ROOT
+import itertools
+import time
+from importlib import import_module
+from AnalysisEvent import AnalysisEvent
+from BaseControlPlots import getArgSet
+import EventSelection
+import cProfile
+
+def main(options):
+  """simplistic program main"""
+  # do basic arg checking
+  if options.path is None: 
+    print "Error: no input path specified."
+    parser.print_help()
+    return
+  levels = []
+  if options.all:
+    levels = range(EventSelection.eventCategories())
+  elif not options.levels is None:
+    levels= map(int,options.levels.split(','))
+  levels.sort()
+  if len(levels)==0:
+    print "Error: no level specified for processing."
+    parser.print_help()
+    return
+  if min(levels)<0:
+    print "Error: levels must be positive integers."
+    parser.print_help()
+    return
+  if max(levels)>=EventSelection.eventCategories():
+    print "Error: last level is",EventSelection.eventCategories()-1
+    parser.print_help()
+    return
+  if options.Njobs<1:
+    print "Error: Njobs must be strictly positive."
+    parser.print_help()
+    return
+  if options.jobNumber>=options.Njobs:
+    print "Error: jobNumber must be strictly smaller than Njobs."
+    parser.print_help()
+    return
+  # if all ok, run the procedure
+  runAnalysis(path=options.path,outputname=options.outputname, levels=levels, Njobs=options.Njobs, jobNumber=options.jobNumber)
+
+#######################################################################################
+### Central Routine: manage input/output, loop on events, manage weights and plots  ###
+#######################################################################################
+
+def runAnalysis(path, levels, outputname="controlPlots.root", Njobs=1, jobNumber=1):
+  """produce all the plots in one go"""
+
+  # inputs
+  if os.path.isdir(path):
+    dirList=list(itertools.islice(os.listdir(path), jobNumber, None, Njobs))
+    files=[]
+    for fname in dirList:
+      files.append(path+"/"+fname)
+  elif os.path.isfile(path):
+    files=[path]
+  else:
+    files=[]
+
+  # output
+  output = ROOT.TFile(outputname, "RECREATE")
+  if configuration.runningMode=="dataset":
+    ROOT.RooAbsData.setDefaultStorageType(ROOT.RooAbsData.Tree)
+    rds = ROOT.RooDataSet(configuration.RDSname, configuration.RDSname, ROOT.RooArgSet())
+
+  # events iterator, plus configuration of standard collections and producers
+  events = AnalysisEvent(files)
+  EventSelection.prepareAnalysisEvent(events)
+
+  # prepare the plots
+  controlPlots=[]
+  if configuration.runningMode=="plots":
+    leafList = [None]*EventSelection.eventCategories()
+    createDirectory(EventSelection.categoriesHierarchy(), output, leafList)
+    for levelDir in leafList:
+      levelPlots=[]
+      for cp in configuration.controlPlots:
+        levelPlots.append(getattr(import_module(cp.module),cp.classname)(dir=levelDir.mkdir(cp.label),mode="plots"))
+      controlPlots.append(levelPlots)
+  else:
+    for cp in configuration.controlPlots:
+      controlPlots.append(getattr(import_module(cp.module),cp.classname)(dir=None, mode="dataset", dataset=rds))
+
+  # book histograms (separate iteration for clarity)
+  if configuration.runningMode=="plots":
+    for level in levels:
+     for conf,cp in zip(configuration.controlPlots,controlPlots[level]):
+       cp.beginJob(**conf.kwargs)
+  else:
+    for conf,cp in zip(configuration.controlPlots,controlPlots):
+      cp.beginJob(**conf.kwargs)
+    for cp in controlPlots[:1]:
+      cp.defineCategories(EventSelection.categoryNames)
+
+  # process events
+  i = 0
+  t0 = time.time()
+  for event in events:
+    # printout
+    if i%100==0 : 
+      print "Processing... event %d. Last batch in %f s." % (i,(time.time()-t0))
+      t0 = time.time()
+    if configuration.runningMode=="plots":
+      # loop on channels
+      plots = filter(lambda x: EventSelection.isInCategory(x,event.category) ,levels)
+      # process the event once (for the first level)
+      selectionPlotsData=[]
+      for level in plots[:1]:
+        for cp in controlPlots[level]:
+          selectionPlotsData.append(cp.process(event))
+      # fill the histograms
+      for level in plots:
+        for cp, data in zip(controlPlots[level],selectionPlotsData):
+          cp.fill(data, event.weight(category=level))
+    else:
+      for cp in controlPlots[:1]:
+        # set categories (first CP only)
+        cp.setCategories(map(lambda c:EventSelection.isInCategory(c, event.category),range(EventSelection.eventCategories())))
+      for cp in controlPlots:
+        # process event (all CP)
+        cp.processEvent(event)
+      # add to the dataset
+      rds.add(getArgSet(controlPlots))
+    i += 1
+
+  # save all
+  if configuration.runningMode=="plots":
+    for level in levels:
+     for cp in controlPlots[level]: 
+       cp.endJob()
+  else:
+   for cp in controlPlots: 
+     cp.endJob()
+
+  # for dataset, write the merged RDS to file
+  if configuration.runningMode=="dataset":
+    output.cd()
+    ws_ras = ROOT.RooWorkspace(configuration.WSname, configuration.WSname)
+    getattr(ws_ras,'import')(rds.get())
+    output.Add(ws_ras)
+    ws_ras.Write()
+    rds.tree().Write()
+  
+  # close the file
+  output.Close()
+
+def createDirectory(dirStructure, directory, leafList):
+  """Recursively creates the directories for the various stages"""
+  for key,item in dirStructure.iteritems():
+    if isinstance(item, dict):
+      createDirectory(item, directory.mkdir(key), leafList)
+    else:
+      leafList[item]=directory.mkdir("stage_"+str(item),key)
+
+#######################################################################################
+### Program bootstrap  ################################################################
+#######################################################################################
+
+if __name__ == "__main__":
+  main(options)
+  #cProfile.run('main(options)', 'controlPlots.prof')
+
Index: trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/Delphes.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/Delphes.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/Delphes.py	(revision 5)
@@ -0,0 +1,160 @@
+import ROOT
+import libPyROOT as _root
+ROOT.gSystem.Load("libDelphes")
+
+#####################################################
+### Definition of the string conversion methods   ###
+#####################################################
+
+def _Event__str__( self ):
+  theString = "Event number %i\n" % self.Number
+  theString += "Read in %f and processed in %f.\n" % (self.ReadTime, self.ProcTime)
+  return theString
+
+_root.MakeRootClass( "Event" ).__str__    = _Event__str__
+
+def _LHCOEvent__str__( self ):
+  theString = "Trigger word: %b\n" % self.Trigger
+  return theString
+
+_root.MakeRootClass( "LHCOEvent" ).__str__    = _LHCOEvent__str__
+
+def _LHEFEvent__str__( self ):
+  hepmcstr = "Process ID: %i\n" % self.ProcessID
+  hepmcstr += "ScalePDF = %f\n" % self.ScalePDF
+  hepmcstr += "Alpha QED = %f\n" % self.AlphaQED
+  hepmcstr += "Alpha DCQ = %f\n" % self.AlphaQCD
+  hepmcstr += "Event weight = %f\n" % self.Weight
+  return hepmcstr
+
+_root.MakeRootClass( "LHEFEvent" ).__str__    = _LHEFEvent__str__
+
+def _HepMCEvent__str__( self ):
+  hepmcstr = "Process ID: %i\n" % self.ProcessID
+  hepmcstr += "Energy scale: %f\n" % self.Scale
+  hepmcstr += "Alpha QED = %f\n" % self.AlphaQED
+  hepmcstr += "Alpha QCD = %f\n" % self.AlphaQCD
+  hepmcstr += "Number of multi parton interactions: %f\n" % self.MPI
+  hepmcstr += """Q-scale used in evaluation of PDFs (in GeV): %f\n""" % self.ScalePDF
+  hepmcstr += """Fraction of beam momentum carried by %i parton ("beam side"): %f\n""" % (self.ID1,self.X1)
+  hepmcstr += """Fraction of beam momentum carried by %i parton ("target side"): %f\n""" % (self.ID2,self.X2)
+  hepmcstr += "PDF (id1, x1, Q) = %f\n" % self.PDF1 
+  hepmcstr += "PDF (id2, x2, Q) = %f\n" % self.PDF2 
+  return hepmcstr
+
+_root.MakeRootClass( "HepMCEvent" ).__str__    = _HepMCEvent__str__
+
+def _GenParticle__str__( self ):
+  thestring =  "Particle HEP ID number = %d\n" % self.PID
+  thestring += "Particle status: %d\n" % self.Status
+  if self.IsPU: thestring += "That particle is from PU.\n"
+  thestring += "Particle 1st mother: %d\n" % self.M1
+  thestring += "Particle 2nd mother: %d\n" % self.M2
+  thestring += "Particle 1st daughter: %d\n" % self.D1
+  thestring += "Particle last daughter: %d\n" % self.D2
+  thestring += "(Px,Py,Pz,E) = (%f,%f,%f,%f)\n" % (self.Px,self.Py,self.Pz,self.E)
+  thestring += "(Pt,Eta,Phi) = (%f,%f,%f)\n" % (self.PT,self.Eta,self.Phi)
+  thestring += "Rapidity = %f\n" % self.Rapidity
+  thestring += "Charge: %d\n" % self.Charge
+  thestring += "Mass: %f\n" % self.Mass
+  thestring += "Vertex position: (x,y,z,t) = (%f,%f,%f,%f)\n" % (self.X,self.Y,self.Z,self.T)
+  return thestring
+
+_root.MakeRootClass( "GenParticle" ).__str__    = _GenParticle__str__
+
+def _GenParticle_printDecay( self, db, particles, pre="" ):
+  thestring = "%s (%f,%f,%f,%f) (status %d)\n" % (db.GetParticle(self.PID).GetName(),self.Px,self.Py,self.Pz,self.E, self.Status)
+  for daughter in range(self.D1,self.D2+1):
+    if daughter==-1: break
+    if daughter<self.D2 : thestring += "%s+->%s" % (pre,particles.At(daughter).printDecay(db,particles,pre+"|   "))
+    else: thestring += "%s+->%s" % (pre,particles.At(daughter).printDecay(db,particles,pre+"    "))
+  return thestring
+
+_root.MakeRootClass( "GenParticle" ).printDecay = _GenParticle_printDecay
+
+def _MissingET__str__( self ):
+  thestring =  "Mising transverse energy: %f\n" % self.MET
+  thestring += "Mising energy azimuthal angle: %f\n" % self.Phi
+  return thestring
+ 
+_root.MakeRootClass( "MissingET" ).__str__    = _MissingET__str__
+
+def _ScalarHT__str__( self ):
+  thestring = "Scalar sum of transverse momenta: %f\n" %self.HT
+
+_root.MakeRootClass( "ScalarHT" ).__str__    = _ScalarHT__str__
+
+def _Photon__str__( self ):
+  thestring = "(Pt,Eta,Phi) =(%f,%f,%f)\n" % (self.PT,self.Eta,self.Phi)
+  return thestring
+
+_root.MakeRootClass( "Photon" ).__str__    = _Photon__str__
+
+def _Electron__str__( self ):
+  thestring = "(Pt,Eta,Phi) =(%f,%f,%f)\n" % (self.PT,self.Eta,self.Phi)
+  thestring += "charge: %d\n" % self.Charge
+  return thestring 
+
+_root.MakeRootClass( "Electron" ).__str__    = _Electron__str__
+
+def _Muon__str__( self ):
+  thestring = "(Pt,Eta,Phi) =(%f,%f,%f)\n" % (self.PT,self.Eta,self.Phi)
+  thestring += "charge: %d\n" % self.Charge
+  return thestring 
+
+_root.MakeRootClass( "Muon" ).__str__    = _Muon__str__
+
+def _Jet__str__( self ):
+  thestring = "(Pt,Eta,Phi) =(%f,%f,%f)\n" % (self.PT,self.Eta,self.Phi)
+  thestring += "Charge: %d\n" % self.Charge
+  thestring += "Mass: %f\n" % self.Mass
+  if self.BTag: thestring += "This jet is b-tagged.\n"
+  if self.TauTag: thestring += "This jet is tagged as a tau-jet.\n" 
+  thestring += "Jet radius in (eta,phi) = (%f,%f)\n" % (self.DeltaEta,self.DeltaPhi)
+  thestring += "Number of constituents: %d\n" % self.Constituents.GetEntries()
+  thestring += "H/E ratio in the calorimeters: %f\n" % self.EhadOverEem
+  nch = 0
+  ech = 0.
+  for constit in self.Constituents:
+    if constit.Charge != 0:
+      fourvector = ROOT.TLorentzVector()
+      fourvector.SetPtEtaPhiM(constit.PT,constit.Eta,constit.Phi,0.)
+      nch += 1
+      ech += fourvector.E()
+  thestring += "Charged Energy fraction: %f\n" % (ech/self.P4().E())
+  thestring += "Charged Multiplicity: %d\n" % nch
+  return thestring
+
+_root.MakeRootClass( "Jet" ).__str__    = _Jet__str__
+
+def _Track__str__( self ):
+  thestring =  "Particle HEP ID number = %d\n" % self.PID
+  thestring += "(Pt,Eta,Phi) = (%f,%f,%f)\n" % (self.PT,self.Eta,self.Phi)
+  thestring += "Charge: %d\n" % self.Charge
+  thestring += "At calorimeter surface: (Pt,Eta,Phi) = (%f,%f,%f)\n" % (self.PT,self.EtaOuter,self.PhiOuter)
+  thestring += "Vertex position: (x,y,z) = (%f,%f,%f)\n" % (self.X,self.Y,self.Z)
+  thestring += "Position at calorimer surface: (x,y,z) = (%f,%f,%f)\n" % (self.XOuter,self.YOuter,self.ZOuter)
+  return thestring 
+
+_root.MakeRootClass( "Track" ).__str__    = _Track__str__
+
+def _Tower__str__( self):
+  thestring  = "(Et,Eta,Phi) = (%f,%f,%f)\n" % (self.ET,self.Eta,self.Phi)
+  thestring += "(E,Eem,Ehad) = (%f,%f,%f)\n" % (tower.E,tower.Eem,tower.Ehad)
+  thestring += "Edges: %f, %f, %f, %f\n" % (tower.Edges[0],tower.Edges[1],tower.Edges[2],tower.Edges[3])
+  return thestring
+
+_root.MakeRootClass( "Tower" ).__str__    = _Tower__str__
+
+#####################################################
+### Definition of additional ROOT methods         ###
+#####################################################
+
+def _lorentzVector__str__( self ):
+  theString =  "(pt, eta, phi) = (%f,%f,%f)\n" % (self.Pt(), self.Eta(), self.Phi())
+  theString += "mass = %f, p = %f, mt = %f\n"  % (self.M(), self.P(), self.Mt())
+  return theString
+
+_root.MakeRootClass( "TLorentzVector" ).__str__    = _lorentzVector__str__
+
+
Index: trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/DumpEventInfo.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/DumpEventInfo.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/DumpEventInfo.py	(revision 5)
@@ -0,0 +1,39 @@
+#!/usr/bin/env python 
+import os
+import ROOT
+import Delphes
+from AnalysisEvent import AnalysisEvent
+import EventSelection
+from CPconfig import configuration, eventDumpConfig
+
+def DumpEventInfo(event=None, eventNumber=None, path="./"):
+  """Dump informations about a given event"""
+  # in case no event is provided, find it using eventNumber
+  if event is None:
+    if eventNumber is None:
+      print "DumpEventInfo Error: either pass an event or an event number"
+      return
+    # find event based on run and event
+    if os.path.isdir(path):
+      dirList=os.listdir(path)
+      files=[]
+      for fname in dirList:
+        files.append(path+fname)
+    elif os.path.isfile(path):
+      files=[path]
+    else:
+      files=[]
+    events = AnalysisEvent(files)
+    EventSelection.prepareAnalysisEvent(events)
+    DumpEventInfo(events[eventNumber])
+    return
+  # run the producers when we want to print the outcome, and mute unneeded collections
+  for product in eventDumpConfig.productsToPrint: getattr(event,product)
+  for collection in eventDumpConfig.collectionsToHide: event.removeCollection(collection)
+  # Now, we can go on with the printing.
+  print event
+
+if __name__=="__main__":
+  import sys
+  DumpEventInfo(eventNumber=int(sys.argv[1]), path=sys.argv[2])
+
Index: trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/DumpEventList.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/DumpEventList.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/DumpEventList.py	(revision 5)
@@ -0,0 +1,35 @@
+#!/usr/bin/env python 
+import os
+import ROOT
+import Delphes
+from AnalysisEvent import AnalysisEvent
+import EventSelection
+
+def DumpEventList(category, path="./", output="eventlist.txt"):
+  """Dump a list of events in a given category"""
+  # input
+  if os.path.isdir(path):
+    dirList=os.listdir(path)
+    files=[]
+    for fname in dirList:
+      files.append(path+fname)
+  elif os.path.isfile(path):
+    files=[path]
+  else:
+    files=[]
+  # events
+  events = AnalysisEvent(files)
+  # output
+  event_list = open(output,"w")
+  # collections and producers used in the analysis
+  EventSelection.prepareAnalysisEvent(events)
+  for event in events:
+    # check category
+    if EventSelection.isInCategory(category, event.category):
+      # print
+      print >> event_list , "Event", event.event()
+
+if __name__=="__main__":
+  import sys
+  DumpEventList(int(sys.argv[1]), path=sys.argv[2], output="eventlist.txt")
+
Index: trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/EventSelection.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/EventSelection.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/EventSelection.py	(revision 5)
@@ -0,0 +1,61 @@
+from CPconfig import configuration
+from importlib import import_module
+
+# A proper implementation of the event selection will at least 
+# define the following:
+# - categoryNames (list of names of categories)
+# - eventCategory (category data producer)
+# - isInCategory (category definition, from category data)
+
+# the list of category names
+categoryNames = [ ]
+
+def eventCategory(event):
+  """Check analysis requirements for various steps
+     and return a tuple of data used to decide 
+     to what category an event belong """
+  raise NotImplementedError
+  return []
+
+def isInCategory(category, categoryData):
+  """Check if the event enters category X, given the tuple computed by eventCategory."""
+  raise NotImplementedError
+  return True
+
+# specific implementation of the "virtual methods" above
+EventSelectionImplementation = __import__(configuration.eventSelection)
+categoryNames  = EventSelectionImplementation.categoryNames
+eventCategory  = EventSelectionImplementation.eventCategory
+isInCategory   = EventSelectionImplementation.isInCategory
+
+# Functions below should not be touched in any implementation.
+
+def eventCategories():
+  """Return the number of catefories """
+  return len(categoryNames)
+
+def categoryName(category):
+  """Return the name of category x"""
+  if category<eventCategories() and category>=0: return categoryNames[category]
+  else: return "None"
+
+def categoriesHierarchy():
+  """Return a hierarchically organized list of categories"""
+  dct = {}
+  for i,item in enumerate(categoryNames):
+    p = dct
+    splitted = item.split('/')
+    for x in splitted[:-1]:
+      p = p.setdefault(x,{})
+    p[splitted[-1]] = i
+  return dct
+
+def prepareAnalysisEvent(event):
+  """Define collections and producers"""
+  for coll in configuration.eventCollections:
+    event.addCollection(coll.label,coll.collection)
+  for prod in configuration.eventProducers:
+    event.addProducer(prod.label,getattr(import_module(prod.module),prod.function),**prod.kwargs)
+  for weight in configuration.eventWeights:
+    events.addWeight(weight.label,getattr(import_module(weight.module),weight.classname)(**weight.kwargs))
+
Index: trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/EventSelectionControlPlots.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/EventSelectionControlPlots.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/EventSelectionControlPlots.py	(revision 5)
@@ -0,0 +1,42 @@
+import ROOT
+import sys
+import os
+from AnalysisEvent import AnalysisEvent
+from BaseControlPlots import BaseControlPlots
+from CPconfig import configuration
+import EventSelection
+
+# Requirements:
+# fully implemented EventSelection
+# categories stored as event.category
+
+class EventSelectionControlPlots(BaseControlPlots):
+    """A class to create control plots for event selection"""
+
+    def __init__(self, dir=None, dataset=None, mode="plots"):
+      # create output file if needed. If no file is given, it means it is delegated
+      BaseControlPlots.__init__(self, dir=dir, purpose="eventSelection", dataset=dataset, mode=mode)
+      self.eventCategories = EventSelection.eventCategories()
+ 
+    def beginJob(self):
+      # declare histograms
+      self.add("event","Event number",1000,0,100000)
+      self.add("category","event category",self.eventCategories+1,0,self.eventCategories+1)
+
+    def process(self, event):
+      """EventSelectionControlPlots"""
+      result = { }
+      ## event category
+      categoryData = event.category
+      result["category"] = [ ]
+      for category in range(self.eventCategories):
+        if EventSelection.isInCategory(category, categoryData):
+          result["category"].append(category)
+      result["event"] = event.event()
+      return result
+
+if __name__=="__main__":
+  import sys
+  from BaseControlPlots import runTest
+  runTest(sys.argv[1], EventSelectionControlPlots())
+
Index: trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/__init__.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/__init__.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/__init__.py	(revision 5)
@@ -0,0 +1,6 @@
+__all__ = [ "Delphes", 
+            "AnalysisEvent", 
+            "BaseControlPlots", "BaseWeightClass", 
+            "EventSelection", 
+            "EventSelectionControlPlots", 
+            "ControlPlots", "DumpEventInfo" ]
Index: trunk/Delphes/Delphes-3.0.9/python/JetControlPlots.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/JetControlPlots.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/JetControlPlots.py	(revision 5)
@@ -0,0 +1,57 @@
+from BaseControlPlots import BaseControlPlots
+
+# Requirements:
+# event.jets
+# event.bjets
+# event.MEt
+
+class JetControlPlots(BaseControlPlots):
+    """A class to create control plots for jetmet"""
+
+    def __init__(self, dir=None, dataset=None, mode="plots"):
+      # create output file if needed. If no file is given, it means it is delegated
+      BaseControlPlots.__init__(self, dir=dir, purpose="jetmet", dataset=dataset, mode=mode)
+
+    def beginJob(self):
+      # declare histograms
+      self.add("JetPt","Jet Pt",100,0,200)
+      self.add("JetEta","Jet Eta",100,-5,5)
+      self.add("JetPhi","Jet Phi",64,-3.2,3.2)
+      self.add("BjetPt","B Jet Pt",100,0,200)
+      self.add("BjetEta","B Jet Eta",100,-5,5)
+      self.add("BjetPhi","B Jet Phi",64,-3.2,3.2)
+      self.add("MET","MET",100,0,200)
+      self.add("METphi","MET phi",64,-3.2,3.2)
+      self.add("Njets","Jet multiplicity",10,0,10)
+      self.add("Nbjets","B Jet multiplicity",10,0,10)
+
+    def process(self, event):
+      #get information
+      result = { }
+      result["JetPt"] = [ ]
+      result["JetEta"] = [ ]
+      result["JetPhi"] = [ ]
+      result["BjetPt"] = [ ]
+      result["BjetEta"] = [ ]
+      result["BjetPhi"] = [ ]
+      nb=0
+      for jet in event.selectedJets:
+        result["JetPt"].append(jet.PT)
+        result["JetEta"].append(jet.Eta)
+        result["JetPhi"].append(jet.Phi)
+        if jet.BTag:
+          nb+=1
+          result["BjetPt"].append(jet.PT)
+          result["BjetEta"].append(jet.Eta)
+          result["BjetPhi"].append(jet.Phi)
+      result["Njets"]  = len(event.selectedJets)
+      result["Nbjets"] = nb
+      result["MET"] = event.MEt[0].MET
+      result["METphi"] = event.MEt[0].Phi
+      return result
+
+if __name__=="__main__":
+  import sys
+  from DelphesAnalysis.BaseControlPlots import runTest
+  runTest(sys.argv[1], JetControlPlots())
+
Index: trunk/Delphes/Delphes-3.0.9/python/LeptonControlPlots.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/LeptonControlPlots.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/LeptonControlPlots.py	(revision 5)
@@ -0,0 +1,44 @@
+from BaseControlPlots import BaseControlPlots
+
+# Requirements:
+# event.muons
+# event.electrons
+
+class LeptonControlPlots(BaseControlPlots):
+    """A class to create control plots for leptons"""
+
+    def __init__(self, dir=None, dataset=None, mode="plots"):
+      # create output file if needed. If no file is given, it means it is delegated
+      BaseControlPlots.__init__(self, dir=dir, purpose="leptons", dataset=dataset, mode=mode)
+
+    def beginJob(self):
+      # declare histograms
+      self.add("ElectronPt","Electron Pt",100,0,200)
+      self.add("MuonPt","Muon Pt",100,0,200)
+      self.add("ElectronEta","Electron Eta",50,-2.5,2.5)
+      self.add("MuonEta","Muon Eta",50,-2.5,2.5)
+      self.add("NMuons","Muon multiplicity",10,0,10)
+      self.add("NElectrons","Electron multiplicity",10,0,10)
+
+    def process(self, event):
+      #get information
+      result = { }
+      result["ElectronPt"] = [ ]
+      result["MuonPt"] = [ ]
+      result["ElectronEta"] = [ ]
+      result["MuonEta"] = [ ]
+      for mu in event.muons:
+        result["MuonPt"].append(mu.PT)
+        result["MuonEta"].append(mu.Eta)
+      for ele in event.electrons:
+        result["ElectronPt"].append(ele.PT)
+        result["ElectronEta"].append(ele.Eta)
+      result["NMuons"] = event.muons.GetEntries()
+      result["NElectrons"] = event.electrons.GetEntries()
+      return result
+
+if __name__=="__main__":
+  import sys
+  from DelphesAnalysis.BaseControlPlots import runTest
+  runTest(sys.argv[1], LeptonControlPlots())
+
Index: trunk/Delphes/Delphes-3.0.9/python/README
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/README	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/README	(revision 5)
@@ -0,0 +1,41 @@
+Explaining DelphesAnalysis:
+AnalysisEvent.py -> main event class
+EventSelection.py -> definition of event categories. Must be complemented for a real analysis
+BaseControlPlots.py -> to be subclassed for each part of the analysis. Std schema: beginJob, process, endJob
+BaseWeightClass.py -> to be subclassed for each event weight
+ControlPlots.py -> main program. 
+DumpEventInfo.py -> dump info about a given event.
+CPconfig.py -> definition of all the components of the analysis. It sources a file provided with the configuration of each analysis.
+
+what should be touched to implement an example?
+     * config.py (name given as argument of ControlPlots or set as DelphesAnalysisCfg env var.
+     * specific EventSelection class
+     * specific controlPlots class(es)
+
+In the present directory, there are two examples:
+ * Simple analysis.
+  - simpleConfig.py
+  - SimpleEventSelection.py
+  - LeptonControlPlots.py
+* Basic ttbar analysis
+  - topConfig.py
+  - TtbarEventSelection.py
+  - TopReconstruction.py
+  - JetControlPlots.py
+  - LeptonControlPlots.py
+  - TopControlPlots.py
+
+Commands (starting in Delphes ROOT directory):
+
+# setup path
+. ./DelphesEnv.sh
+cd python
+# run the analysis
+DelphesAnalysis/ControlPlots.py -i ../files/ -o controlPlots_demo.root --all -c topConfig.py
+# dump a list of events in category 5 (ttbar candidates)
+export DelphesAnalysisCfg="topConfig.py"
+python DelphesAnalysis/DumpEventList.py 5 ../delphes_output.root 
+# for each of them, print details
+for i in `cat eventlist.txt| cut -d' ' -f 2`; { python DelphesAnalysis/DumpEventInfo.py $i ../delphes_output.root; }
+
+
Index: trunk/Delphes/Delphes-3.0.9/python/SimpleEventSelection.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/SimpleEventSelection.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/SimpleEventSelection.py	(revision 5)
@@ -0,0 +1,53 @@
+#very simple EventSelection class aimed at demonstrating the 
+#typical implementation of an EventSelection class
+
+#On purpose, the categories are not in any "logical" order, and there is some redundant check when testing the category.
+#This is mostly for illustration.
+
+# requirements:
+#   event.muons
+#   event.electrons
+#   event.jets
+
+# the list of category names
+categoryNames = [ "MuonChannel/SingleMuon", "ElectronChannel/SingleElectron", "ElectronChannel/Jet", "MuonChannel/DoubleMuon", "ElectronChannel/DoubleElectron" ]
+
+def eventCategory(event):
+  """Check analysis requirements for various steps
+     and return a tuple of data used to decide 
+     to what category an event belong """
+  categoryData = [ ]
+  # 0: number of muons
+  categoryData.append(event.muons.GetEntries())
+  # 1: number of electrons
+  categoryData.append(event.electrons.GetEntries())
+  # 2: number of jets
+  categoryData.append(event.jets.GetEntries())
+  # 3: Pt of the leading muon > 2GeV
+  if event.muons.GetEntries():
+    categoryData.append(event.muons[0].PT>1.)
+  else:
+    categoryData.append(False)
+  # 4: Pt of the leading electron > 2 GeV
+  if event.electrons.GetEntries():
+    categoryData.append(event.electrons[0].PT>1.)
+  else:
+    categoryData.append(False)
+  # DONE
+  return categoryData
+
+def isInCategory(category, categoryData):
+  """Check if the event enters category X, given the tuple computed by eventCategory."""
+  if category==0:
+    return categoryData[0]>0 
+  elif category==1:
+    return categoryData[1]>0
+  elif category==2:
+    return categoryData[2]>0
+  elif category==3:
+    return isInCategory(0,categoryData) and categoryData[3]==True
+  elif category==4:
+    return isInCategory(1,categoryData) and categoryData[4]==True
+  else:
+    return False
+
Index: trunk/Delphes/Delphes-3.0.9/python/TopControlPlots.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/TopControlPlots.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/TopControlPlots.py	(revision 5)
@@ -0,0 +1,66 @@
+from BaseControlPlots import BaseControlPlots
+import ROOT
+
+# Requirements:
+#   event.topCandidates_L
+#   event.topCandidates_H
+#   event.topPairCandidates
+
+class TopControlPlots(BaseControlPlots):
+    """A class to create control plots for jetmet"""
+
+    def __init__(self, dir=None, dataset=None, mode="plots"):
+      # create output file if needed. If no file is given, it means it is delegated
+      BaseControlPlots.__init__(self, dir=dir, purpose="top", dataset=dataset, mode=mode)
+
+    def beginJob(self):
+      # declare histograms
+      self.add("Hmass","hadronic top mass",1000,0,1000)
+      self.add("Hpt","hadronic top transverse momentum",1000,0,1000)
+      self.add("bestHmass","hadronic top mass",1000,0,1000)
+      self.add("bestHpt","Hadronic top transverse momentum",1000,0,1000)
+      self.add("bestLmass","leptonic top transverse mass",1000,0,1000)
+      self.add("bestLpt","leptonic top transverse momentum",1000,0,1000)
+      self.add("mass1","hadronic top mass",1000,0,1000)
+      self.add("pt1","hadronic top transverse momentum",1000,0,1000)
+      self.add("mass2","leptonic top transverse mass",1000,0,1000)
+      self.add("pt2","leptonic top transverse momentum",1000,0,1000)
+
+    def process(self, event):
+      #get information
+      result = { }
+      result["Hmass"] = [ ]
+      result["Hpt"] = [ ]
+      for top in event.topCandidates_H:
+        result["Hmass"].append((top[0].P4()+top[1].P4()+top[2].P4()).M())
+        result["Hpt"].append((top[0].P4()+top[1].P4()+top[2].P4()).Pt())
+      if len(event.topCandidates_H):
+        top = event.topCandidates_H[0]
+        result["bestHmass"] = (top[0].P4()+top[1].P4()+top[2].P4()).M()
+        result["bestHpt"] = (top[0].P4()+top[1].P4()+top[2].P4()).Pt()
+      if len(event.topCandidates_L):
+        top = event.topCandidates_L[0]
+        met = ROOT.TLorentzVector()
+        met.SetPtEtaPhiE(top[2].MET,0,top[2].Phi,top[2].MET)
+        momentum = top[0].P4()+top[1].P4()+met
+        momentum.SetPz(0)
+        result["bestLmass"] = momentum.M()
+        result["bestLpt"] = momentum.Pt()
+      if len(event.topPairCandidates):
+        top = event.topPairCandidates[0][:3]
+        result["mass1"] = (top[0].P4()+top[1].P4()+top[2].P4()).M()
+        result["pt1"] = (top[0].P4()+top[1].P4()+top[2].P4()).Pt()
+        top = event.topPairCandidates[0][3:]
+        met = ROOT.TLorentzVector()
+        met.SetPtEtaPhiE(top[2].MET,0,top[2].Phi,top[2].MET)
+        momentum = top[0].P4()+top[1].P4()+met
+        momentum.SetPz(0)
+        result["mass2"] = momentum.M()
+        result["pt2"] =momentum.Pt()
+      return result
+
+if __name__=="__main__":
+  import sys
+  from DelphesAnalysis.BaseControlPlots import runTest
+  runTest(sys.argv[1], TopControlPlots())
+
Index: trunk/Delphes/Delphes-3.0.9/python/TopReconstruction.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/TopReconstruction.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/TopReconstruction.py	(revision 5)
@@ -0,0 +1,57 @@
+from itertools import combinations
+
+def jetSelection(event, ptcut=20., etacut=2.4):
+  def jetfilter(jet): return jet.PT>ptcut and abs(jet.Eta)<etacut
+  return filter(jetfilter,event.jets)
+
+def bjets(event):
+  def jetfilter(jet): return jet.BTag
+  return filter(jetfilter,event.selectedJets)
+
+def ljets(event):
+  def jetfilter(jet): return jet.BTag==0
+  return filter(jetfilter,event.selectedJets)
+
+def topCandidates(event,leptonic=True,hadronic=True):
+  electrons = event.electrons
+  muons = event.muons
+  ljets = event.lJets
+  bjets = event.bJets
+  met = event.MEt[0]
+  output = []
+  # leptonic top candidates: lepton + bjet + MET
+  if leptonic and not hadronic:
+    # build all combinations
+    for b in bjets:
+      for l in electrons:
+        output.append( (l,b,met) )
+      for l in muons:
+        output.append( (l,b,met) )
+    # no specific order
+    return output
+  # hadronic top candidates: 2 jets + bjet
+  if hadronic and not leptonic:
+    # build all combinations
+    for j in combinations(ljets,2):
+      for b in bjets:
+        output.append( (j[0], j[1], b) )
+    # order by distance to top mass
+    def massDistance(top):
+      mass = (top[0].P4()+top[1].P4()+top[2].P4()).M()
+      return abs(mass-172.9)
+    return sorted(output,key=massDistance)
+  # full event reconstruction
+  if hadronic and leptonic:
+    # build all combinations
+    for j in combinations(ljets,2):
+      for b in combinations(bjets,2):
+        for l in electrons:
+          output.append( (j[0], j[1], b[0], l, b[1], met) )
+        for l in muons:
+          output.append( (j[0], j[1], b[0], l, b[1], met) )
+    # find the best ones: order via hadronic top mass
+    def massDistance(top):
+      mass = (top[0].P4()+top[1].P4()+top[2].P4()).M()
+      return abs(mass-172.9)
+    return sorted(output,key=massDistance)
+
Index: trunk/Delphes/Delphes-3.0.9/python/TtbarEventSelection.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/TtbarEventSelection.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/TtbarEventSelection.py	(revision 5)
@@ -0,0 +1,66 @@
+# basic selection for semi-leptonic ttbar events
+
+# requirements:
+#   event.muons
+#   event.electrons
+#   event.jets
+#   event.selectedJets
+#   event.bJets
+#   event.topCandidates_L
+#   event.topCandidates_H
+#   event.topPairCandidates
+
+# the list of category names
+categoryNames = [ "l4j", "withPtCuts", "withBtag", "LeptonicTopCandidate", "HadronicTopCandidate", "TtbarCandidate" ]
+
+def eventCategory(event):
+  """Check analysis requirements for various steps
+     and return a tuple of data used to decide 
+     to what category an event belong """
+  categoryData = [ ]
+  # 0: number of muons
+  categoryData.append(event.muons.GetEntries())
+  # 1: number of electrons
+  categoryData.append(event.electrons.GetEntries())
+  # 2: number of jets
+  categoryData.append(event.jets.GetEntries())
+  # 3: Pt of the leading muon 
+  if event.muons.GetEntries():
+    categoryData.append(event.muons[0].PT)
+  else:
+    categoryData.append(0.)
+  # 4: Pt of the leading electron 
+  if event.electrons.GetEntries():
+    categoryData.append(event.electrons[0].PT)
+  else:
+    categoryData.append(0.)
+  # 5: number of selected jets
+  categoryData.append(len(event.selectedJets))
+  # 6: number of bjets
+  categoryData.append(len(event.bJets))
+  # 7: leptonic top candidate
+  categoryData.append(len(event.topCandidates_L))
+  # 8: hadronic top candidate
+  categoryData.append(len(event.topCandidates_H))
+  # 9: top pairs
+  categoryData.append(len(event.topPairCandidates))
+  # DONE
+  return categoryData
+
+def isInCategory(category, categoryData):
+  """Check if the event enters category X, given the tuple computed by eventCategory."""
+  if category==0:
+    return (categoryData[0]>0 or categoryData[1]>0) and categoryData[2]>=4
+  elif category==1:
+    return isInCategory(0,categoryData) and (categoryData[3]>15 or categoryData[4]>15) and categoryData[5]>=4
+  elif category==2:
+    return isInCategory(1,categoryData) and categoryData[6]>=2
+  elif category==3:
+    return isInCategory(2,categoryData) and categoryData[7]>0
+  elif category==4:
+    return isInCategory(2,categoryData) and categoryData[8]>0
+  elif category==5:
+    return isInCategory(2,categoryData) and categoryData[9]>0
+  else:
+    return False
+
Index: trunk/Delphes/Delphes-3.0.9/python/simpleConfig.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/simpleConfig.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/simpleConfig.py	(revision 5)
@@ -0,0 +1,39 @@
+#configuration of the ControlPlot machinery
+
+from collections import namedtuple
+controlPlot     = namedtuple("controlPlot",    ["label","module","classname","kwargs"])
+eventCollection = namedtuple("eventCollection",["label","collection"])
+eventProducer   = namedtuple("eventProducer",  ["label","module","function","kwargs"])
+eventWeight     = namedtuple("eventWeight",    ["label","module","classname","kwargs"])
+
+class configuration:
+  # default I/O
+  defaultFilename = "controlPlots"
+  RDSname = "rds_delphes"
+  WSname = "workspace_ras"
+
+  # mode: plots or dataset
+  runningMode = "plots"
+  #runningMode = "dataset"
+
+  # event selection class
+  eventSelection = "SimpleEventSelection"
+
+  # control plot classes
+  controlPlots = [ controlPlot("selection","EventSelectionControlPlots","EventSelectionControlPlots", { }),
+                   controlPlot("leptons","LeptonControlPlots","LeptonControlPlots", { }) ]
+
+  # event content: lists of eventCollection, eventProducer, and eventWeight objects respectively.
+  eventCollections = [ eventCollection("genEvent","Event"),
+                       eventCollection("muons","EFlowMuon"), 
+                       eventCollection("electrons","Electron"), 
+                       eventCollection("jets","Jet"),
+                       eventCollection("tracks","Track")] 
+  eventProducers   = [ eventProducer("category","SimpleEventSelection","eventCategory",{ }) ] 
+  eventWeights     = [ ]
+
+class eventDumpConfig:
+  # fine-tuning of the event content for display
+  productsToPrint   = [ "category" ] # list of product to display (use the producer label)
+  collectionsToHide = [ "tracks" ] # collections used in the analysis but not printed (use the collection label) 
+
Index: trunk/Delphes/Delphes-3.0.9/python/topConfig.py
===================================================================
--- trunk/Delphes/Delphes-3.0.9/python/topConfig.py	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/python/topConfig.py	(revision 5)
@@ -0,0 +1,50 @@
+#configuration of the ControlPlot machinery
+
+from collections import namedtuple
+controlPlot     = namedtuple("controlPlot",    ["label","module","classname","kwargs"])
+eventCollection = namedtuple("eventCollection",["label","collection"])
+eventProducer   = namedtuple("eventProducer",  ["label","module","function","kwargs"])
+eventWeight     = namedtuple("eventWeight",    ["label","module","classname","kwargs"])
+
+class configuration:
+  # default I/O
+  defaultFilename = "controlPlots_ttbar"
+  RDSname = "rds_delphes_ttbar"
+  WSname = "workspace_ras_ttbar"
+
+  # mode: plots or dataset
+  runningMode = "plots"
+  #runningMode = "dataset"
+
+  # event selection class
+  eventSelection = "TtbarEventSelection"
+
+  # control plot classes
+  controlPlots = [ controlPlot("selection","EventSelectionControlPlots","EventSelectionControlPlots", { }),
+                   controlPlot("leptons","LeptonControlPlots","LeptonControlPlots", { }),
+                   controlPlot("jets","JetControlPlots","JetControlPlots", { }),
+                   controlPlot("top","TopControlPlots","TopControlPlots", { }) 
+                 ]
+
+  # event content: lists of eventCollection, eventProducer, and eventWeight objects respectively.
+  eventCollections = [ eventCollection("genEvent","Event"),
+                       eventCollection("muons","Muon"), 
+                       eventCollection("electrons","Electron"), 
+                       eventCollection("jets","Jet"),
+                       eventCollection("MEt","MissingET")
+                     ] 
+  eventProducers   = [ eventProducer("category","TtbarEventSelection","eventCategory",{ }),
+                       eventProducer("selectedJets","TopReconstruction","jetSelection",{ "ptcut":20., "etacut":2.4 }),
+                       eventProducer("bJets","TopReconstruction","bjets",{}),
+                       eventProducer("lJets","TopReconstruction","ljets",{}),
+                       eventProducer("topCandidates_L","TopReconstruction","topCandidates",{"leptonic":True,"hadronic":False}),
+                       eventProducer("topCandidates_H","TopReconstruction","topCandidates",{"leptonic":False,"hadronic":True}),
+                       eventProducer("topPairCandidates","TopReconstruction","topCandidates",{"leptonic":True,"hadronic":True})
+                     ] 
+  eventWeights     = [ ]
+
+class eventDumpConfig:
+  # fine-tuning of the event content for display
+  productsToPrint   = [ "category", "topPairCandidates" ] # list of product to display (use the producer label)
+  collectionsToHide = [ ] # collections used in the analysis but not printed (use the collection label) 
+
Index: trunk/Delphes/Delphes-3.0.9/readers/DelphesHepMC.cpp
===================================================================
--- trunk/Delphes/Delphes-3.0.9/readers/DelphesHepMC.cpp	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/readers/DelphesHepMC.cpp	(revision 5)
@@ -0,0 +1,203 @@
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+#include <signal.h>
+
+#include "TROOT.h"
+#include "TApplication.h"
+
+#include "TFile.h"
+#include "TObjArray.h"
+#include "TStopwatch.h"
+#include "TDatabasePDG.h"
+#include "TParticlePDG.h"
+#include "TLorentzVector.h"
+
+#include "modules/Delphes.h"
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesHepMCReader.h"
+
+#include "ExRootAnalysis/ExRootTreeWriter.h"
+#include "ExRootAnalysis/ExRootTreeBranch.h"
+#include "ExRootAnalysis/ExRootProgressBar.h"
+
+using namespace std;
+
+//---------------------------------------------------------------------------
+
+static bool interrupted = false;
+
+void SignalHandler(int sig)
+{
+  interrupted = true;
+}
+
+//---------------------------------------------------------------------------
+
+int main(int argc, char *argv[])
+{
+  char appName[] = "DelphesHepMC";
+  stringstream message;
+  FILE *inputFile = 0;
+  TFile *outputFile = 0;
+  TStopwatch readStopWatch, procStopWatch;
+  ExRootTreeWriter *treeWriter = 0;
+  ExRootTreeBranch *branchEvent = 0;
+  ExRootConfReader *confReader = 0;
+  Delphes *modularDelphes = 0;
+  DelphesFactory *factory = 0;
+  TObjArray *stableParticleOutputArray = 0, *allParticleOutputArray = 0, *partonOutputArray = 0;
+  DelphesHepMCReader *reader = 0;
+  Int_t i;
+  Long64_t length, eventCounter;
+
+  if(argc < 3)
+  {
+    cout << " Usage: " << appName << " config_file" << " output_file" << " [input_file(s)]" << endl;
+    cout << " config_file - configuration file in Tcl format," << endl;
+    cout << " output_file - output file in ROOT format," << endl;
+    cout << " input_file(s) - input file(s) in HepMC format," << endl;
+    cout << " with no input_file, or when input_file is -, read standard input." << endl;
+    return 1;
+  }
+
+  signal(SIGINT, SignalHandler);
+
+  gROOT->SetBatch();
+
+  int appargc = 1;
+  char *appargv[] = {appName};
+  TApplication app(appName, &appargc, appargv);
+
+  try
+  {
+    outputFile = TFile::Open(argv[2], "CREATE");
+
+    if(outputFile == NULL)
+    {
+      message << "can't create output file " << argv[2];
+      throw runtime_error(message.str());
+    }
+
+    treeWriter = new ExRootTreeWriter(outputFile, "Delphes");
+
+    branchEvent = treeWriter->NewBranch("Event", HepMCEvent::Class());
+
+    confReader = new ExRootConfReader;
+    confReader->ReadFile(argv[1]);
+
+    modularDelphes = new Delphes("Delphes");
+    modularDelphes->SetConfReader(confReader);
+    modularDelphes->SetTreeWriter(treeWriter);
+
+    factory = modularDelphes->GetFactory();
+    allParticleOutputArray = modularDelphes->ExportArray("allParticles");
+    stableParticleOutputArray = modularDelphes->ExportArray("stableParticles");
+    partonOutputArray = modularDelphes->ExportArray("partons");
+
+    reader = new DelphesHepMCReader;
+
+    modularDelphes->InitTask();
+
+    i = 3;
+    do
+    {
+      if(interrupted) break;
+
+      if(i == argc || strncmp(argv[i], "-", 2) == 0)
+      {
+        cout << "** Reading standard input" << endl;
+        inputFile = stdin;
+        length = -1;
+      }
+      else
+      {
+        cout << "** Reading " << argv[i] << endl;
+        inputFile = fopen(argv[i], "r");
+
+        if(inputFile == NULL)
+        {
+          message << "can't open " << argv[i];
+          throw runtime_error(message.str());
+        }
+
+        fseek(inputFile, 0L, SEEK_END);
+        length = ftello(inputFile);
+        fseek(inputFile, 0L, SEEK_SET);
+
+        if(length <= 0)
+        {
+          fclose(inputFile);
+          ++i;
+          continue;
+        }
+      }
+
+      reader->SetInputFile(inputFile);
+
+      ExRootProgressBar progressBar(length);
+
+      // Loop over all objects
+      eventCounter = 0;
+      treeWriter->Clear();
+      modularDelphes->Clear();
+      reader->Clear();
+      readStopWatch.Start();
+      while(reader->ReadBlock(factory, allParticleOutputArray,
+        stableParticleOutputArray, partonOutputArray) && !interrupted)
+      {
+        if(reader->EventReady())
+        {
+          ++eventCounter;
+
+          readStopWatch.Stop();
+          procStopWatch.Start();
+          modularDelphes->ProcessTask();
+          procStopWatch.Stop();
+
+          reader->AnalyzeEvent(branchEvent, eventCounter, &readStopWatch, &procStopWatch);
+
+          treeWriter->Fill();
+
+          treeWriter->Clear();
+          modularDelphes->Clear();
+          reader->Clear();
+
+          readStopWatch.Start();
+        }
+        progressBar.Update(ftello(inputFile), eventCounter);
+      }
+
+      fseek(inputFile, 0L, SEEK_END);
+      progressBar.Update(ftello(inputFile), eventCounter, kTRUE);
+      progressBar.Finish();
+
+      if(inputFile != stdin) fclose(inputFile);
+
+      ++i;
+    }
+    while(i < argc);
+
+    modularDelphes->FinishTask();
+    treeWriter->Write();
+
+    cout << "** Exiting..." << endl;
+
+    delete reader;
+    delete modularDelphes;
+    delete confReader;
+    delete treeWriter;
+    delete outputFile;
+
+    return 0;
+  }
+  catch(runtime_error &e)
+  {
+    if(treeWriter) delete treeWriter;
+    if(outputFile) delete outputFile;
+    cerr << "** ERROR: " << e.what() << endl;
+    return 1;
+  }
+}
Index: trunk/Delphes/Delphes-3.0.9/readers/DelphesLHEF.cpp
===================================================================
--- trunk/Delphes/Delphes-3.0.9/readers/DelphesLHEF.cpp	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/readers/DelphesLHEF.cpp	(revision 5)
@@ -0,0 +1,203 @@
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+#include <signal.h>
+
+#include "TROOT.h"
+#include "TApplication.h"
+
+#include "TFile.h"
+#include "TObjArray.h"
+#include "TStopwatch.h"
+#include "TDatabasePDG.h"
+#include "TParticlePDG.h"
+#include "TLorentzVector.h"
+
+#include "modules/Delphes.h"
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesLHEFReader.h"
+
+#include "ExRootAnalysis/ExRootTreeWriter.h"
+#include "ExRootAnalysis/ExRootTreeBranch.h"
+#include "ExRootAnalysis/ExRootProgressBar.h"
+
+using namespace std;
+
+//---------------------------------------------------------------------------
+
+static bool interrupted = false;
+
+void SignalHandler(int sig)
+{
+  interrupted = true;
+}
+
+//---------------------------------------------------------------------------
+
+int main(int argc, char *argv[])
+{
+  char appName[] = "DelphesLHEF";
+  stringstream message;
+  FILE *inputFile = 0;
+  TFile *outputFile = 0;
+  TStopwatch readStopWatch, procStopWatch;
+  ExRootTreeWriter *treeWriter = 0;
+  ExRootTreeBranch *branchEvent = 0;
+  ExRootConfReader *confReader = 0;
+  Delphes *modularDelphes = 0;
+  DelphesFactory *factory = 0;
+  TObjArray *stableParticleOutputArray = 0, *allParticleOutputArray = 0, *partonOutputArray = 0;
+  DelphesLHEFReader *reader = 0;
+  Int_t i;
+  Long64_t length, eventCounter;
+
+  if(argc < 3)
+  {
+    cout << " Usage: " << appName << " config_file" << " output_file" << " [input_file(s)]" << endl;
+    cout << " config_file - configuration file in Tcl format," << endl;
+    cout << " output_file - output file in ROOT format," << endl;
+    cout << " input_file(s) - input file(s) in LHEF format," << endl;
+    cout << " with no input_file, or when input_file is -, read standard input." << endl;
+    return 1;
+  }
+
+  signal(SIGINT, SignalHandler);
+
+  gROOT->SetBatch();
+
+  int appargc = 1;
+  char *appargv[] = {appName};
+  TApplication app(appName, &appargc, appargv);
+
+  try
+  {
+    outputFile = TFile::Open(argv[2], "CREATE");
+
+    if(outputFile == NULL)
+    {
+      message << "can't create output file " << argv[2];
+      throw runtime_error(message.str());
+    }
+
+    treeWriter = new ExRootTreeWriter(outputFile, "Delphes");
+
+    branchEvent = treeWriter->NewBranch("Event", LHEFEvent::Class());
+
+    confReader = new ExRootConfReader;
+    confReader->ReadFile(argv[1]);
+
+    modularDelphes = new Delphes("Delphes");
+    modularDelphes->SetConfReader(confReader);
+    modularDelphes->SetTreeWriter(treeWriter);
+
+    factory = modularDelphes->GetFactory();
+    allParticleOutputArray = modularDelphes->ExportArray("allParticles");
+    stableParticleOutputArray = modularDelphes->ExportArray("stableParticles");
+    partonOutputArray = modularDelphes->ExportArray("partons");
+
+    reader = new DelphesLHEFReader;
+
+    modularDelphes->InitTask();
+
+    i = 3;
+    do
+    {
+      if(interrupted) break;
+
+      if(i == argc || strncmp(argv[i], "-", 2) == 0)
+      {
+        cout << "** Reading standard input" << endl;
+        inputFile = stdin;
+        length = -1;
+      }
+      else
+      {
+        cout << "** Reading " << argv[i] << endl;
+        inputFile = fopen(argv[i], "r");
+
+        if(inputFile == NULL)
+        {
+          message << "can't open " << argv[i];
+          throw runtime_error(message.str());
+        }
+
+        fseek(inputFile, 0L, SEEK_END);
+        length = ftello(inputFile);
+        fseek(inputFile, 0L, SEEK_SET);
+
+        if(length <= 0)
+        {
+          fclose(inputFile);
+          ++i;
+          continue;
+        }
+      }
+
+      reader->SetInputFile(inputFile);
+
+      ExRootProgressBar progressBar(length);
+
+      // Loop over all objects
+      eventCounter = 0;
+      treeWriter->Clear();
+      modularDelphes->Clear();
+      reader->Clear();
+      readStopWatch.Start();
+      while(reader->ReadBlock(factory, allParticleOutputArray,
+        stableParticleOutputArray, partonOutputArray) && !interrupted)
+      {
+        if(reader->EventReady())
+        {
+          ++eventCounter;
+
+          readStopWatch.Stop();
+          procStopWatch.Start();
+          modularDelphes->ProcessTask();
+          procStopWatch.Stop();
+
+          reader->AnalyzeEvent(branchEvent, eventCounter, &readStopWatch, &procStopWatch);
+
+          treeWriter->Fill();
+
+          treeWriter->Clear();
+          modularDelphes->Clear();
+          reader->Clear();
+
+          readStopWatch.Start();
+        }
+        progressBar.Update(ftello(inputFile), eventCounter);
+      }
+
+      fseek(inputFile, 0L, SEEK_END);
+      progressBar.Update(ftello(inputFile), eventCounter, kTRUE);
+      progressBar.Finish();
+
+      if(inputFile != stdin) fclose(inputFile);
+
+      ++i;
+    }
+    while(i < argc);
+
+    modularDelphes->FinishTask();
+    treeWriter->Write();
+
+    cout << "** Exiting..." << endl;
+
+    delete reader;
+    delete modularDelphes;
+    delete confReader;
+    delete treeWriter;
+    delete outputFile;
+
+    return 0;
+  }
+  catch(runtime_error &e)
+  {
+    if(treeWriter) delete treeWriter;
+    if(outputFile) delete outputFile;
+    cerr << "** ERROR: " << e.what() << endl;
+    return 1;
+  }
+}
Index: trunk/Delphes/Delphes-3.0.9/readers/DelphesSTDHEP.cpp
===================================================================
--- trunk/Delphes/Delphes-3.0.9/readers/DelphesSTDHEP.cpp	(revision 5)
+++ trunk/Delphes/Delphes-3.0.9/readers/DelphesSTDHEP.cpp	(revision 5)
@@ -0,0 +1,203 @@
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+#include <signal.h>
+
+#include "TROOT.h"
+#include "TApplication.h"
+
+#include "TFile.h"
+#include "TObjArray.h"
+#include "TStopwatch.h"
+#include "TDatabasePDG.h"
+#include "TParticlePDG.h"
+#include "TLorentzVector.h"
+
+#include "modules/Delphes.h"
+#include "classes/DelphesClasses.h"
+#include "classes/DelphesFactory.h"
+#include "classes/DelphesSTDHEPReader.h"
+
+#include "ExRootAnalysis/ExRootTreeWriter.h"
+#include "ExRootAnalysis/ExRootTreeBranch.h"
+#include "ExRootAnalysis/ExRootProgressBar.h"
+
+using namespace std;
+
+//---------------------------------------------------------------------------
+
+static bool interrupted = false;
+
+void SignalHandler(int sig)
+{
+  interrupted = true;
+}
+
+//---------------------------------------------------------------------------
+
+int main(int argc, char *argv[])
+{
+  char appName[] = "DelphesSTDHEP";
+  stringstream message;
+  FILE *inputFile = 0;
+  TFile *outputFile = 0;
+  TStopwatch readStopWatch, procStopWatch;
+  ExRootTreeWriter *treeWriter = 0;
+  ExRootTreeBranch *branchEvent = 0;
+  ExRootConfReader *confReader = 0;
+  Delphes *modularDelphes = 0;
+  DelphesFactory *factory = 0;
+  TObjArray *stableParticleOutputArray = 0, *allParticleOutputArray = 0, *partonOutputArray = 0;
+  DelphesSTDHEPReader *reader = 0;
+  Int_t i;
+  Long64_t length, eventCounter;
+
+  if(argc < 3)
+  {
+    cout << " Usage: " << appName << " config_file" << " output_file" << " [input_file(s)]" << endl;
+    cout << " config_file - configuration file in Tcl format," << endl;
+    cout << " output_file - output file in ROOT format," << endl;
+    cout << " input_file(s) - input file(s) in STDHEP format," << endl;
+    cout << " with no input_file, or when input_file is -, read standard input." << endl;
+    return 1;
+  }
+
+  signal(SIGINT, SignalHandler);
+
+  gROOT->SetBatch();
+
+  int appargc = 1;
+  char *appargv[] = {appName};
+  TApplication app(appName, &appargc, appargv);
+
+  try
+  {
+    outputFile = TFile::Open(argv[2], "CREATE");
+
+    if(outputFile == NULL)
+    {
+      message << "can't create output file " << argv[2];
+      throw runtime_error(message.str());
+    }
+
+    treeWriter = new ExRootTreeWriter(outputFile, "Delphes");
+
+    branchEvent = treeWriter->NewBranch("Event", LHEFEvent::Class());
+
+    confReader = new ExRootConfReader;
+    confReader->ReadFile(argv[1]);
+
+    modularDelphes = new Delphes("Delphes");
+    modularDelphes->SetConfReader(confReader);
+    modularDelphes->SetTreeWriter(treeWriter);
+
+    factory = modularDelphes->GetFactory();
+    allParticleOutputArray = modularDelphes->ExportArray("allParticles");
+    stableParticleOutputArray = modularDelphes->ExportArray("stableParticles");
+    partonOutputArray = modularDelphes->ExportArray("partons");
+
+    reader = new DelphesSTDHEPReader;
+
+    modularDelphes->InitTask();
+
+    i = 3;
+    do
+    {
+      if(interrupted) break;
+
+      if(i == argc || strncmp(argv[i], "-", 2) == 0)
+      {
+        cout << "** Reading standard input" << endl;
+        inputFile = stdin;
+        length = -1;
+      }
+      else
+      {
+        cout << "** Reading " << argv[i] << endl;
+        inputFile = fopen(argv[i], "r");
+
+        if(inputFile == NULL)
+        {
+          message << "can't open " << argv[i];
+          throw runtime_error(message.str());
+        }
+
+        fseek(inputFile, 0L, SEEK_END);
+        length = ftello(inputFile);
+        fseek(inputFile, 0L, SEEK_SET);
+
+        if(length <= 0)
+        {
+          fclose(inputFile);
+          ++i;
+          continue;
+        }
+      }
+
+      reader->SetInputFile(inputFile);
+
+      ExRootProgressBar progressBar(length);
+
+      // Loop over all objects
+      eventCounter = 0;
+      treeWriter->Clear();
+      modularDelphes->Clear();
+      reader->Clear();
+      readStopWatch.Start();
+      while(reader->ReadBlock(factory, allParticleOutputArray,
+        stableParticleOutputArray, partonOutputArray) && !interrupted)
+      {
+        if(reader->EventReady())
+        {
+          ++eventCounter;
+
+          readStopWatch.Stop();
+          procStopWatch.Start();
+          modularDelphes->ProcessTask();
+          procStopWatch.Stop();
+
+          reader->AnalyzeEvent(branchEvent, eventCounter, &readStopWatch, &procStopWatch);
+
+          treeWriter->Fill();
+
+          treeWriter->Clear();
+          modularDelphes->Clear();
+          reader->Clear();
+
+          readStopWatch.Start();
+        }
+        progressBar.Update(ftello(inputFile), eventCounter);
+      }
+
+      fseek(inputFile, 0L, SEEK_END);
+      progressBar.Update(ftello(inputFile), eventCounter, kTRUE);
+      progressBar.Finish();
+
+      if(inputFile != stdin) fclose(inputFile);
+
+      ++i;
+    }
+    while(i < argc);
+
+    modularDelphes->FinishTask();
+    treeWriter->Write();
+
+    cout << "** Exiting..." << endl;
+
+    delete reader;
+    delete modularDelphes;
+    delete confReader;
+    delete treeWriter;
+    delete outputFile;
+
+    return 0;
+  }
+  catch(runtime_error &e)
+  {
+    if(treeWriter) delete treeWriter;
+    if(outputFile) delete outputFile;
+    cerr << "** ERROR: " << e.what() << endl;
+    return 1;
+  }
+}
