public class DTMManagerDefault extends DTMManager
{

  /** Set this to true if you want a dump of the DTM after creation. */
  private static final boolean DUMPTREE = false;

  /** Set this to true if you want a basic diagnostics. */
  private static final boolean DEBUG = false;

  /**
   * Map from DTM identifier numbers to DTM objects that this manager manages.
   * One DTM may have several prefix numbers, if extended node indexing
   * is in use; in that case, m_dtm_offsets[] will used to control which
   * prefix maps to which section of the DTM.
   *
   * This array grows as necessary; see addDTM().
   *
   * This array grows as necessary; see addDTM(). Growth is uncommon... but
   * access needs to be blindingly fast since it's used in node addressing.
   */
  protected DTM m_dtms[] = new DTM[256];

  /** Map from DTM identifier numbers to offsets. For small DTMs with a
   * single identifier, this will always be 0. In overflow addressing, where
   * additional identifiers are allocated to access nodes beyond the range of
   * a single Node Handle, this table is used to map the handle's node field
   * into the actual node identifier.
   *
   * This array grows as necessary; see addDTM().
   *
   * This array grows as necessary; see addDTM(). Growth is uncommon... but
   * access needs to be blindingly fast since it's used in node addressing.
   * (And at the moment, that includes accessing it from DTMDefaultBase,
   * which is why this is not Protected or Private.)
   */
  int m_dtm_offsets[] = new int[256];

  /**
   * The cache for XMLReader objects to be used if the user did not
   * supply an XMLReader for a SAXSource or supplied a StreamSource.
   */
  protected XMLReaderManager m_readerManager = null;

  /**
   * Add a DTM to the DTM table. This convenience call adds it as the
   * "base DTM ID", with offset 0. The other version of addDTM should
   * be used if you want to add "extended" DTM IDs with nonzero offsets.
   *
   * @param dtm Should be a valid reference to a DTM.
   * @param id Integer DTM ID to be bound to this DTM
   */
  synchronized public void addDTM(DTM dtm, int id) {	addDTM(dtm,id,0); }

  /**
   * Add a DTM to the DTM table.
   *
   * @param dtm Should be a valid reference to a DTM.
   * @param id Integer DTM ID to be bound to this DTM.
   * @param offset Integer addressing offset. The internal DTM Node ID is
   * obtained by adding this offset to the node-number field of the
   * public DTM Handle. For the first DTM ID accessing each DTM, this is 0;
   * for overflow addressing it will be a multiple of 1<<IDENT_DTM_NODE_BITS.
   */
  synchronized public void addDTM(DTM dtm, int id, int offset)
  {
		if(id>=IDENT_MAX_DTMS)
		{
		}

		int oldlen=m_dtms.length;
		if(oldlen<=id)
		{
			int newlen=Math.min((id+256),IDENT_MAX_DTMS);

			DTM new_m_dtms[] = new DTM[newlen];
			System.arraycopy(m_dtms,0,new_m_dtms,0,oldlen);
			m_dtms=new_m_dtms;
			int new_m_dtm_offsets[] = new int[newlen];
			System.arraycopy(m_dtm_offsets,0,new_m_dtm_offsets,0,oldlen);
			m_dtm_offsets=new_m_dtm_offsets;
		}

    m_dtms[id] = dtm;
		m_dtm_offsets[id]=offset;
    dtm.documentRegistration();
  }

  /**
   * Get the first free DTM ID available. %OPT% Linear search is inefficient!
   */
  synchronized public int getFirstFreeDTMID()
  {
    int n = m_dtms.length;
    for (int i = 1; i < n; i++)
    {
      if(null == m_dtms[i])
      {
        return i;
      }
    }
  }

  /**
   * The default table for exandedNameID lookups.
   */
  private ExpandedNameTable m_expandedNameTable =
    new ExpandedNameTable();

  /**
   * Constructor DTMManagerDefault
   *
   */
  public DTMManagerDefault(){}

  /**
   * Get an instance of a DTM, loaded with the content from the
   * specified source.  If the unique flag is true, a new instance will
   * always be returned.  Otherwise it is up to the DTMManager to return a
   * new instance or an instance that it already created and may be being used
   * by someone else.
   *
   * A bit of magic in this implementation: If the source is null, unique is true,
   * and incremental and doIndexing are both false, we return an instance of
   * SAX2RTFDTM, which see.
   *
   * (I think more parameters will need to be added for error handling, and entity
   * resolution, and more explicit control of the RTF situation).
   *
   * @param source the specification of the source object.
   * @param unique true if the returned DTM must be unique, probably because it
   * is going to be mutated.
   * @param whiteSpaceFilter Enables filtering of whitespace nodes, and may
   *                         be null.
   * @param incremental true if the DTM should be built incrementally, if
   *                    possible.
   * @param doIndexing true if the caller considers it worth it to use
   *                   indexing schemes.
   *
   * @return a non-null DTM reference.
   */
  synchronized public DTM getDTM(Source source, boolean unique,
                                 DTMWSFilter whiteSpaceFilter,
                                 boolean incremental, boolean doIndexing)
  {

    if(DEBUG && null != source)
      System.out.println("Starting "+
                         (unique ? "UNIQUE" : "shared")+
                         " source: "+source.getSystemId()
                         );

    XMLStringFactory xstringFactory = m_xsf;
    int dtmPos = getFirstFreeDTMID();
    int documentID = dtmPos << IDENT_DTM_NODE_BITS;

    if ((null != source) && source instanceof DOMSource)
    {
      DOM2DTM dtm = new DOM2DTM(this, (DOMSource) source, documentID,
                                whiteSpaceFilter, xstringFactory, doIndexing);

      addDTM(dtm, dtmPos, 0);

      return dtm;
    }
    else
    {
      boolean isSAXSource = (null != source)
        ? (source instanceof SAXSource) : true;
      boolean isStreamSource = (null != source)
        ? (source instanceof StreamSource) : false;

      if (isSAXSource || isStreamSource) {
        XMLReader reader = null;

        try {
          InputSource xmlSource;

          if (null == source) {
            xmlSource = null;
          } else {
            reader = getXMLReader(source);
            xmlSource = SAXSource.sourceToInputSource(source);

            String urlOfSource = xmlSource.getSystemId();

            if (null != urlOfSource) {
              try {
                urlOfSource = SystemIDResolver.getAbsoluteURI(urlOfSource);
              } catch (Exception e) {
                System.err.println("Can not absolutize URL: " + urlOfSource);
              }

              xmlSource.setSystemId(urlOfSource);
            }
          }

          SAX2DTM dtm;
          if (source==null && unique && !incremental && !doIndexing) {
            dtm = new SAX2RTFDTM(this, source, documentID, whiteSpaceFilter,
                                 xstringFactory, doIndexing);
          }
          /**************************************************************
          else if(JKESS_XNI_EXPERIMENT && m_incremental) {
            dtm = new XNI2DTM(this, source, documentID, whiteSpaceFilter,
                              xstringFactory, doIndexing);
          }
          **************************************************************/
          else {
            dtm = new SAX2DTM(this, source, documentID, whiteSpaceFilter,
                              xstringFactory, doIndexing);
          }

          addDTM(dtm, dtmPos, 0);

          boolean haveXercesParser =
                     (null != reader)
                     && (reader.getClass()
                               .getName()
                               .equals("org.apache.xerces.parsers.SAXParser") );

          if (haveXercesParser) {
          }

          if (m_incremental && incremental
               /* || ((null == reader) && incremental) */) {
            IncrementalSAXSource coParser=null;

            if (haveXercesParser) {
              try {
                coParser =(IncrementalSAXSource)
                  Class.forName("org.apache.xml.dtm.ref.IncrementalSAXSource_Xerces").newInstance();
              }  catch( Exception ex ) {
                ex.printStackTrace();
                coParser=null;
              }
            }

            if (coParser==null ) {
              if (null == reader) {
                coParser = new IncrementalSAXSource_Filter();
              } else {
                IncrementalSAXSource_Filter filter =
                         new IncrementalSAXSource_Filter();
                filter.setXMLReader(reader);
                coParser=filter;
              }
            }

            /**************************************************************
            if (JKESS_XNI_EXPERIMENT && m_incremental &&
                  dtm instanceof XNI2DTM &&
                  coParser instanceof IncrementalSAXSource_Xerces) {
                org.apache.xerces.xni.parser.XMLPullParserConfiguration xpc=
                      ((IncrementalSAXSource_Xerces)coParser)
                                           .getXNIParserConfiguration();
              if (xpc!=null) {
                ((XNI2DTM)dtm).setIncrementalXNISource(xpc);
              } else {
                dtm.setIncrementalSAXSource(coParser);
              }
            } else
            ***************************************************************/

            dtm.setIncrementalSAXSource(coParser);

            if (null == xmlSource) {

              return dtm;
            }

            if (null == reader.getErrorHandler()) {
              reader.setErrorHandler(dtm);
            }
            reader.setDTDHandler(dtm);

            try {

              coParser.startParse(xmlSource);
            } catch (RuntimeException re) {

              dtm.clearCoRoutine();

              throw re;
            } catch (Exception e) {

              dtm.clearCoRoutine();

              throw new org.apache.xml.utils.WrappedRuntimeException(e);
            }
          } else {
            if (null == reader) {

              return dtm;
            }

            reader.setContentHandler(dtm);
            reader.setDTDHandler(dtm);
            if (null == reader.getErrorHandler()) {
              reader.setErrorHandler(dtm);
            }

            try {
              reader.setProperty(
                               dtm);
            } catch (SAXNotRecognizedException e){}
              catch (SAXNotSupportedException e){}

            try {
              reader.parse(xmlSource);
            } catch (RuntimeException re) {
              dtm.clearCoRoutine();

              throw re;
            } catch (Exception e) {
              dtm.clearCoRoutine();

              throw new org.apache.xml.utils.WrappedRuntimeException(e);
            }
          }

          if (DUMPTREE) {
            System.out.println("Dumping SAX2DOM");
            dtm.dumpDTM(System.err);
          }

          return dtm;
        } finally {
          releaseXMLReader(reader);
        }
      } else {

      }
    }
  }

