docs: private void parseEntityRef(boolean externalAllowed) throws SAXException,
              IOException {
          String name;
  
          name = readNmtoken(true);
          require(';');
          switch (getEntityType(name)) {
              case ENTITY_UNDECLARED:
                  // NOTE: XML REC describes amazingly convoluted handling for
                  // this case. Nothing as meaningful as being a WFness error
                  // unless the processor might _legitimately_ not have seen a
                  // declaration ... which is what this implements.
                  String message;
  
                  message = "reference to undeclared general entity " + name;
                  if (skippedPE && !docIsStandalone) {
                      handler.verror(message);
                      // we don't know this entity, and it might be external...
                      if (externalAllowed) {
                          handler.skippedEntity(name);
                      }
                  } else {
                      fatal(message);
                  }
                  break;
              case ENTITY_INTERNAL:
                  pushString(name, getEntityValue(name));
  
                  // workaround for possible input pop before marking
                  // the buffer reading position
                  char t = readCh();
                  unread(t);
                  int bufferPosMark = readBufferPos;
  
                  int end = readBufferPos + getEntityValue(name).length();
                  for (int k = readBufferPos; k < end; k++) {
                      t = readCh();
                      if (t == '&') {
                          t = readCh();
                          if (t == '#') {
                              // try to match a character ref
                              tryReadCharRef();
  
                              // everything has been read
                              if (readBufferPos >= end) {
                                  break;
                              }
                              k = readBufferPos;
                              continue;
                          } else if (Character.isLetter(t)) {
                              // looks like an entity ref
                              unread(t);
                              readNmtoken(true);
                              require(';');
  
                              // everything has been read
                              if (readBufferPos >= end) {
                                  break;
                              }
                              k = readBufferPos;
                              continue;
                          }
                          fatal(" malformed entity reference");
                      }
  
                  }
                  readBufferPos = bufferPosMark;
                  break;
              case ENTITY_TEXT:
                  if (externalAllowed) {
                      pushURL(false, name, getEntityIds(name), null, null, null,
                              true);
                  } else {
                      fatal("reference to external entity in attribute value.",
                              name, null);
                  }
                  break;
              case ENTITY_NDATA:
                  if (externalAllowed) {
                      fatal("unparsed entity reference in content", name, null);
                  } else {
                      fatal("reference to external entity in attribute value.",
                              name, null);
                  }
                  break;
              default:
                  throw new RuntimeException();
          }
      }