void formatMsgCore( int formatPass, HBuffer fmtBuf)
throws HdfException
{
  byte[] nameBytes = HdfUtil.encodeString( attrName, false, hdfGroup);
  fmtBuf.putBufByte("MsgAttribute: attrVersion", 3);

  // Flag bits:
  //   0  datatype is shared
  //   1  dataspace is shared
  fmtBuf.putBufByte("MsgAttribute: flag", 0);

  // Name must have null termination
  fmtBuf.putBufShort(
    "MsgAttribute: nameSize", nameBytes.length + 1);   // +1 for null term
  fmtBuf.putBufShort(
    "MsgAttribute: dataTypeSize", msgDataType.hdrMsgSize);
  fmtBuf.putBufShort(
    "MsgAttribute: dataSpaceSize", msgDataSpace.hdrMsgSize);
  fmtBuf.putBufByte("MsgAttribute: encoding", 0);

  fmtBuf.putBufBytes("MsgAttribute: attr name", nameBytes);
  fmtBuf.putBufByte("MsgAttribute: attr name null term", 0);

  msgDataType.formatNakedMsg( formatPass, fmtBuf);

  msgDataSpace.formatNakedMsg( formatPass, fmtBuf);

  int[] startIxs = new int[ dataVarDims.length];

  if (attrValue == null) {
    // Don't write null attrValue
  }
  else if (isVlen) {
    // Vlen: format the globalHeap references to hdfFile.mainGlobalHeap.
    // Get back heap ref indices, one per VLEN row.
    int[] heapIxs = hdfFile.mainGlobalHeap.putHeapVlenObject(
      hdfGroup,
      msgDataType.dtype,
      msgDataType.subMsgs[0].dtype,
      msgDataType.subMsgs[0].elementLen,    // stgLen, without null term
      dataVarDims,
      attrValue);
    if (hdfFile.bugs >= 2) {
      String tmsg = "MsgAttribute vlen: attrName: \"" + attrName + "\"\n"
        + "  heapIxs len: " + heapIxs.length + "\n"
        + "  heapIxs:";
      for (int ii = 0; ii < heapIxs.length; ii++) {
        tmsg += " " + heapIxs[ii];
      }
      prtf( tmsg);
    }

    hdfGroup.formatVlenRawData( heapIxs, attrValue, fmtBuf);
  }

  else if (msgDataType.dtype == HdfGroup.DTYPE_STRING_VAR) {
    // Vlen: format the globalHeap references to hdfFile.bbuf
    int compressionLevel = 0;      // cannot compress heap objects
    HBuffer refBuf = new HBuffer( null, compressionLevel, hdfFile);
    int[] curIxs = new int[dataVarDims.length];
    if (hdfFile.bugs >= 2)
      prtf("MsgAttribute: call formatRawData for string data");
    hdfGroup.formatRawData(
      "attrName: " + attrName,
      0,                   // curLev
      curIxs,
      false,               // useLinear
      attrType,
      stgFieldLen,
      dataVarDims,         // varDims
      dataVarDims,         // chnLens
      dataVarDims,         // dataDims
      elementLen,
      startIxs,
      attrValue,
      new HdfModInt(0),
      hdfFile.mainGlobalHeap.blkPosition,  // gcolAddr for DTYPE_STRING_VAR
      hdfFile.mainGlobalHeap,              // gcol for DTYPE_STRING_VAR
      refBuf);
    fmtBuf.putBufBuf("STRING_VAR refs", refBuf);    // write out references
  } // if DTYPE_STRING_VAR

  else {
    // Raw data: format the raw data to fmtBuf
    int[] curIxs = new int[dataVarDims.length];
    if (hdfFile.bugs >= 2)
      prtf("MsgAttribute: call formatRawData for numeric data");
    hdfGroup.formatRawData(
      "attrName: " + attrName,
      0,                   // curLev
      curIxs,
      false,               // useLinear
      attrType,
      stgFieldLen,
      dataVarDims,         // varDims
      dataVarDims,         // chnLens
      dataVarDims,         // dataDims
      elementLen,
      startIxs,
      attrValue,
      new HdfModInt(0),
      0,                   // gcolAddr for DTYPE_STRING_VAR
      null,                // gcol for DTYPE_STRING_VAR
      fmtBuf);

    // Kluge: When an attribute is null or length == 0,
    // the HDF5 C library still writes out a single scalar value: 0.
    // And the reader reads it.
    if (totNumEle == 0)
      fmtBuf.putBufLong( "MsgAttribute: empty attr kluge", 0);
  }

} // end formatMsgCore