  /**
   * Given a W3C DOM node, try and return a DTM handle.
   * Note: calling this may be non-optimal, and there is no guarantee that
   * the node will be found in any particular DTM.
   *
   * @param node Non-null reference to a DOM node.
   *
   * @return a valid DTM handle.
   */
  synchronized public int getDTMHandleFromNode(org.w3c.dom.Node node)
  {
    if(null == node)

    if (node instanceof org.apache.xml.dtm.ref.DTMNodeProxy)
      return ((org.apache.xml.dtm.ref.DTMNodeProxy) node).getDTMNodeNumber();

    else
    {
			int max = m_dtms.length;
      for(int i = 0; i < max; i++)
        {
          DTM thisDTM=m_dtms[i];
          if((null != thisDTM) && thisDTM instanceof DOM2DTM)
          {
            int handle=((DOM2DTM)thisDTM).getHandleOfNode(node);
            if(handle!=DTM.NULL) return handle;
          }
         }

      Node root = node;
      Node p = (root.getNodeType() == Node.ATTRIBUTE_NODE) ? ((org.w3c.dom.Attr)root).getOwnerElement() : root.getParentNode();
      for (; p != null; p = p.getParentNode())
      {
        root = p;
      }

      DOM2DTM dtm = (DOM2DTM) getDTM(new javax.xml.transform.dom.DOMSource(root),
																		 false, null, true, true);

      int handle;

      if(node instanceof org.apache.xml.dtm.ref.dom2dtm.DOM2DTMdefaultNamespaceDeclarationNode)
      {
				handle=dtm.getHandleOfNode(((org.w3c.dom.Attr)node).getOwnerElement());
				handle=dtm.getAttributeNode(handle,node.getNamespaceURI(),node.getLocalName());
      }
      else
				handle = ((DOM2DTM)dtm).getHandleOfNode(node);

      if(DTM.NULL == handle)

      return handle;
    }
  }

  /**
   * This method returns the SAX2 parser to use with the InputSource
   * obtained from this URI.
   * It may return null if any SAX2-conformant XML parser can be used,
   * or if getInputSource() will also return null. The parser must
   * be free for use (i.e., not currently in use for another parse().
   * After use of the parser is completed, the releaseXMLReader(XMLReader)
   * must be called.
   *
   * @param inputSource The value returned from the URIResolver.
   * @return  a SAX2 XMLReader to use to resolve the inputSource argument.
   *
   * @return non-null XMLReader reference ready to parse.
   */
  synchronized public XMLReader getXMLReader(Source inputSource)
  {

    try
    {
      XMLReader reader = (inputSource instanceof SAXSource)
                         ? ((SAXSource) inputSource).getXMLReader() : null;

      if (null == reader) {
        if (m_readerManager == null) {
            m_readerManager = XMLReaderManager.getInstance();
        }

        reader = m_readerManager.getXMLReader();
      }

      return reader;

    } catch (SAXException se) {
      throw new DTMException(se.getMessage(), se);
    }
  }

  /**
   * Indicates that the XMLReader object is no longer in use for the transform.
   *
   * Note that the getXMLReader method may return an XMLReader that was
   * specified on the SAXSource object by the application code.  Such a
   * reader should still be passed to releaseXMLReader, but the reader manager
   * will only re-use XMLReaders that it created.
   *
   * @param reader The XMLReader to be released.
   */
  synchronized public void releaseXMLReader(XMLReader reader) {
    if (m_readerManager != null) {
      m_readerManager.releaseXMLReader(reader);
    }
  }

  /**
   * Return the DTM object containing a representation of this node.
   *
   * @param nodeHandle DTM Handle indicating which node to retrieve
   *
   * @return a reference to the DTM object containing this node.
   */
  synchronized public DTM getDTM(int nodeHandle)
  {
    try
    {
      return m_dtms[nodeHandle >>> IDENT_DTM_NODE_BITS];
    }
    catch(java.lang.ArrayIndexOutOfBoundsException e)
    {
      if(nodeHandle==DTM.NULL){}
      else{}
    }
  }

  /**
   * Given a DTM, find the ID number in the DTM tables which addresses
   * the start of the document. If overflow addressing is in use, other
   * DTM IDs may also be assigned to this DTM.
   *
   * @param dtm The DTM which (hopefully) contains this node.
   *
   * @return The DTM ID (as the high bits of a NodeHandle, not as our
   * internal index), or -1 if the DTM doesn't belong to this manager.
   */
  synchronized public int getDTMIdentity(DTM dtm)
  {
	if(dtm instanceof DTMDefaultBase)
	{
		DTMDefaultBase dtmdb=(DTMDefaultBase)dtm;
		if(dtmdb.getManager()==this)
			return dtmdb.getDTMIDs().elementAt(0);
		else
			return -1;
	}

    int n = m_dtms.length;

    for (int i = 0; i < n; i++)
    {
      DTM tdtm = m_dtms[i];

      if (tdtm == dtm && m_dtm_offsets[i]==0)
        return i << IDENT_DTM_NODE_BITS;
    }

    return -1;
  }

  /**
   * Release the DTMManager's reference(s) to a DTM, making it unmanaged.
   * This is typically done as part of returning the DTM to the heap after
   * we're done with it.
   *
   * @param dtm the DTM to be released.
   *
   * @param shouldHardDelete If false, this call is a suggestion rather than an
   * order, and we may not actually release the DTM. This is intended to
   * support intelligent caching of documents... which is not implemented
   * in this version of the DTM manager.
   *
   * @return true if the DTM was released, false if shouldHardDelete was set
   * and we decided not to.
   */
  synchronized public boolean release(DTM dtm, boolean shouldHardDelete)
  {
    if(DEBUG)
    {
      System.out.println("Releasing "+
			 (shouldHardDelete ? "HARD" : "soft")+
			 " dtm="+
			 dtm.getDocumentBaseURI()
			 );
    }

    if (dtm instanceof SAX2DTM)
    {
      ((SAX2DTM) dtm).clearCoRoutine();
    }

		if(dtm instanceof DTMDefaultBase)
		{
			org.apache.xml.utils.SuballocatedIntVector ids=((DTMDefaultBase)dtm).getDTMIDs();
			for(int i=ids.size()-1;i>=0;--i)
				m_dtms[ids.elementAt(i)>>>DTMManager.IDENT_DTM_NODE_BITS]=null;
		}
		else
		{
			int i = getDTMIdentity(dtm);
		    if (i >= 0)
			{
				m_dtms[i >>> DTMManager.IDENT_DTM_NODE_BITS] = null;
			}
		}

    dtm.documentRelease();
    return true;
  }

  /**
   * Method createDocumentFragment
   *
   *
   * NEEDSDOC (createDocumentFragment) @return
   */
  synchronized public DTM createDocumentFragment()
  {

    try
    {
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

      dbf.setNamespaceAware(true);

      DocumentBuilder db = dbf.newDocumentBuilder();
      Document doc = db.newDocument();
      Node df = doc.createDocumentFragment();

      return getDTM(new DOMSource(df), true, null, false, false);
    }
    catch (Exception e)
    {
      throw new DTMException(e);
    }
  }

  /**
   * NEEDSDOC Method createDTMIterator
   *
   *
   * NEEDSDOC @param whatToShow
   * NEEDSDOC @param filter
   * NEEDSDOC @param entityReferenceExpansion
   *
   * NEEDSDOC (createDTMIterator) @return
   */
  synchronized public DTMIterator createDTMIterator(int whatToShow, DTMFilter filter,
                                       boolean entityReferenceExpansion)
  {

    /** @todo: implement this org.apache.xml.dtm.DTMManager abstract method */
    return null;
  }

  /**
   * NEEDSDOC Method createDTMIterator
   *
   *
   * NEEDSDOC @param xpathString
   * NEEDSDOC @param presolver
   *
   * NEEDSDOC (createDTMIterator) @return
   */
  synchronized public DTMIterator createDTMIterator(String xpathString,
                                       PrefixResolver presolver)
  {

    /** @todo: implement this org.apache.xml.dtm.DTMManager abstract method */
    return null;
  }

  /**
   * NEEDSDOC Method createDTMIterator
   *
   *
   * NEEDSDOC @param node
   *
   * NEEDSDOC (createDTMIterator) @return
   */
  synchronized public DTMIterator createDTMIterator(int node)
  {

    /** @todo: implement this org.apache.xml.dtm.DTMManager abstract method */
    return null;
  }

  /**
   * NEEDSDOC Method createDTMIterator
   *
   *
   * NEEDSDOC @param xpathCompiler
   * NEEDSDOC @param pos
   *
   * NEEDSDOC (createDTMIterator) @return
   */
  synchronized public DTMIterator createDTMIterator(Object xpathCompiler, int pos)
  {

    /** @todo: implement this org.apache.xml.dtm.DTMManager abstract method */
    return null;
  }

