docs: private void scanXMLDeclOrTextDecl(boolean scanningTextDecl,
  				       String[] pseudoAttributeValues) 
                  throws IOException, JspCoreException {
  
          // pseudo-attribute values
          String version = null;
          String encoding = null;
          String standalone = null;
  
          // scan pseudo-attributes
          final int STATE_VERSION = 0;
          final int STATE_ENCODING = 1;
          final int STATE_STANDALONE = 2;
          final int STATE_DONE = 3;
          int state = STATE_VERSION;
  
          boolean dataFoundForTarget = false;
          boolean sawSpace = skipSpaces();
          while (peekChar() != '?') {
              dataFoundForTarget = true;
              String name = scanPseudoAttribute(scanningTextDecl, fString);
              switch (state) {
                  case STATE_VERSION: {
                      if (name == fVersionSymbol) {
                          if (!sawSpace) {
                              reportFatalError(scanningTextDecl
                                         ? "jsp.error.xml.spaceRequiredBeforeVersionInTextDecl"
                                         : "jsp.error.xml.spaceRequiredBeforeVersionInXMLDecl",
                                               null);
                          }
                          version = fString.toString();
                          state = STATE_ENCODING;
                          if (!version.equals("1.0")) {
                              // REVISIT: XML REC says we should throw an error
  			    // in such cases.
                              // some may object the throwing of fatalError.
                              throw new JspCoreException("jsp.error.xml.versionNotSupported", new Object[] { version });
                              //err.jspError("jsp.error.xml.versionNotSupported", version);
                          }
                      } else if (name == fEncodingSymbol) {
                          if (!scanningTextDecl) {
                              throw new JspCoreException("jsp.error.xml.versionInfoRequired");
                              //err.jspError("jsp.error.xml.versionInfoRequired");
                          }
                          if (!sawSpace) {
                              reportFatalError(scanningTextDecl
                                        ? "jsp.error.xml.spaceRequiredBeforeEncodingInTextDecl"
                                        : "jsp.error.xml.spaceRequiredBeforeEncodingInXMLDecl",
                                               null);
                          }
                          encoding = fString.toString();
                          state = scanningTextDecl ? STATE_DONE : STATE_STANDALONE;
                      } else {
                          if (scanningTextDecl) {
                              throw new JspCoreException("jsp.error.xml.encodingDeclRequired");
                              //err.jspError("jsp.error.xml.encodingDeclRequired");
                          }
                          else {
                              throw new JspCoreException("jsp.error.xml.versionInfoRequired");
                              //err.jspError("jsp.error.xml.versionInfoRequired");
                          }
                      }
                      break;
                  }
                  case STATE_ENCODING: {
                      if (name == fEncodingSymbol) {
                          if (!sawSpace) {
                              reportFatalError(scanningTextDecl
                                        ? "jsp.error.xml.spaceRequiredBeforeEncodingInTextDecl"
                                        : "jsp.error.xml.spaceRequiredBeforeEncodingInXMLDecl",
                                               null);
                          }
                          encoding = fString.toString();
                          state = scanningTextDecl ? STATE_DONE : STATE_STANDALONE;
                          // TODO: check encoding name; set encoding on
                          //       entity scanner
                      } else if (!scanningTextDecl && name == fStandaloneSymbol) {
                          if (!sawSpace) {
                              throw new JspCoreException("jsp.error.xml.spaceRequiredBeforeStandalone");
                              //err.jspError("jsp.error.xml.spaceRequiredBeforeStandalone");
                          }
                          standalone = fString.toString();
                          state = STATE_DONE;
                          if (!standalone.equals("yes") && !standalone.equals("no")) {
                              throw new JspCoreException("jsp.error.xml.sdDeclInvalid");
                              //err.jspError("jsp.error.xml.sdDeclInvalid");
                          }
                      } else {
                          throw new JspCoreException("jsp.error.xml.encodingDeclRequired");
                          //err.jspError("jsp.error.xml.encodingDeclRequired");
                      }
                      break;
                  }
                  case STATE_STANDALONE: {
                      if (name == fStandaloneSymbol) {
                          if (!sawSpace) {
                              throw new JspCoreException("jsp.error.xml.spaceRequiredBeforeStandalone");
                              //err.jspError("jsp.error.xml.spaceRequiredBeforeStandalone");
                          }
                          standalone = fString.toString();
                          state = STATE_DONE;
                          if (!standalone.equals("yes") && !standalone.equals("no")) {
                              throw new JspCoreException("jsp.error.xml.sdDeclInvalid");
                              //err.jspError("jsp.error.xml.sdDeclInvalid");
                          }
                      } else {
                          throw new JspCoreException("jsp.error.xml.encodingDeclRequired");
                      	//err.jspError("jsp.error.xml.encodingDeclRequired");
                      }
                      break;
                  }
                  default: {
                      throw new JspCoreException("jsp.error.xml.noMorePseudoAttributes");
                      //err.jspError("jsp.error.xml.noMorePseudoAttributes");
                  }
              }
              sawSpace = skipSpaces();
          }
          // REVISIT: should we remove this error reporting?
          if (scanningTextDecl && state != STATE_DONE) {
              throw new JspCoreException("jsp.error.xml.morePseudoAttributes");
              //err.jspError("jsp.error.xml.morePseudoAttributes");
          }
          
          // If there is no data in the xml or text decl then we fail to report
  	// error for version or encoding info above.
          if (scanningTextDecl) {
              if (!dataFoundForTarget && encoding == null) {
                  throw new JspCoreException("jsp.error.xml.encodingDeclRequired");
                  //err.jspError("jsp.error.xml.encodingDeclRequired");
              }
          } else {
              if (!dataFoundForTarget && version == null) {
                  throw new JspCoreException("jsp.error.xml.versionInfoRequired");
                  //err.jspError("jsp.error.xml.versionInfoRequired");
              }
          }
  
          // end
          if (!skipChar('?')) {
              throw new JspCoreException("jsp.error.xml.xmlDeclUnterminated");
              //err.jspError("jsp.error.xml.xmlDeclUnterminated");
          }
          if (!skipChar('>')) {
              throw new JspCoreException("jsp.error.xml.xmlDeclUnterminated");
              //err.jspError("jsp.error.xml.xmlDeclUnterminated");
  
          }
          
          // fill in return array
          pseudoAttributeValues[0] = version;
          pseudoAttributeValues[1] = encoding;
          pseudoAttributeValues[2] = standalone;
      }