void parseDoctypedecl() throws java.lang.Exception
    {
        char c;
        String doctypeName, ids[];

        // Read the document type name.
        requireWhitespace();
        doctypeName = readNmtoken(true);

        // Read the ExternalIDs.
        skipWhitespace();
        ids = readExternalIds(false);

        // Look for a declaration subset.
        skipWhitespace();
        if (tryRead('[')) {

            // loop until the subset ends
            while (true) {
                context = CONTEXT_DTD;
                skipWhitespace();
                context = CONTEXT_NONE;
                if (tryRead(']')) {
                    break; // end of subset
                } else {
                    context = CONTEXT_DTD;
                    parseMarkupdecl();
                    context = CONTEXT_NONE;
                }
            }
        }

        // Read the external subset, if any
        if (ids[1] != null) {
            pushURL("[external subset]", ids[0], ids[1], null, null, null);

            // Loop until we end up back at '>'
            while (true) {
                context = CONTEXT_DTD;
                skipWhitespace();
                context = CONTEXT_NONE;
                if (tryRead('>')) {
                    break;
                } else {
                    context = CONTEXT_DTD;
                    parseMarkupdecl();
                    context = CONTEXT_NONE;
                }
            }
        } else {
            // No external subset.
            skipWhitespace();
            require('>');
        }

        if (handler != null) {
            handler.doctypeDecl(doctypeName, ids[0], ids[1]);
        }

        // Expand general entities in
        // default values of attributes.
        // (Do this after the doctypeDecl
        // event!).
        // expandAttributeDefaultValues();
    }