  /**
   * return the expanded name table.
   *
   * NEEDSDOC @param dtm
   *
   * NEEDSDOC ($objectName$) @return
   */
  public ExpandedNameTable getExpandedNameTable(DTM dtm)
  {
    return m_expandedNameTable;


org.apache.xalan.xsltc.dom.SortSettings

final class SortSettings {
    /**
     * A reference to the translet object for the transformation.
     */
    private AbstractTranslet _translet;

    /**
     * The sort order (ascending or descending) for each level of
     * xsl:sort
     */
    private int[] _sortOrders;

    /**
     * The type of comparison (text or number) for each level of
     * xsl:sort
     */
    private int[] _types;

    /**
     * The Locale for each level of xsl:sort, based on any lang
     * attribute or the default Locale.
     */
    private Locale[] _locales;

    /**
     * The Collator object in effect for each level of xsl:sort
     */
    private Collator[] _collators;

    /**
     * Case ordering for each level of xsl:sort.
     */
    private String[] _caseOrders;

    /**
     * Create an instance of SortSettings.
     * @param translet {@link org.apache.xalan.xsltc.runtime.AbstractTranslet}
     *                 object for the transformation
     * @param sortOrders an array specifying the sort order for each sort level
     * @param types an array specifying the type of comparison for each sort
     *              level (text or number)
     * @param locales an array specifying the Locale for each sort level
     * @param collators an array specifying the Collation in effect for each
     *                  sort level
     * @param caseOrders an array specifying whether upper-case, lower-case
     *                   or neither is to take precedence for each sort level.
     *                   The value of each element is equal to one of
     *                   "upper-first", "lower-first", or "".
     */
    SortSettings(AbstractTranslet translet, int[] sortOrders, int[] types,
                 Locale[] locales, Collator[] collators, String[] caseOrders) {
        _translet = translet;
        _sortOrders = sortOrders;
        _types = types;
        _locales = locales;
        _collators = collators;
        _caseOrders = caseOrders;
    }

    /**
     * @return A reference to the translet object for the transformation.
     */
    AbstractTranslet getTranslet() {
        return _translet;
    }

    /**
     * @return An array containing the sort order (ascending or descending)
     *         for each level of xsl:sort
     */
    int[] getSortOrders() {
        return _sortOrders;
    }

    /**
     * @return An array containing the type of comparison (text or number)
     *         to perform for each level of xsl:sort
     */
    int[] getTypes() {
        return _types;
    }

    /**
     * @return An array containing the Locale object in effect for each level
     *         of xsl:sort
     */
    Locale[] getLocales() {
        return _locales;
    }

    /**
     * @return An array containing the Collator object in effect for each level
     *         of xsl:sort
     */
    Collator[] getCollators() {
        return _collators;
    }

    /**
     * @return An array specifying the case ordering for each level of
     *         xsl:sort.
     */
    String[] getCaseOrders() {
        return _caseOrders;

    int[] getTypes() {
        return _types;

FUNC_DECL PARAM PARAM PARAM PARAM PARAM PARAM ASSIGN ASSIGN ASSIGN ASSIGN ASSIGN ASSIGN


class FunctionCall extends Expression {

    private QName  _fname;
    private final Vector _arguments;
    private final static Vector EMPTY_ARG_LIST = new Vector(0);

    protected final static String EXT_XSLTC =
	TRANSLET_URI;

    protected final static String JAVA_EXT_XSLTC =
	EXT_XSLTC + "/java";

    protected final static String EXT_XALAN = '';

    protected final static String JAVA_EXT_XALAN = '';

    protected final static String JAVA_EXT_XALAN_OLD = '';

    protected final static String EXSLT_COMMON = '';

    protected final static String EXSLT_MATH = '';

    protected final static String EXSLT_SETS = '';

    protected final static String EXSLT_DATETIME = '';

    protected final static String EXSLT_STRINGS = '';

    protected final static int NAMESPACE_FORMAT_JAVA = 0;
    protected final static int NAMESPACE_FORMAT_CLASS = 1;
    protected final static int NAMESPACE_FORMAT_PACKAGE = 2;
    protected final static int NAMESPACE_FORMAT_CLASS_OR_PACKAGE = 3;

    private int _namespace_format = NAMESPACE_FORMAT_JAVA;

    /**
     * Stores reference to object for non-static Java calls
     */
    Expression _thisArgument = null;

    private String      _className;
    private Class       _clazz;
    private Method      _chosenMethod;
    private Constructor _chosenConstructor;
    private MethodType  _chosenMethodType;

    private boolean    unresolvedExternal;

    private boolean     _isExtConstructor = false;

    private boolean 	  _isStatic = false;

    private static final MultiHashtable _internal2Java = new MultiHashtable();

    private static final Hashtable _java2Internal = new Hashtable();

    private static final Hashtable _extensionNamespaceTable = new Hashtable();

    private static final Hashtable _extensionFunctionTable = new Hashtable();
    /**
     * inner class to used in internal2Java mappings, contains
     * the Java type and the distance between the internal type and
     * the Java type.
     */
    static class JavaType {
	public Class  type;
	public int distance;

	public JavaType(Class type, int distance){
	    this.type = type;
	    this.distance = distance;
	}
	public boolean equals(Object query){
	    return query.equals(type);
	}
    }

    /**
     * Defines 2 conversion tables:
     * 1. From internal types to Java types and
     * 2. From Java types to internal types.
     * These two tables are used when calling external (Java) functions.
     */
    static {

	try {
	    final Class objectClass   = Class.forName("java.lang.Object");
	    final Class stringClass   = Class.forName("java.lang.String");
	    final Class nodeClass     = Class.forName("org.w3c.dom.Node");
	    final Class nodeListClass = Class.forName("org.w3c.dom.NodeList");

	    _internal2Java.put(Type.Boolean, new JavaType(objectClass,2));
	    _internal2Java.put(Type.Boolean, new JavaType(java.lang.Boolean.class,1));
	    _internal2Java.put(Type.Boolean, new JavaType(Boolean.TYPE,0));

	    _internal2Java.put(Type.Int, new JavaType(objectClass, 8));
	    _internal2Java.put(Type.Int, new JavaType(Character.TYPE, 7));
	    _internal2Java.put(Type.Int, new JavaType(Byte.TYPE, 6));
	    _internal2Java.put(Type.Int, new JavaType(Short.TYPE, 5));
	    _internal2Java.put(Type.Int, new JavaType(Integer.TYPE, 0));
	    _internal2Java.put(Type.Int, new JavaType(java.lang.Integer.class, 1));
	    _internal2Java.put(Type.Int, new JavaType(Long.TYPE, 2));
	    _internal2Java.put(Type.Int, new JavaType(Float.TYPE, 3));
	    _internal2Java.put(Type.Int, new JavaType(Double.TYPE, 4));

	    _internal2Java.put(Type.Real, new JavaType(objectClass, 8));
	    _internal2Java.put(Type.Real, new JavaType(Character.TYPE, 7));
	    _internal2Java.put(Type.Real, new JavaType(Byte.TYPE, 6));
	    _internal2Java.put(Type.Real, new JavaType(Short.TYPE, 5));
	    _internal2Java.put(Type.Real, new JavaType(Integer.TYPE, 4));
	    _internal2Java.put(Type.Real, new JavaType(Long.TYPE, 3));
	    _internal2Java.put(Type.Real, new JavaType(Float.TYPE, 2));
	    _internal2Java.put(Type.Real, new JavaType(java.lang.Double.class, 1));
	    _internal2Java.put(Type.Real, new JavaType(Double.TYPE, 0));

	    _internal2Java.put(Type.String, new JavaType(objectClass, 1));
	    _internal2Java.put(Type.String, new JavaType(stringClass, 0));

	    _internal2Java.put(Type.Node, new JavaType(nodeClass, 0));
	    _internal2Java.put(Type.Node, new JavaType(nodeListClass, 1));
	    _internal2Java.put(Type.Node, new JavaType(objectClass, 2));
	    _internal2Java.put(Type.Node, new JavaType(stringClass, 3));

	    _internal2Java.put(Type.NodeSet, new JavaType(Integer.TYPE, 10));
	    _internal2Java.put(Type.NodeSet, new JavaType(stringClass, 3));
	    _internal2Java.put(Type.NodeSet, new JavaType(objectClass, 2));
	    _internal2Java.put(Type.NodeSet, new JavaType(nodeClass, 1));
	    _internal2Java.put(Type.NodeSet, new JavaType(nodeListClass,0));

	    _internal2Java.put(Type.ResultTree, new JavaType(nodeClass, 1));
	    _internal2Java.put(Type.ResultTree, new JavaType(nodeListClass, 0));
	    _internal2Java.put(Type.ResultTree, new JavaType(objectClass, 2));
	    _internal2Java.put(Type.ResultTree, new JavaType(stringClass, 3));
	    _internal2Java.put(Type.ResultTree, new JavaType(Double.TYPE, 4));

	    _internal2Java.put(Type.Reference, new JavaType(objectClass,0));

	    _java2Internal.put(Boolean.TYPE, Type.Boolean);
	    _java2Internal.put(Void.TYPE, Type.Void);
	    _java2Internal.put(Character.TYPE, Type.Real);
	    _java2Internal.put(Byte.TYPE, Type.Real);
	    _java2Internal.put(Short.TYPE, Type.Real);
	    _java2Internal.put(Integer.TYPE, Type.Real);
	    _java2Internal.put(Long.TYPE, Type.Real);
	    _java2Internal.put(Float.TYPE, Type.Real);
	    _java2Internal.put(Double.TYPE, Type.Real);

	    _java2Internal.put(stringClass, Type.String);

	    _java2Internal.put(objectClass, Type.Reference);

	    _java2Internal.put(nodeListClass, Type.NodeSet);
	    _java2Internal.put(nodeClass, Type.NodeSet);

	    _extensionNamespaceTable.put(EXT_XALAN, "org.apache.xalan.lib.Extensions");
	    _extensionNamespaceTable.put(EXSLT_COMMON, "org.apache.xalan.lib.ExsltCommon");
	    _extensionNamespaceTable.put(EXSLT_MATH, "org.apache.xalan.lib.ExsltMath");
	    _extensionNamespaceTable.put(EXSLT_SETS, "org.apache.xalan.lib.ExsltSets");
	    _extensionNamespaceTable.put(EXSLT_DATETIME, "org.apache.xalan.lib.ExsltDatetime");
	    _extensionNamespaceTable.put(EXSLT_STRINGS, "org.apache.xalan.lib.ExsltStrings");

	    _extensionFunctionTable.put(EXSLT_COMMON + ":nodeSet", "nodeset");
	    _extensionFunctionTable.put(EXSLT_COMMON + ":objectType", "objectType");
	    _extensionFunctionTable.put(EXT_XALAN + ":nodeset", "nodeset");
	}
	catch (ClassNotFoundException e) {
	    System.err.println(e);
	}
    }

    public FunctionCall(QName fname, Vector arguments) {
	_fname = fname;
	_arguments = arguments;
	_type = null;
    }

    public FunctionCall(QName fname) {
	this(fname, EMPTY_ARG_LIST);
    }

    public String getName() {
	return(_fname.toString());
    }

    public void setParser(Parser parser) {
	super.setParser(parser);
	if (_arguments != null) {
	    final int n = _arguments.size();
	    for (int i = 0; i < n; i++) {
		final Expression exp = (Expression)_arguments.elementAt(i);
		exp.setParser(parser);
		exp.setParent(this);
	    }
	}
    }

    public String getClassNameFromUri(String uri)
    {
        String className = (String)_extensionNamespaceTable.get(uri);

        if (className != null)
            return className;
        else {
            if (uri.startsWith(JAVA_EXT_XSLTC)) {
      	    	int length = JAVA_EXT_XSLTC.length() + 1;
            	return (uri.length() > length) ? uri.substring(length) : EMPTYSTRING;
            }
            else if (uri.startsWith(JAVA_EXT_XALAN)) {
      	    	int length = JAVA_EXT_XALAN.length() + 1;
            	return (uri.length() > length) ? uri.substring(length) : EMPTYSTRING;
            }
            else if (uri.startsWith(JAVA_EXT_XALAN_OLD)) {
      	    	int length = JAVA_EXT_XALAN_OLD.length() + 1;
            	return (uri.length() > length) ? uri.substring(length) : EMPTYSTRING;
            }
            else {
      	    	int index = uri.lastIndexOf('/');
      	    	return (index > 0) ? uri.substring(index+1) : uri;
            }
        }
    }

    /**
     * Type check a function call. Since different type conversions apply,
     * type checking is different for standard and external (Java) functions.
     */
    public Type typeCheck(SymbolTable stable)
	throws TypeCheckError
    {
        if (_type != null) return _type;

	final String namespace = _fname.getNamespace();
	String local = _fname.getLocalPart();

	if (isExtension()) {
	    _fname = new QName(null, null, local);
	    return typeCheckStandard(stable);
	}
	else if (isStandard()) {
	    return typeCheckStandard(stable);
	}
	else {
	    try {
	    	_className = getClassNameFromUri(namespace);

                final int pos = local.lastIndexOf('.');
		if (pos > 0) {
		    _isStatic = true;
		    if (_className != null && _className.length() > 0) {
		    	_namespace_format = NAMESPACE_FORMAT_PACKAGE;
		     	_className = _className + "." + local.substring(0, pos);
		    }
		    else {
		     	_namespace_format = NAMESPACE_FORMAT_JAVA;
		     	_className = local.substring(0, pos);
		    }

		    _fname = new QName(namespace, null, local.substring(pos + 1));
		}
		else {
		    if (_className != null && _className.length() > 0) {
		    	try {
		      	    TransletLoader loader = new TransletLoader();
		            _clazz = loader.loadClass(_className);
		            _namespace_format = NAMESPACE_FORMAT_CLASS;
		    	}
		    	catch (ClassNotFoundException e) {
		      	    _namespace_format = NAMESPACE_FORMAT_PACKAGE;
		        }
		    }
		    else
	            	_namespace_format = NAMESPACE_FORMAT_JAVA;

		    if (local.indexOf('-') > 0) {
		        local = replaceDash(local);
		    }

		    String extFunction = (String)_extensionFunctionTable.get(namespace + ":" + local);
		    if (extFunction != null) {
		      	_fname = new QName(null, null, extFunction);
		      	return typeCheckStandard(stable);
		    }
		    else
		      	_fname = new QName(namespace, null, local);
		}

		return typeCheckExternal(stable);
	    }
	    catch (TypeCheckError e) {
		ErrorMsg errorMsg = e.getErrorMsg();
		if (errorMsg == null) {
		    final String name = _fname.getLocalPart();
		    errorMsg = new ErrorMsg(ErrorMsg.METHOD_NOT_FOUND_ERR, name);
		}
		getParser().reportError(ERROR, errorMsg);
		return _type = Type.Void;
	    }
	  }
    }

    /**
     * Type check a call to a standard function. Insert CastExprs when needed.
     * If as a result of the insertion of a CastExpr a type check error is
     * thrown, then catch it and re-throw it with a new "this".
     */
    public Type typeCheckStandard(SymbolTable stable) throws TypeCheckError {

	final int n = _arguments.size();
	final Vector argsType = typeCheckArgs(stable);
	final MethodType args = new MethodType(Type.Void, argsType);
	final MethodType ptype =
	    lookupPrimop(stable, _fname.getLocalPart(), args);

	if (ptype != null) {
	    for (int i = 0; i < n; i++) {
		final Type argType = (Type) ptype.argsType().elementAt(i);
		final Expression exp = (Expression)_arguments.elementAt(i);
		if (!argType.identicalTo(exp.getType())) {
		    try {
			_arguments.setElementAt(new CastExpr(exp, argType), i);
		    }
		    catch (TypeCheckError e) {
		    }
		}
	    }
	    _chosenMethodType = ptype;
	    return _type = ptype.resultType();
	}
	throw new TypeCheckError(this);
    }

    public Type typeCheckConstructor(SymbolTable stable) throws TypeCheckError{
        final Vector constructors = findConstructors();
	if (constructors == null) {
            throw new TypeCheckError(ErrorMsg.CONSTRUCTOR_NOT_FOUND,
		_className);

	}

	final int nConstructors = constructors.size();
	final int nArgs = _arguments.size();
	final Vector argsType = typeCheckArgs(stable);

	int bestConstrDistance = Integer.MAX_VALUE;
	for (int j, i = 0; i < nConstructors; i++) {
	    final Constructor constructor =
		(Constructor)constructors.elementAt(i);
	    final Class[] paramTypes = constructor.getParameterTypes();

	    Class extType = null;
	    int currConstrDistance = 0;
	    for (j = 0; j < nArgs; j++) {
		extType = paramTypes[j];
		final Type intType = (Type)argsType.elementAt(j);
		Object match = _internal2Java.maps(intType, extType);
		if (match != null) {
		    currConstrDistance += ((JavaType)match).distance;
		}
		else if (intType instanceof ObjectType) {
		    ObjectType objectType = (ObjectType)intType;
		    if (objectType.getJavaClass() == extType)
		        continue;
		    else if (extType.isAssignableFrom(objectType.getJavaClass()))
		        currConstrDistance += 1;
		    else {
			currConstrDistance = Integer.MAX_VALUE;
			break;
		    }
		}
		else {
		    currConstrDistance = Integer.MAX_VALUE;
		    break;
		}
	    }

	    if (j == nArgs && currConstrDistance < bestConstrDistance ) {
	        _chosenConstructor = constructor;
	        _isExtConstructor = true;
		bestConstrDistance = currConstrDistance;

		if (_clazz != null)
	          _type = new ObjectType(_clazz);
		else
		  _type = new ObjectType(_className);
	    }
	}

	if (_type != null) {
	    return _type;
	}

	throw new TypeCheckError(ErrorMsg.ARGUMENT_CONVERSION_ERR, getMethodSignature(argsType));
    }

    /**
     * Type check a call to an external (Java) method.
     * The method must be static an public, and a legal type conversion
     * must exist for all its arguments and its return type.
     * Every method of name <code>_fname</code> is inspected
     * as a possible candidate.
     */
    public Type typeCheckExternal(SymbolTable stable) throws TypeCheckError {
	int nArgs = _arguments.size();
	final String name = _fname.getLocalPart();

	if (_fname.getLocalPart().equals("new")) {
	    return typeCheckConstructor(stable);
	}
	else {
	    boolean hasThisArgument = false;

	    if (nArgs == 0)
	        _isStatic = true;

	    if (!_isStatic) {
	        if (_namespace_format == NAMESPACE_FORMAT_JAVA
	  	    || _namespace_format == NAMESPACE_FORMAT_PACKAGE)
	   	    hasThisArgument = true;

	  	Expression firstArg = (Expression)_arguments.elementAt(0);
	  	Type firstArgType = (Type)firstArg.typeCheck(stable);

	  	if (_namespace_format == NAMESPACE_FORMAT_CLASS
	  	    && firstArgType instanceof ObjectType
	  	    && _clazz != null
	  	    && _clazz.isAssignableFrom(((ObjectType)firstArgType).getJavaClass()))
	  	    hasThisArgument = true;

	  	if (hasThisArgument) {
	  	    _thisArgument = (Expression) _arguments.elementAt(0);
	  	    _arguments.remove(0); nArgs--;
		    if (firstArgType instanceof ObjectType) {
		    	_className = ((ObjectType) firstArgType).getJavaClassName();
		    }
		    else
		    	throw new TypeCheckError(ErrorMsg.NO_JAVA_FUNCT_THIS_REF, name);
	  	}
	    }
	    else if (_className.length() == 0) {
		/*
		 * Warn user if external function could not be resolved.
		 * Warning will _NOT_ be issued is the call is properly
		 * wrapped in an <xsl:if> or <xsl:when> element. For details
		 * see If.parserContents() and When.parserContents()
		 */
		final Parser parser = getParser();
		if (parser != null) {
		    reportWarning(this, parser, ErrorMsg.FUNCTION_RESOLVE_ERR,
				  _fname.toString());
		}
		unresolvedExternal = true;
	    }
	}

	final Vector methods = findMethods();

	if (methods == null) {
	    throw new TypeCheckError(ErrorMsg.METHOD_NOT_FOUND_ERR, _className + "." + name);
	}

	Class extType = null;
	final int nMethods = methods.size();
	final Vector argsType = typeCheckArgs(stable);

	int bestMethodDistance  = Integer.MAX_VALUE;
	for (int j, i = 0; i < nMethods; i++) {

	    final Method method = (Method)methods.elementAt(i);
	    final Class[] paramTypes = method.getParameterTypes();

	    int currMethodDistance = 0;
	    for (j = 0; j < nArgs; j++) {
		extType = paramTypes[j];
		final Type intType = (Type)argsType.elementAt(j);
		Object match = _internal2Java.maps(intType, extType);
		if (match != null) {
		    currMethodDistance += ((JavaType)match).distance;
		}
		else {
		    if (intType instanceof ReferenceType) {
		       currMethodDistance += 1;
		    }
		    else if (intType instanceof ObjectType) {
		        ObjectType object = (ObjectType)intType;
		        if (extType.getName().equals(object.getJavaClassName()))
		            currMethodDistance += 0;
		      	else if (extType.isAssignableFrom(object.getJavaClass()))
		            currMethodDistance += 1;
		      	else {
		      	    currMethodDistance = Integer.MAX_VALUE;
		      	    break;
		        }
		    }
		    else {
		        currMethodDistance = Integer.MAX_VALUE;
		        break;
		    }
		}
	    }

	    if (j == nArgs) {
		  extType = method.getReturnType();

		  _type = (Type) _java2Internal.get(extType);
		  if (_type == null) {
		      _type = new ObjectType(extType);
		  }

		  if (_type != null && currMethodDistance < bestMethodDistance) {
		      _chosenMethod = method;
		      bestMethodDistance = currMethodDistance;
		  }
	    }
	}

	if (_chosenMethod != null && _thisArgument == null &&
	    !Modifier.isStatic(_chosenMethod.getModifiers())) {
	    throw new TypeCheckError(ErrorMsg.NO_JAVA_FUNCT_THIS_REF, getMethodSignature(argsType));
	}

	if (_type != null) {
	    if (_type == Type.NodeSet) {
            	getXSLTC().setMultiDocument(true);
            }
	    return _type;
	}

	throw new TypeCheckError(ErrorMsg.ARGUMENT_CONVERSION_ERR, getMethodSignature(argsType));
    }

    /**
     * Type check the actual arguments of this function call.
     */
    public Vector typeCheckArgs(SymbolTable stable) throws TypeCheckError {
	final Vector result = new Vector();
	final Enumeration e = _arguments.elements();
	while (e.hasMoreElements()) {
	    final Expression exp = (Expression)e.nextElement();
	    result.addElement(exp.typeCheck(stable));
	}
	return result;
    }

    protected final Expression argument(int i) {
	return (Expression)_arguments.elementAt(i);
    }

    protected final Expression argument() {
	return argument(0);
    }

    protected final int argumentCount() {
	return _arguments.size();
    }

    protected final void setArgument(int i, Expression exp) {
	_arguments.setElementAt(exp, i);
    }

    /**
     * Compile the function call and treat as an expression
     * Update true/false-lists.
     */
    public void translateDesynthesized(ClassGenerator classGen,
				       MethodGenerator methodGen)
    {
	Type type = Type.Boolean;
	if (_chosenMethodType != null)
	    type = _chosenMethodType.resultType();

	final InstructionList il = methodGen.getInstructionList();
	translate(classGen, methodGen);

	if ((type instanceof BooleanType) || (type instanceof IntType)) {
	    _falseList.add(il.append(new IFEQ(null)));
	}
    }

    /**
     * Translate a function call. The compiled code will leave the function's
     * return value on the JVM's stack.
     */
    public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
	final int n = argumentCount();
	final ConstantPoolGen cpg = classGen.getConstantPool();
	final InstructionList il = methodGen.getInstructionList();
	int index;

	if (isStandard() || isExtension()) {
	    for (int i = 0; i < n; i++) {
		final Expression exp = argument(i);
		exp.translate(classGen, methodGen);
		exp.startResetIterator(classGen, methodGen);
	    }

	    final String name = _fname.toString().replace('-', '_') + "F";
	    String args = Constants.EMPTYSTRING;

	    if (name.equals("sumF")) {
		args = DOM_INTF_SIG;
		il.append(methodGen.loadDOM());
	    }
	    else if (name.equals("normalize_spaceF")) {
		if (_chosenMethodType.toSignature(args).
		    equals("()Ljava/lang/String;")) {
		    args = "I"+DOM_INTF_SIG;
		    il.append(methodGen.loadContextNode());
		    il.append(methodGen.loadDOM());
		}
	    }

	    index = cpg.addMethodref(BASIS_LIBRARY_CLASS, name,
				     _chosenMethodType.toSignature(args));
	    il.append(new INVOKESTATIC(index));
	}
	else if (unresolvedExternal) {
	    index = cpg.addMethodref(BASIS_LIBRARY_CLASS,
				     "unresolved_externalF",
				     "(Ljava/lang/String;)V");
	    il.append(new PUSH(cpg, _fname.toString()));
	    il.append(new INVOKESTATIC(index));
	}
	else if (_isExtConstructor) {
	    final String clazz =
		_chosenConstructor.getDeclaringClass().getName();
	    Class[] paramTypes = _chosenConstructor.getParameterTypes();

	    il.append(new NEW(cpg.addClass(_className)));
	    il.append(InstructionConstants.DUP);

	    for (int i = 0; i < n; i++) {
		final Expression exp = argument(i);
		exp.translate(classGen, methodGen);
		exp.startResetIterator(classGen, methodGen);
		exp.getType().translateTo(classGen, methodGen, paramTypes[i]);
	    }

	    final StringBuffer buffer = new StringBuffer();
	    buffer.append('(');
	    for (int i = 0; i < paramTypes.length; i++) {
		buffer.append(getSignature(paramTypes[i]));
	    }
	    buffer.append(')');
	    buffer.append("V");

	    index = cpg.addMethodref(clazz,
				     "<init>",
				     buffer.toString());
	    il.append(new INVOKESPECIAL(index));

	    (Type.Object).translateFrom(classGen, methodGen,
				_chosenConstructor.getDeclaringClass());

	}
	else {
	    final String clazz = _chosenMethod.getDeclaringClass().getName();
	    Class[] paramTypes = _chosenMethod.getParameterTypes();

	    if (_thisArgument != null) {
		_thisArgument.translate(classGen, methodGen);
	    }

	    for (int i = 0; i < n; i++) {
		final Expression exp = argument(i);
		exp.translate(classGen, methodGen);
		exp.startResetIterator(classGen, methodGen);
		exp.getType().translateTo(classGen, methodGen, paramTypes[i]);
	    }

	    final StringBuffer buffer = new StringBuffer();
	    buffer.append('(');
	    for (int i = 0; i < paramTypes.length; i++) {
		buffer.append(getSignature(paramTypes[i]));
	    }
	    buffer.append(')');
	    buffer.append(getSignature(_chosenMethod.getReturnType()));

	    index = cpg.addMethodref(clazz,
				     _fname.getLocalPart(),
				     buffer.toString());
	    il.append(_thisArgument != null ? (InvokeInstruction) new INVOKEVIRTUAL(index) :
	    		  (InvokeInstruction) new INVOKESTATIC(index));

	    _type.translateFrom(classGen, methodGen,
				_chosenMethod.getReturnType());
	}
    }

    public String toString() {
	return "funcall(" + _fname + ", " + _arguments + ')';
    }

    public boolean isStandard() {
	final String namespace = _fname.getNamespace();
	return (namespace == null) || (namespace.equals(Constants.EMPTYSTRING));
    }

    public boolean isExtension() {
	final String namespace = _fname.getNamespace();
	return (namespace != null) && (namespace.equals(EXT_XSLTC));
    }

    /**
     * Returns a vector with all methods named <code>_fname</code>
     * after stripping its namespace or <code>null</code>
     * if no such methods exist.
     */
    private Vector findMethods() {

	  Vector result = null;
	  final String namespace = _fname.getNamespace();

	  if (_className != null && _className.length() > 0) {
	    final int nArgs = _arguments.size();
	    try {
	      if (_clazz == null) {
		TransletLoader loader = new TransletLoader();
		_clazz = loader.loadClass(_className);

		if (_clazz == null) {
		  final ErrorMsg msg =
		        new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, _className);
		  getParser().reportError(Constants.ERROR, msg);
		}
	      }

	      final String methodName = _fname.getLocalPart();
	      final Method[] methods = _clazz.getMethods();

	      for (int i = 0; i < methods.length; i++) {
		final int mods = methods[i].getModifiers();
		if (Modifier.isPublic(mods)
		    && methods[i].getName().equals(methodName)
		    && methods[i].getParameterTypes().length == nArgs)
		{
		  if (result == null) {
		    result = new Vector();
	          }
		  result.addElement(methods[i]);
		}
	      }
	    }
	    catch (ClassNotFoundException e) {
		  final ErrorMsg msg = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, _className);
		  getParser().reportError(Constants.ERROR, msg);
	    }
	  }
	  return result;
    }

    /**
     * Returns a vector with all constructors named <code>_fname</code>
     * after stripping its namespace or <code>null</code>
     * if no such methods exist.
     */
    private Vector findConstructors() {
        Vector result = null;
        final String namespace = _fname.getNamespace();

        final int nArgs = _arguments.size();
        try {
          if (_clazz == null) {
            TransletLoader loader = new TransletLoader();
            _clazz = loader.loadClass(_className);

            if (_clazz == null) {
              final ErrorMsg msg = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, _className);
              getParser().reportError(Constants.ERROR, msg);
            }
          }

          final Constructor[] constructors = _clazz.getConstructors();

          for (int i = 0; i < constructors.length; i++) {
              final int mods = constructors[i].getModifiers();
              if (Modifier.isPublic(mods) &&
                  constructors[i].getParameterTypes().length == nArgs)
              {
                if (result == null) {
                  result = new Vector();
                }
                result.addElement(constructors[i]);
              }
          }
        }
        catch (ClassNotFoundException e) {
          final ErrorMsg msg = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, _className);
          getParser().reportError(Constants.ERROR, msg);
        }

        return result;
    }

    /**
     * Compute the JVM signature for the class.
     */
    static final String getSignature(Class clazz) {
	if (clazz.isArray()) {
	    final StringBuffer sb = new StringBuffer();
	    Class cl = clazz;
	    while (cl.isArray()) {
		sb.append("[");
		cl = cl.getComponentType();
	    }
	    sb.append(getSignature(cl));
	    return sb.toString();
	}
	else if (clazz.isPrimitive()) {
	    if (clazz == Integer.TYPE) {
		return "I";
	    }
	    else if (clazz == Byte.TYPE) {
		return "B";
	    }
	    else if (clazz == Long.TYPE) {
		return "J";
	    }
	    else if (clazz == Float.TYPE) {
		return "F";
	    }
	    else if (clazz == Double.TYPE) {
		return "D";
	    }
	    else if (clazz == Short.TYPE) {
		return "S";
	    }
	    else if (clazz == Character.TYPE) {
		return "C";
	    }
	    else if (clazz == Boolean.TYPE) {
		return "Z";
	    }
	    else if (clazz == Void.TYPE) {
		return "V";
	    }
	    else {
		final String name = clazz.toString();
		ErrorMsg err = new ErrorMsg(ErrorMsg.UNKNOWN_SIG_TYPE_ERR,name);
		throw new Error(err.toString());
	    }
	}
	else {
	    return "L" + clazz.getName().replace('.', '/') + ';';
	}
    }

    /**
     * Compute the JVM method descriptor for the method.
     */
    static final String getSignature(Method meth) {
	final StringBuffer sb = new StringBuffer();
	sb.append('(');
	for (int j = 0; j < params.length; j++) {
	    sb.append(getSignature(params[j]));
	}
	return sb.append(')').append(getSignature(meth.getReturnType()))
	    .toString();
    }

    /**
     * Compute the JVM constructor descriptor for the constructor.
     */
    static final String getSignature(Constructor cons) {
	final StringBuffer sb = new StringBuffer();
	sb.append('(');
	for (int j = 0; j < params.length; j++) {
	    sb.append(getSignature(params[j]));
	}
	return sb.append(")V").toString();
    }

    /**
     * Return the signature of the current method
     */
    private String getMethodSignature(Vector argsType) {
 	final StringBuffer buf = new StringBuffer(_className);
        buf.append('.').append(_fname.getLocalPart()).append('(');

	int nArgs = argsType.size();
	for (int i = 0; i < nArgs; i++) {
	    final Type intType = (Type)argsType.elementAt(i);
	    buf.append(intType.toString());
	    if (i < nArgs - 1) buf.append(", ");
	}

	buf.append(')');
	return buf.toString();
    }

    /**
     * To support EXSLT extensions, convert names with dash to allowable Java names:
     * e.g., convert abc-xyz to abcXyz.
     * Note: dashes only appear in middle of an EXSLT function or element name.
     */
    protected static String replaceDash(String name)
    {
        char dash = '-';
        StringBuffer buff = new StringBuffer("");
        for (int i = 0; i < name.length(); i++) {
        if (i > 0 && name.charAt(i-1) == dash)
            buff.append(Character.toUpperCase(name.charAt(i)));
        else if (name.charAt(i) != dash)
            buff.append(name.charAt(i));
        }
        return buff.toString();

FUNC_DECL RETURN LOOP VAR_DECL VAR_DECL PARAM CALL VAR_DECL CALL CALL CALL CALL CALL

FUNC_DECL IF VAR_DECL VAR_DECL VAR_DECL VAR_DECL PARAM PARAM IF BINARY_OP IF IF VAR_DECL VAR_DECL LOOP CALL CALL CALL CALL CALL CALL ASSIGN IF CALL BINARY_OP LOOP VAR_DECL LOOP IF VAR_DECL VAR_DECL LOOP VAR_DECL LOOP VAR_DECL VAR_DECL CALL CALL ASSIGN CALL CALL CALL LITERAL_ANCHOR BINARY_OP VAR_DECL CALL CALL ASSIGN CALL CALL BINARY_OP CALL BINARY_OP BINARY_OP CALL ASSIGN CALL CALL BINARY_OP CALL BINARY_OP CALL CALL CALL CALL CALL CALL IF LITERAL_ANCHOR CALL ASSIGN LITERAL_ANCHOR CALL CALL CALL LITERAL_ANCHOR CALL COND_EXPR CALL CALL LITERAL_ANCHOR LITERAL_ANCHOR CALL VAR_DECL LITERAL_ANCHOR CALL CALL CALL CALL CALL LITERAL_ANCHOR LITERAL_ANCHOR LITERAL_ANCHOR CALL VAR_DECL CALL CALL CALL CALL LITERAL_ANCHOR LITERAL_ANCHOR CALL CALL CALL CALL BINARY_OP CALL CALL CALL CALL LITERAL_ANCHOR CALL CALL CALL LITERAL_ANCHOR CALL CALL CALL CALL LITERAL_ANCHOR CALL LITERAL_ANCHOR CALL CALL CALL LITERAL_ANCHOR CALL CALL CALL LITERAL_ANCHOR LITERAL_ANCHOR CALL CALL LITERAL_ANCHOR CALL CALL CALL CALL CALL CALL CALL CALL ASSIGN LITERAL_ANCHOR CALL CALL BINARY_OP LITERAL_ANCHOR

FUNC_DECL RETURN LOOP VAR_DECL PARAM CALL BINARY_OP CALL LITERAL_ANCHOR CALL CALL LITERAL_ANCHOR CALL CALL CALL LITERAL_ANCHOR CALL CALL

FUNC_DECL PARAM PARAM ASSIGN ASSIGN ASSIGN LITERAL_ANCHOR


public interface BufferSetListener extends EventListener
{
	/**
	 * A buffer was added in the bufferSet.
	 *
	 * @param buffer the buffer
	 * @param index the position where it was added
	 */
	void bufferAdded(Buffer buffer, int index);

	/**
	 * A buffer was removed from the bufferSet.
	 *
	 * @param buffer the removed buffer
	 * @param index the position where the buffer was
	 */
	void bufferRemoved(Buffer buffer, int index);

	/**
	 * A buffer was moved in the BufferSet.
	 *
	 * @param buffer the moved buffer
	 * @param oldIndex the old index
	 * @param newIndex the new index
	 */
	void bufferMoved(Buffer buffer, int oldIndex, int newIndex);

	/**
	 * The bufferSet was sorted.
	 */
	void bufferSetSorted();


org.gjt.sp.jedit.menu.PluginsProvider

public class PluginsProvider implements DynamicMenuProvider
{
	//{{{ updateEveryTime() method
	public boolean updateEveryTime()
	{
		return false;
	} //}}}

	//{{{ update() method
	public void update(JMenu menu)
	{
		// We build a set of lists, each list contains plugin menu
		// items that begin with a given letter.
		int count = 0;

		List<JMenuItem>[] letters = (List<JMenuItem>[])new List[26];
		for(int i = 0; i < letters.length; i++)
		{
			letters[i] = new ArrayList<JMenuItem>();
		}

		Vector<JMenuItem> pluginMenuItems = new Vector<JMenuItem>();

		PluginJAR[] pluginArray = jEdit.getPluginJARs();
		for(int i = 0; i < pluginArray.length; i++)
		{
			PluginJAR jar = pluginArray[i];
			EditPlugin plugin = jar.getPlugin();
			if(plugin == null)
				continue;

			JMenuItem menuItem = plugin.createMenuItems();
			if(menuItem != null)
			{
				addToLetterMap(letters,menuItem);
				count++;
			}
			//{{{ old API
			else if(jEdit.getProperty("plugin."
				+ plugin.getClassName()
				+ ".activate") == null)
			{
				try
				{
					pluginMenuItems.clear();
					plugin.createMenuItems(pluginMenuItems);

					Iterator<JMenuItem> iter
						= pluginMenuItems.iterator();
					while(iter.hasNext())
					{
						addToLetterMap(letters,
							iter.next());
						count++;
					}
				}
				catch(Throwable t)
				{
					Log.log(Log.ERROR,this,
						"Error creating menu items"
						+ " for plugin");
					Log.log(Log.ERROR,this,t);
				}
			} //}}}
		}

		if(count == 0)
		{
			JMenuItem menuItem = new JMenuItem(
				jEdit.getProperty("no-plugins.label"));
			menuItem.setEnabled(false);
			menu.add(menuItem);
			return;
		}

		// Sort each letter
		for(int i = 0; i < letters.length; i++)
		{
			Collections.sort(letters[i],new MenuItemTextComparator());
		}

		int maxItems = jEdit.getIntegerProperty("menu.spillover",20);

		// if less than 20 items, put them directly in the menu
		if(count <= maxItems)
		{
			for(int i = 0; i < letters.length; i++)
			{
				Iterator<JMenuItem> iter
					= letters[i].iterator();
				while(iter.hasNext())
				{
					menu.add(iter.next());
				}
			}

			return;
		}

		// Collect blocks of up to maxItems of consecutive letters
		count = 0;
		char first = 'A';
		JMenu submenu = new JMenu();
		menu.add(submenu);

		for(int i = 0; i < letters.length; i++)
		{
			List<JMenuItem> letter = letters[i];

			if(count + letter.size() > maxItems && count != 0)
			{
				char last = (char)(i + 'A' - 1);
				if(last == first)
					submenu.setText(String.valueOf(first));
				else
					submenu.setText(first + " - " + last);
				first = (char)(i + 'A');
				count = 0;
				submenu = null;
			}

			Iterator<JMenuItem> iter = letter.iterator();
			while(iter.hasNext())
			{
				if(submenu == null)
				{
					submenu = new JMenu();
					menu.add(submenu);
				}
				submenu.add(iter.next());
			}

			count += letter.size();
		}

		if(submenu != null)
		{
			char last = 'Z';
			if(last == first)
				submenu.setText(String.valueOf(first));
			else
				submenu.setText(first + " - " + last);
		}
	} //}}}

	//{{{ addToLetterMap() method
	private void addToLetterMap(List<JMenuItem>[] letters, JMenuItem item)
	{
		char ch = item.getText().charAt(0);
		ch = Character.toUpperCase(ch);
		if(ch < 'A' || ch > 'Z')
		{
			Log.log(Log.ERROR,this,"Plugin menu item label must "
				+ "begin with A - Z, or a - z: "
				+ item.getText());
		}
		else
			letters[ch - 'A'].add(item);


org.apache.camel.model.ProceedType

@XmlRootElement(name = "proceed")
@XmlAccessorType(XmlAccessType.FIELD)
public class ProceedType extends ProcessorType {

    public List<ProcessorType> getOutputs() {
        return Collections.EMPTY_LIST;
    }

    public List<InterceptorType> getInterceptors() {
        return Collections.EMPTY_LIST;
    }

    public Processor createProcessor(RouteContext routeContext) throws Exception {
        return routeContext.createProceedProcessor();


org.apache.camel.view.XmlGraphGenerator

public class XmlGraphGenerator extends GraphGeneratorSupport {
    private boolean addUrl = true;

    public XmlGraphGenerator(String dir) {
        super(dir, ".xml");
    }

    protected void generateFile(PrintWriter writer, Map<String, List<RouteType>> map) {
        writer.println("<?xml version='1.0' encoding='UTF-8'?>");
        writer.println("<Graph>");
        writer.println();

        if (map.size() > 0) {
            writer.println("<Node id='root' name='Camel Routes' description='Collection of Camel Routes' nodeType='root'/>");
        }
        printRoutes(writer, map);

        writer.println();
        writer.println("</Graph>");
    }

    protected void printRoutes(PrintWriter writer, Map<String, List<RouteType>> map) {
        Set<Map.Entry<String, List<RouteType>>> entries = map.entrySet();
        for (Map.Entry<String, List<RouteType>> entry : entries) {
            String group = entry.getKey();
            printRoutes(writer, group, entry.getValue());
        }
    }

    protected void printRoutes(PrintWriter writer, String group, List<RouteType> routes) {
        group = encode(group);
        if (group != null) {
            int idx = group.lastIndexOf('.');
            String name =group;
            if (idx > 0 && idx < group.length() -1 ) {
                name = group.substring(idx + 1);
            }
            writer.println("<Node id='" + group + "' name='" + name + "' description='" + group + "' nodeType='group'/>");
            writer.println("<Edge fromID='root' toID='" + group + "'/>");
        }
        for (RouteType route : routes) {
            List<FromType> inputs = route.getInputs();
            boolean first = true;
            for (FromType input : inputs) {
                NodeData nodeData = getNodeData(input);
                if (first) {
                    first = false;
                    if (group != null) {
                        writer.println("<Edge fromID='" + group + "' toID='" + encode(nodeData.id) + "'/>");
                    }
                }
                printRoute(writer, route, nodeData);
            }
            writer.println();
        }
    }

    protected void printRoute(PrintWriter writer, final RouteType route, NodeData nodeData) {
        printNode(writer, nodeData);

        List<ProcessorType> outputs = route.getOutputs();
        NodeData from = nodeData;
        for (ProcessorType output : outputs) {
            NodeData newData = printNode(writer, from, output);
            from = newData;
        }
    }

    protected NodeData printNode(PrintWriter writer, NodeData fromData, ProcessorType node) {
        if (node instanceof MulticastType) {
            List<ProcessorType> outputs = node.getOutputs();
            for (ProcessorType output : outputs) {
                printNode(writer, fromData, output);
            }
            return fromData;
        }
        NodeData toData = getNodeData(node);

        printNode(writer, toData);

        if (fromData != null) {
            writer.print("<Edge fromID=\"");
            writer.print(encode(fromData.id));
            writer.print("\" toID=\"");
            writer.print(encode(toData.id));
            String association = toData.edgeLabel;
            if (isNullOrBlank(association)) {
                writer.print("\" association=\"");
                writer.print(encode(association));
            }
            writer.println("\"/>");
        }

        List<ProcessorType> outputs = toData.outputs;
        if (outputs != null) {
            for (ProcessorType output : outputs) {
                NodeData newData = printNode(writer, toData, output);
                if (!isMulticastNode(node)) {
                    toData = newData;
                }
            }
        }
        return toData;
    }

    protected void printNode(PrintWriter writer, NodeData data) {
        if (!data.nodeWritten) {
            data.nodeWritten = true;

            writer.println();
            writer.print("<Node id=\"");
            writer.print(encode(data.id));
            writer.print("\" name=\"");
            String name = data.label;
            if (isNullOrBlank(name)) {
                name = data.tooltop;
            }
            writer.print(encode(name));
            writer.print("\" nodeType=\"");
            String nodeType = data.image;
            if (isNullOrBlank(nodeType)) {
                nodeType = data.shape;
                if (isNullOrBlank(nodeType)) {
                    nodeType = "node";
                }
            }
            writer.print(encode(nodeType));
            writer.print("\" description=\"");
            writer.print(encode(data.tooltop));
            if (addUrl) {
                writer.print("\" url=\"");
                writer.print(encode(data.url));
            }
            writer.println("\"/>");
        }
    }

    protected String encode(String text) {
        if (text == null) {
            return "";
        }
        return text.replaceAll("\"", """).replaceAll("<", "<").
                replaceAll(">", ">").replaceAll("&", "&");

FUNC_DECL LOOP VAR_DECL PARAM PARAM VAR_DECL CALL CALL CALL CALL

FUNC_DECL LOOP VAR_DECL VAR_DECL PARAM PARAM PARAM CALL VAR_DECL CALL ASSIGN CALL

FUNC_DECL RETURN IF VAR_DECL IF VAR_DECL IF PARAM PARAM PARAM BINARY_OP BINARY_OP CALL BINARY_OP LOOP LITERAL_ANCHOR IF VAR_DECL LITERAL_ANCHOR CALL RETURN LOOP VAR_DECL CALL CALL CALL CALL CALL CALL IF VAR_DECL LITERAL_ANCHOR CALL LITERAL_ANCHOR CALL LITERAL_ANCHOR CALL CALL CALL CALL CALL CALL CALL LITERAL_ANCHOR ASSIGN

FUNC_DECL IF PARAM PARAM IF IF VAR_DECL IF VAR_DECL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL ASSIGN LITERAL_ANCHOR CALL LITERAL_ANCHOR CALL IF LITERAL_ANCHOR CALL LITERAL_ANCHOR CALL LITERAL_ANCHOR LITERAL_ANCHOR CALL CALL CALL ASSIGN ASSIGN CALL LITERAL_ANCHOR ASSIGN LITERAL_ANCHOR


org.gjt.sp.jedit.io.BufferIORequest

public class BufferIORequest extends WorkRequest
{
	/**
	 * Size of I/O buffers.
	 */
	public static final int IOBUFSIZE = 32768;

	/**
	 * Number of lines per progress increment.
	 */
	public static final int PROGRESS_INTERVAL = 300;

	/**
	 * Property loaded data is stored in.
	 */
	public static final String LOAD_DATA = "IORequest__loadData";

	/**
	 * A file load request.
	 */
	public static final int LOAD = 0;

	/**
	 * A file save request.
	 */
	public static final int SAVE = 1;

	/**
	 * An autosave request. Only supported for local files.
	 */
	public static final int AUTOSAVE = 2;

	/**
	 * An insert file request.
	 */
	public static final int INSERT = 3;

	/**
	 * Creates a new buffer I/O request.
	 * @param type The request type
	 * @param view The view
	 * @param buffer The buffer
	 * @param session The VFS session
	 * @param vfs The VFS
	 * @param path The path
	 */
	public BufferIORequest(int type, View view, Buffer buffer,
		Object session, VFS vfs, String path)
	{
		this.type = type;
		this.view = view;
		this.buffer = buffer;
		this.session = session;
		this.vfs = vfs;
		this.path = path;

		markersPath = vfs.getParentOfPath(path)
			+ '.' + vfs.getFileName(path)
			+ ".marks";
	}

	public void run()
	{
		switch(type)
		{
		case LOAD:
			load();
			break;
		case SAVE:
			save();
			break;
		case AUTOSAVE:
			autosave();
			break;
		case INSERT:
			insert();
			break;
		}
	}

	public String toString()
	{
		String typeString;
		switch(type)
		{
		case LOAD:
			typeString = "LOAD";
			break;
		case SAVE:
			typeString = "SAVE";
			break;
		case AUTOSAVE:
			typeString = "AUTOSAVE";
			break;
		default:
			typeString = "UNKNOWN!!!";
		}

		return getClass().getName() + "[type=" + typeString
			+ ",buffer=" + buffer + "]";
	}

	// private members
	private int type;
	private View view;
	private Buffer buffer;
	private Object session;
	private VFS vfs;
	private String path;
	private String markersPath;

	private void load()
	{
		InputStream in = null;

		try
		{
			try
			{
				String[] args = { vfs.getFileName(path) };
				setStatus(jEdit.getProperty("vfs.status.load",args));
				setAbortable(true);
				setProgressValue(0);

				VFS.DirectoryEntry entry = vfs._getDirectoryEntry(
					session,path,view);
				long length;
				if(entry != null)
					length = entry.length;
				else
					length = 0L;

				in = vfs._createInputStream(session,path,false,view);
				if(in == null)
					return;

				if(path.endsWith(".gz"))
					in = new GZIPInputStream(in);

				String lineSeparator = read(buffer,in,length);
				buffer.putProperty(Buffer.LINESEP,lineSeparator);
				buffer.setNewFile(false);
			}
			catch(CharConversionException ch)
			{
				Log.log(Log.ERROR,this,ch);
				Object[] pp = { path,
					buffer.getProperty(Buffer.ENCODING),
					ch.toString() };
				VFSManager.error(view,"encoding-error",pp);
			}
			catch(IOException io)
			{
				Log.log(Log.ERROR,this,io);
				Object[] pp = { path, io.toString() };
				VFSManager.error(view,"read-error",pp);
			}

			if(jEdit.getBooleanProperty("persistentMarkers"))
			{
				try
				{
					String[] args = { vfs.getFileName(path) };
					setStatus(jEdit.getProperty("vfs.status.load-markers",args));
					setAbortable(true);

					in = vfs._createInputStream(session,markersPath,true,view);
					if(in != null)
						readMarkers(buffer,in);
				}
				catch(IOException io)
				{
					// ignore
				}
			}
		}
		catch(WorkThread.Abort a)
		{
			if(in != null)
			{
				try
				{
					in.close();
				}
				catch(IOException io)
				{
				}
			}
		}
		finally
		{
			try
			{
				vfs._endVFSSession(session,view);
			}
			catch(IOException io)
			{
				Log.log(Log.ERROR,this,io);
				String[] pp = { path, io.toString() };
				VFSManager.error(view,"read-error",pp);
			}
			catch(WorkThread.Abort a)
			{
			}
		}
	}

	/**
	 * Reads the buffer from the specified input stream. Read and
	 * understand all these notes if you want to snarf this code for
	 * your own app; it has a number of subtle behaviours which are
	 * not entirely obvious.

	 *
	 * Some notes that will help future hackers:
	 *

	 *

	 * We use a StringBuffer because there is no way to pre-allocate
	 * in the GapContent - and adding text each time to the GapContent
	 * would be slow because it would require array enlarging, etc.
	 * Better to do as few gap inserts as possible.
	 *
	 *
The StringBuffer is pre-allocated to the file's size (obtained
	 * from the VFS). If the file size is not known, we default to
	 * IOBUFSIZE.
	 *
	 *
We read the stream in IOBUFSIZE (= 32k) blocks, and loop over
	 * the read characters looking for line breaks.
	 *

	 *
a \r or \n causes a line to be added to the model, and appended
	 * to the string buffer
	 *
a \n immediately following an \r is ignored; so that Windows
	 * line endings are handled
	 *

	 *
	 *
This method remembers the line separator used in the file, and
	 * stores it in the lineSeparator buffer-local property. However,
	 * if the file contains, say, hello\rworld\n, lineSeparator will
	 * be set to \n, and the file will be saved as hello\nworld\n.
	 * Hence jEdit is not really appropriate for editing binary files.
	 *
	 *
To make reloading a bit easier, this method automatically
	 * removes all data from the model before inserting it. This
	 * shouldn't cause any problems, as most documents will be
	 * empty before being loaded into anyway.
	 *
	 *
If the last character read from the file is a line separator,
	 * it is not added to the model! There are two reasons:
	 *

	 *
On Unix, all text files have a line separator at the end,
	 * there is no point wasting an empty screen line on that
	 *
Because save() appends a line separator after *every* line,
	 * it prevents the blank line count at the end from growing
	 *

	 *
	 *

	 */
	private String read(Buffer buffer, InputStream _in, long length)
		throws IOException
	{
		// only true if the file size is known
		boolean trackProgress = (length != 0);
		File file = buffer.getFile();

		setProgressValue(0);
		setProgressMaximum((int)length);

		// if the file size is not known, start with a resonable
		// default buffer size
		if(length == 0)
			length = IOBUFSIZE;

		StringBuffer sbuf = new StringBuffer((int)length);

		InputStreamReader in = new InputStreamReader(_in,
			(String)buffer.getProperty(Buffer.ENCODING));
		char[] buf = new char[IOBUFSIZE];
		// Number of characters in 'buf' array.
		// InputStream.read() doesn't always fill the
		// array (eg, the file size is not a multiple of
		// IOBUFSIZE, or it is a GZipped file, etc)
		int len;

		// True if a \n was read after a \r. Usually
		// means this is a DOS/Windows file
		boolean CRLF = false;

		// A \r was read, hence a MacOS file
		boolean CROnly = false;

		// Was the previous read character a \r?
		// If we read a \n and this is true, we assume
		// we have a DOS/Windows file
		boolean lastWasCR = false;

		// Number of lines read. Every 100 lines, we update the
		// progress bar
		int lineCount = 0;

		while((len = in.read(buf,0,buf.length)) != -1)
		{
			// Offset of previous line, relative to
			// the start of the I/O buffer (NOT
			// relative to the start of the document)
			int lastLine = 0;

			for(int i = 0; i < len; i++)
			{
				// Look for line endings.
				switch(buf[i])
				{
				case '\r':
					// If we read a \r and
					// lastWasCR is also true,
					// it is probably a Mac file
					// (\r\r in stream)
					if(lastWasCR)
					{
						CROnly = true;
						CRLF = false;
					}
					// Otherwise set a flag,
					// so that \n knows that last
					// was a \r
					else
					{
						lastWasCR = true;
					}

					// Insert a line
					sbuf.append(buf,lastLine,i -
						lastLine);
					sbuf.append('\n');
					if(trackProgress && lineCount++ % PROGRESS_INTERVAL == 0)
						setProgressValue(sbuf.length());

					// This is i+1 to take the
					// trailing \n into account
					lastLine = i + 1;
					break;
				case '\n':
					// If lastWasCR is true,
					// we just read a \r followed
					// by a \n. We specify that
					// this is a Windows file,
					// but take no further
					// action and just ignore
					// the \r.
					if(lastWasCR)
					{
						CROnly = false;
						CRLF = true;
						lastWasCR = false;
						// Bump lastLine so
						// that the next line
						// doesn't erronously
						// pick up the \r
						lastLine = i + 1;
					}
					// Otherwise, we found a \n
					// that follows some other
					// character, hence we have
					// a Unix file
					else
					{
						CROnly = false;
						CRLF = false;
						sbuf.append(buf,lastLine,
							i - lastLine);
						sbuf.append('\n');
						if(trackProgress && lineCount++ % PROGRESS_INTERVAL == 0)
							setProgressValue(sbuf.length());
						lastLine = i + 1;
					}
					break;
				default:
					// If we find some other
					// character that follows
					// a \r, so it is not a
					// Windows file, and probably
					// a Mac file
					if(lastWasCR)
					{
						CROnly = true;
						CRLF = false;
						lastWasCR = false;
					}
					break;
				}
			}

			if(trackProgress)
				setProgressValue(sbuf.length());

			// Add remaining stuff from buffer
			sbuf.append(buf,lastLine,len - lastLine);
		}

		setAbortable(false);

		String returnValue;
		if(CRLF)
			returnValue = "\r\n";
		else if(CROnly)
			returnValue = "\r";
		else
			returnValue = "\n";

		in.close();

		// Chop trailing newline and/or ^Z (if any)
		int bufferLength = sbuf.length();
		if(bufferLength != 0)
		{
			char ch = sbuf.charAt(bufferLength - 1);
			if(length >= 2 && ch == 0x1a /* DOS ^Z */
				&& sbuf.charAt(bufferLength - 2) == '\n')
				sbuf.setLength(bufferLength - 2);
			else if(ch == '\n')
				sbuf.setLength(bufferLength - 1);
		}

		// to avoid having to deal with read/write locks and such,
		// we insert the loaded data into the buffer in the
		// post-load cleanup runnable, which runs in the AWT thread.
		buffer.putProperty(LOAD_DATA,sbuf);

		return returnValue;
	}

	private void readMarkers(Buffer buffer, InputStream _in)
		throws IOException
	{
		// For `reload' command
		buffer.removeAllMarkers();

		BufferedReader in = new BufferedReader(new InputStreamReader(_in));

		String line;
		while((line = in.readLine()) != null)
		{
			// compatibility kludge for jEdit 3.1 and earlier
			if(!line.startsWith("!"))
				continue;

			char shortcut = line.charAt(1);
			int start = line.indexOf(';');
			int end = line.indexOf(';',start + 1);
			int position = Integer.parseInt(line.substring(start + 1,end));
			buffer.addMarker(shortcut,position);
		}

		in.close();
	}

	private void save()
	{
		OutputStream out = null;

		try
		{
			String[] args = { vfs.getFileName(path) };
			setStatus(jEdit.getProperty("vfs.status.save",args));

			// the entire save operation can be aborted...
			setAbortable(true);

			try
			{
				buffer.readLock();

				/* if the VFS supports renaming files, we first
				 * save to #<filename>#save#, then rename that
				 * to <filename>, so that if the save fails,
				 * data will not be lost */
				String savePath;

				if((vfs.getCapabilities() & VFS.RENAME_CAP) != 0)
				{
					savePath = vfs.getParentOfPath(path)
						+ '#' + vfs.getFileName(path)
						+ "#save#";
				}
				else
					savePath = path;

				out = vfs._createOutputStream(session,savePath,view);
				if(out != null)
				{
					if(path.endsWith(".gz"))
						out = new GZIPOutputStream(out);

					write(buffer,out);
				}

				// Only backup once per session
				if(buffer.getProperty(Buffer.BACKED_UP) == null)
				{
					vfs._backup(session,path,view);
					buffer.putProperty(Buffer.BACKED_UP,Boolean.TRUE);
				}

				if((vfs.getCapabilities() & VFS.RENAME_CAP) != 0)
					vfs._rename(session,savePath,path,view);

				// We only save markers to VFS's that support deletion.
				// Otherwise, we will accumilate stale marks files.
				if((vfs.getCapabilities() & VFS.DELETE_CAP) != 0)
				{
					if(jEdit.getBooleanProperty("persistentMarkers")
						&& buffer.getMarkers().size() != 0)
					{
						setStatus(jEdit.getProperty("vfs.status.save-markers",args));
						setProgressValue(0);
						out = vfs._createOutputStream(session,markersPath,view);
						if(out != null)
							writeMarkers(buffer,out);
					}
					else
						vfs._delete(session,markersPath,view);
				}
			}
			catch(BadLocationException bl)
			{
				Log.log(Log.ERROR,this,bl);
			}
			catch(IOException io)
			{
				Log.log(Log.ERROR,this,io);
				String[] pp = { path, io.toString() };
				VFSManager.error(view,"write-error",pp);
			}
			finally
			{
				buffer.readUnlock();
			}
		}
		catch(WorkThread.Abort a)
		{
			if(out != null)
			{
				try
				{
					out.close();
				}
				catch(IOException io)
				{
				}
			}
		}
		finally
		{
			try
			{
				vfs._saveComplete(session,buffer,view);
				vfs._endVFSSession(session,view);
			}
			catch(IOException io)
			{
				Log.log(Log.ERROR,this,io);
				String[] pp = { path, io.toString() };
				VFSManager.error(view,"write-error",pp);
			}
			catch(WorkThread.Abort a)
			{
			}
		}
	}

	private void autosave()
	{
		OutputStream out = null;

		try
		{
			String[] args = { vfs.getFileName(path) };
			setStatus(jEdit.getProperty("vfs.status.autosave",args));

			// the entire save operation can be aborted...
			setAbortable(true);

			try
			{
				buffer.readLock();

				if(!buffer.isDirty())
				{
					// buffer has been saved while we
					// were waiting.
					return;
				}

				out = vfs._createOutputStream(session,path,view);
				if(out == null)
					return;

				write(buffer,out);
			}
			catch(BadLocationException bl)
			{
				Log.log(Log.ERROR,this,bl);
			}
			catch(IOException io)
			{
				/* Log.log(Log.ERROR,this,io);
				args[0] = io.toString();
				VFSManager.error(view,"ioerror",args); */
			}
			finally
			{
				buffer.readUnlock();
			}
		}
		catch(WorkThread.Abort a)
		{
			if(out != null)
			{
				try
				{
					out.close();
				}
				catch(IOException io)
				{
				}
			}
		}
	}

	private void write(Buffer buffer, OutputStream _out)
		throws IOException, BadLocationException
	{
		BufferedWriter out = new BufferedWriter(
			new OutputStreamWriter(_out,
				(String)buffer.getProperty(Buffer.ENCODING)),
				IOBUFSIZE);
		Segment lineSegment = new Segment();
		String newline = (String)buffer.getProperty(Buffer.LINESEP);
		if(newline == null)
			newline = System.getProperty("line.separator");
		Element map = buffer.getDefaultRootElement();

		setProgressMaximum(map.getElementCount() / PROGRESS_INTERVAL);
		setProgressValue(0);

		int i = 0;
		while(i < map.getElementCount())
		{
			Element line = map.getElement(i);
			int start = line.getStartOffset();
			buffer.getText(start,line.getEndOffset() - start - 1,
				lineSegment);
			out.write(lineSegment.array,lineSegment.offset,
				lineSegment.count);
			out.write(newline);

			if(++i % PROGRESS_INTERVAL == 0)
				setProgressValue(i / PROGRESS_INTERVAL);
		}
		out.close();
	}

	private void writeMarkers(Buffer buffer, OutputStream out)
		throws IOException
	{
		Writer o = new BufferedWriter(new OutputStreamWriter(out));
		Vector markers = buffer.getMarkers();
		for(int i = 0; i < markers.size(); i++)
		{
			Marker marker = (Marker)markers.elementAt(i);
			o.write('!');
			o.write(marker.getShortcut());
			o.write(';');

			String pos = String.valueOf(marker.getPosition());
			o.write(pos);
			o.write(';');
			o.write(pos);
			o.write('\n');
		}
		o.close();
	}

	private void insert()
	{
		InputStream in = null;

		try
		{
			try
			{
				String[] args = { vfs.getFileName(path) };
				setStatus(jEdit.getProperty("vfs.status.load",args));
				setAbortable(true);

				VFS.DirectoryEntry entry = vfs._getDirectoryEntry(
					session,path,view);
				long length;
				if(entry != null)
					length = entry.length;
				else
					length = 0L;

				in = vfs._createInputStream(session,path,false,view);
				if(in == null)
					return;

				if(path.endsWith(".gz"))
					in = new GZIPInputStream(in);

				read(buffer,in,length);
			}
			catch(IOException io)
			{
				Log.log(Log.ERROR,this,io);
				String[] pp = { path, io.toString() };
				VFSManager.error(view,"read-error",pp);
			}
		}
		catch(WorkThread.Abort a)
		{
			if(in != null)
			{
				try
				{
					in.close();
				}
				catch(IOException io)
				{
				}
			}
		}
		finally
		{
			try
			{
				vfs._endVFSSession(session,view);
			}
			catch(IOException io)
			{
				Log.log(Log.ERROR,this,io);
				String[] pp = { path, io.toString() };
				VFSManager.error(view,"read-error",pp);

FUNC_DECL TRY VAR_DECL CATCH TRY VAR_DECL IF CATCH CATCH IF IF CALL CALL LITERAL_ANCHOR BINARY_OP CALL CALL RETURN BINARY_OP ASSIGN CALL CALL LITERAL_ANCHOR CALL TRY LITERAL_ANCHOR CALL LITERAL_ANCHOR CALL RETURN LITERAL_ANCHOR CALL CATCH CALL

FUNC_DECL PARAM PARAM PARAM PARAM PARAM PARAM ASSIGN ASSIGN ASSIGN ASSIGN ASSIGN ASSIGN ASSIGN BINARY_OP LITERAL_ANCHOR BINARY_OP CALL BINARY_OP LITERAL_ANCHOR CALL


public class LessThanPtg
    extends OperationPtg
{
    /** the size of the Ptg  */
    public final static int SIZE = 1;

    /** the sid for the less than operator as hex */
    public final static byte sid  = 0x09;

    /** identifier for LESS THAN char */
    private final static String LESSTHAN = "<";

    /**
     * Constructor. Creates new LessThanPtg
     */
    public LessThanPtg()
    {
    }

    /**
     * Constructor. Create a new LessThanPtg.
     * @param data the byte array to have the PTG added to
     * @param offset the offset to the PTG to.
     */
    public LessThanPtg(RecordInputStream in)
    {
    }

    /**
     * Write the sid to an array
     * @param array the array of bytes to write the sid to
     * @param offset the offset to add the sid to
     */
    public void writeBytes(byte[] array, int offset)
    {
        array[ offset + 0 ] = sid;
    }

    /**
     * Get the size of the sid
     * @return int the size of the sid in terms of byte additions to an array
     */
    public int getSize()
    {
        return SIZE;
    }

    /**
     * Get the type of PTG for Less Than
     * @return int the identifier for the type
     */
    public int getType()
    {
        return TYPE_BINARY;
    }

    /**
     * Get the number of operands for the Less than operator
     * @return int the number of operands
     */
    public int getNumberOfOperands()
    {
        return 2;
    }

    /**
     * Implementation of method from Ptg
     * @param book the Sheet References
     */
    public String toFormulaString(Workbook book)
    {
        return this.LESSTHAN;
    }

    /**
     * Implementation of method from OperationsPtg
     * @param operands a String array of operands
     * @return String the Formula as a String
     */
    public String toFormulaString(String[] operands)
    {
        StringBuffer buffer = new StringBuffer();
        buffer.append(operands[ 0 ]);
        buffer.append(this.LESSTHAN);
        buffer.append(operands[ 1 ]);
        return buffer.toString();
    }

    /**
     * Get the default operands class value
     * @return byte the Ptg Class Value as a byte from the Ptg Parent object
     */
    public byte getDefaultOperandClass()
    {
        return Ptg.CLASS_VALUE;
    }

    /**
     * Implementation of clone method from Object
     * @return Object a clone of this class as an Object
     */
    public Object clone()
    {
        return new LessThanPtg();

    public int getSize()
    {
        return SIZE;