text:
#include "dexdump.h"

#include <inttypes.h>
#include <stdio.h>

#include <iostream>
#include <memory>
#include <sstream>
#include <vector>

#include "dex_file-inl.h"
#include "dex_instruction-inl.h"
#include "utils.h"

namespace art {

/*
 * Options parsed in main driver.
 */
struct Options gOptions;

/*
 * Output file. Defaults to stdout.
 */
FILE* gOutFile = stdout;

/*
 * Data types that match the definitions in the VM specification.
 */
typedef uint8_t  u1;
typedef uint16_t u2;
typedef uint32_t u4;
typedef uint64_t u8;
typedef int32_t  s4;
typedef int64_t  s8;

/*
 * Basic information about a field or a method.
 */
struct FieldMethodInfo {
  const char* classDescriptor;
  const char* name;
  const char* signature;
};

/*
 * Flags for use with createAccessFlagStr().
 */
enum AccessFor {
  kAccessForClass = 0, kAccessForMethod = 1, kAccessForField = 2, kAccessForMAX
};
const int kNumFlags = 18;

/*
 * Gets 2 little-endian bytes.
 */
static inline u2 get2LE(unsigned char const* pSrc) {
  return pSrc[0] | (pSrc[1] << 8);
}

/*
 * Converts a single-character primitive type into human-readable form.
 */
static const char* primitiveTypeLabel(char typeChar) {
  switch (typeChar) {
    case 'B': return "byte";
    case 'C': return "char";
    case 'D': return "double";
    case 'F': return "float";
    case 'I': return "int";
    case 'J': return "long";
    case 'S': return "short";
    case 'V': return "void";
    case 'Z': return "boolean";
    default:  return "UNKNOWN";
  }  // switch
}

/*
 * Converts a type descriptor to human-readable "dotted" form.  For
 * example, "Ljava/lang/String;" becomes "java.lang.String", and
 * "[I" becomes "int[]".  Also converts '$' to '.', which means this
 * form can't be converted back to a descriptor.
 */
static char* descriptorToDot(const char* str) {
  int targetLen = strlen(str);
  int offset = 0;

  // Strip leading [s; will be added to end.
  while (targetLen > 1 && str[offset] == '[') {
    offset++;
    targetLen--;
  }  // while

  const int arrayDepth = offset;

  if (targetLen == 1) {
    // Primitive type.
    str = primitiveTypeLabel(str[offset]);
    offset = 0;
    targetLen = strlen(str);
  } else {
    // Account for leading 'L' and trailing ';'.
    if (targetLen >= 2 && str[offset] == 'L' &&
        str[offset + targetLen - 1] == ';') {
      targetLen -= 2;
      offset++;
    }
  }

  // Copy class name over.
  char* newStr = reinterpret_cast<char*>(
      malloc(targetLen + arrayDepth * 2 + 1));
  int i = 0;
  for (; i < targetLen; i++) {
    const char ch = str[offset + i];
    newStr[i] = (ch == '/' || ch == '$') ? '.' : ch;
  }  // for

  // Add the appropriate number of brackets for arrays.
  for (int j = 0; j < arrayDepth; j++) {
    newStr[i++] = '[';
    newStr[i++] = ']';
  }  // for

  newStr[i] = '\0';
  return newStr;
}

/*
 * Converts the class name portion of a type descriptor to human-readable
 * "dotted" form.
 *
 * Returns a newly-allocated string.
 */
static char* descriptorClassToDot(const char* str) {
  // Reduce to just the class name, trimming trailing ';'.
  const char* lastSlash = strrchr(str, '/');
  if (lastSlash == nullptr) {
    lastSlash = str + 1;  // start past 'L'
  } else {
    lastSlash++;          // start past '/'
  }

  char* newStr = strdup(lastSlash);
  newStr[strlen(lastSlash) - 1] = '\0';
  for (char* cp = newStr; *cp != '\0'; cp++) {
    if (*cp == '$') {
      *cp = '.';
    }
  }  // for
  return newStr;
}

/*
 * Returns a quoted string representing the boolean value.
 */
static const char* quotedBool(bool val) {
  return val ? "\"true\"" : "\"false\"";
}

/*
 * Returns a quoted string representing the access flags.
 */
static const char* quotedVisibility(u4 accessFlags) {
  if (accessFlags & kAccPublic) {
    return "\"public\"";
  } else if (accessFlags & kAccProtected) {
    return "\"protected\"";
  } else if (accessFlags & kAccPrivate) {
    return "\"private\"";
  } else {
    return "\"package\"";
  }
}

/*
 * Counts the number of '1' bits in a word.
 */
static int countOnes(u4 val) {
  val = val - ((val >> 1) & 0x55555555);
  val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
  return (((val + (val >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}

/*
 * Creates a new string with human-readable access flags.
 *
 * In the base language the access_flags fields are type u2; in Dalvik
 * they're u4.
 */
static char* createAccessFlagStr(u4 flags, AccessFor forWhat) {
  static const char* kAccessStrings[kAccessForMAX][kNumFlags] = {
    {
      "PUBLIC",                /* 0x00001 */
      "PRIVATE",               /* 0x00002 */
      "PROTECTED",             /* 0x00004 */
      "STATIC",                /* 0x00008 */
      "FINAL",                 /* 0x00010 */
      "?",                     /* 0x00020 */
      "?",                     /* 0x00040 */
      "?",                     /* 0x00080 */
      "?",                     /* 0x00100 */
      "INTERFACE",             /* 0x00200 */
      "ABSTRACT",              /* 0x00400 */
      "?",                     /* 0x00800 */
      "SYNTHETIC",             /* 0x01000 */
      "ANNOTATION",            /* 0x02000 */
      "ENUM",                  /* 0x04000 */
      "?",                     /* 0x08000 */
      "VERIFIED",              /* 0x10000 */
      "OPTIMIZED",             /* 0x20000 */
    }, {
      "PUBLIC",                /* 0x00001 */
      "PRIVATE",               /* 0x00002 */
      "PROTECTED",             /* 0x00004 */
      "STATIC",                /* 0x00008 */
      "FINAL",                 /* 0x00010 */
      "SYNCHRONIZED",          /* 0x00020 */
      "BRIDGE",                /* 0x00040 */
      "VARARGS",               /* 0x00080 */
      "NATIVE",                /* 0x00100 */
      "?",                     /* 0x00200 */
      "ABSTRACT",              /* 0x00400 */
      "STRICT",                /* 0x00800 */
      "SYNTHETIC",             /* 0x01000 */
      "?",                     /* 0x02000 */
      "?",                     /* 0x04000 */
      "MIRANDA",               /* 0x08000 */
      "CONSTRUCTOR",           /* 0x10000 */
      "DECLARED_SYNCHRONIZED", /* 0x20000 */
    }, {
      "PUBLIC",                /* 0x00001 */
      "PRIVATE",               /* 0x00002 */
      "PROTECTED",             /* 0x00004 */
      "STATIC",                /* 0x00008 */
      "FINAL",                 /* 0x00010 */
      "?",                     /* 0x00020 */
      "VOLATILE",              /* 0x00040 */
      "TRANSIENT",             /* 0x00080 */
      "?",                     /* 0x00100 */
      "?",                     /* 0x00200 */
      "?",                     /* 0x00400 */
      "?",                     /* 0x00800 */
      "SYNTHETIC",             /* 0x01000 */
      "?",                     /* 0x02000 */
      "ENUM",                  /* 0x04000 */
      "?",                     /* 0x08000 */
      "?",                     /* 0x10000 */
      "?",                     /* 0x20000 */
    },
  };

  // Allocate enough storage to hold the expected number of strings,
  // plus a space between each.  We over-allocate, using the longest
  // string above as the base metric.
  const int kLongest = 21;  // The strlen of longest string above.
  const int count = countOnes(flags);
  char* str;
  char* cp;
  cp = str = reinterpret_cast<char*>(malloc(count * (kLongest + 1) + 1));

  for (int i = 0; i < kNumFlags; i++) {
    if (flags & 0x01) {
      const char* accessStr = kAccessStrings[forWhat][i];
      const int len = strlen(accessStr);
      if (cp != str) {
        *cp++ = ' ';
      }
      memcpy(cp, accessStr, len);
      cp += len;
    }
    flags >>= 1;
  }  // for

  *cp = '\0';
  return str;
}

/*
 * Copies character data from "data" to "out", converting non-ASCII values
 * to fprintf format chars or an ASCII filler ('.' or '?').
 *
 * The output buffer must be able to hold (2*len)+1 bytes.  The result is
 * NULL-terminated.
 */
static void asciify(char* out, const unsigned char* data, size_t len) {
  while (len--) {
    if (*data < 0x20) {
      // Could do more here, but we don't need them yet.
      switch (*data) {
        case '\0':
          *out++ = '\\';
          *out++ = '0';
          break;
        case '\n':
          *out++ = '\\';
          *out++ = 'n';
          break;
        default:
          *out++ = '.';
          break;
      }  // switch
    } else if (*data >= 0x80) {
      *out++ = '?';
    } else {
      *out++ = *data;
    }
    data++;
  }  // while
  *out = '\0';
}

/*
 * Dumps the file header.
 *
 * Note that some of the : are misaligned on purpose to preserve
 * the exact output of the original Dalvik dexdump.
 */
static void dumpFileHeader(const DexFile* pDexFile) {
  const DexFile::Header& pHeader = pDexFile->GetHeader();
  char sanitized[sizeof(pHeader.magic_) * 2 + 1];
  fprintf(gOutFile, "DEX file header:\n");
  asciify(sanitized, pHeader.magic_, sizeof(pHeader.magic_));
  fprintf(gOutFile, "magic               : '%s'\n", sanitized);
  fprintf(gOutFile, "checksum            : %08x\n", pHeader.checksum_);
  fprintf(gOutFile, "signature           : %02x%02x...%02x%02x\n",
          pHeader.signature_[0], pHeader.signature_[1],
          pHeader.signature_[DexFile::kSha1DigestSize - 2],
          pHeader.signature_[DexFile::kSha1DigestSize - 1]);
  fprintf(gOutFile, "file_size           : %d\n", pHeader.file_size_);
  fprintf(gOutFile, "header_size         : %d\n", pHeader.header_size_);
  fprintf(gOutFile, "link_size           : %d\n", pHeader.link_size_);
  fprintf(gOutFile, "link_off            : %d (0x%06x)\n",
          pHeader.link_off_, pHeader.link_off_);
  fprintf(gOutFile, "string_ids_size     : %d\n", pHeader.string_ids_size_);
  fprintf(gOutFile, "string_ids_off      : %d (0x%06x)\n",
          pHeader.string_ids_off_, pHeader.string_ids_off_);
  fprintf(gOutFile, "type_ids_size       : %d\n", pHeader.type_ids_size_);
  fprintf(gOutFile, "type_ids_off        : %d (0x%06x)\n",
          pHeader.type_ids_off_, pHeader.type_ids_off_);
  fprintf(gOutFile, "proto_ids_size       : %d\n", pHeader.proto_ids_size_);
  fprintf(gOutFile, "proto_ids_off        : %d (0x%06x)\n",
          pHeader.proto_ids_off_, pHeader.proto_ids_off_);
  fprintf(gOutFile, "field_ids_size      : %d\n", pHeader.field_ids_size_);
  fprintf(gOutFile, "field_ids_off       : %d (0x%06x)\n",
          pHeader.field_ids_off_, pHeader.field_ids_off_);
  fprintf(gOutFile, "method_ids_size     : %d\n", pHeader.method_ids_size_);
  fprintf(gOutFile, "method_ids_off      : %d (0x%06x)\n",
          pHeader.method_ids_off_, pHeader.method_ids_off_);
  fprintf(gOutFile, "class_defs_size     : %d\n", pHeader.class_defs_size_);
  fprintf(gOutFile, "class_defs_off      : %d (0x%06x)\n",
          pHeader.class_defs_off_, pHeader.class_defs_off_);
  fprintf(gOutFile, "data_size           : %d\n", pHeader.data_size_);
  fprintf(gOutFile, "data_off            : %d (0x%06x)\n\n",
          pHeader.data_off_, pHeader.data_off_);
}

/*
 * Dumps a class_def_item.
 */
static void dumpClassDef(const DexFile* pDexFile, int idx) {
  // General class information.
  const DexFile::ClassDef& pClassDef = pDexFile->GetClassDef(idx);
  fprintf(gOutFile, "Class #%d header:\n", idx);
  fprintf(gOutFile, "class_idx           : %d\n", pClassDef.class_idx_);
  fprintf(gOutFile, "access_flags        : %d (0x%04x)\n",
          pClassDef.access_flags_, pClassDef.access_flags_);
  fprintf(gOutFile, "superclass_idx      : %d\n", pClassDef.superclass_idx_);
  fprintf(gOutFile, "interfaces_off      : %d (0x%06x)\n",
          pClassDef.interfaces_off_, pClassDef.interfaces_off_);
  fprintf(gOutFile, "source_file_idx     : %d\n", pClassDef.source_file_idx_);
  fprintf(gOutFile, "annotations_off     : %d (0x%06x)\n",
          pClassDef.annotations_off_, pClassDef.annotations_off_);
  fprintf(gOutFile, "class_data_off      : %d (0x%06x)\n",
          pClassDef.class_data_off_, pClassDef.class_data_off_);

  // Fields and methods.
  const u1* pEncodedData = pDexFile->GetClassData(pClassDef);
  if (pEncodedData != nullptr) {
    ClassDataItemIterator pClassData(*pDexFile, pEncodedData);
    fprintf(gOutFile, "static_fields_size  : %d\n", pClassData.NumStaticFields());
    fprintf(gOutFile, "instance_fields_size: %d\n", pClassData.NumInstanceFields());
    fprintf(gOutFile, "direct_methods_size : %d\n", pClassData.NumDirectMethods());
    fprintf(gOutFile, "virtual_methods_size: %d\n", pClassData.NumVirtualMethods());
  } else {
    fprintf(gOutFile, "static_fields_size  : 0\n");
    fprintf(gOutFile, "instance_fields_size: 0\n");
    fprintf(gOutFile, "direct_methods_size : 0\n");
    fprintf(gOutFile, "virtual_methods_size: 0\n");
  }
  fprintf(gOutFile, "\n");
}

/*
 * Dumps an interface that a class declares to implement.
 */
static void dumpInterface(const DexFile* pDexFile, const DexFile::TypeItem& pTypeItem, int i) {
  const char* interfaceName = pDexFile->StringByTypeIdx(pTypeItem.type_idx_);
  if (gOptions.outputFormat == OUTPUT_PLAIN) {
    fprintf(gOutFile, "    #%d              : '%s'\n", i, interfaceName);
  } else {
    char* dotted = descriptorToDot(interfaceName);
    fprintf(gOutFile, "<implements name=\"%s\">\n</implements>\n", dotted);
    free(dotted);
  }
}

/*
 * Dumps the catches table associated with the code.
 */
static void dumpCatches(const DexFile* pDexFile, const DexFile::CodeItem* pCode) {
  const u4 triesSize = pCode->tries_size_;

  // No catch table.
  if (triesSize == 0) {
    fprintf(gOutFile, "      catches       : (none)\n");
    return;
  }

  // Dump all table entries.
  fprintf(gOutFile, "      catches       : %d\n", triesSize);
  for (u4 i = 0; i < triesSize; i++) {
    const DexFile::TryItem* pTry = pDexFile->GetTryItems(*pCode, i);
    const u4 start = pTry->start_addr_;
    const u4 end = start + pTry->insn_count_;
    fprintf(gOutFile, "        0x%04x - 0x%04x\n", start, end);
    for (CatchHandlerIterator it(*pCode, *pTry); it.HasNext(); it.Next()) {
      const u2 tidx = it.GetHandlerTypeIndex();
      const char* descriptor =
          (tidx == DexFile::kDexNoIndex16) ? "<any>" : pDexFile->StringByTypeIdx(tidx);
      fprintf(gOutFile, "          %s -> 0x%04x\n", descriptor, it.GetHandlerAddress());
    }  // for
  }  // for
}

/*
 * Callback for dumping each positions table entry.
 */
static bool dumpPositionsCb(void* /*context*/, const DexFile::PositionInfo& entry) {
  fprintf(gOutFile, "        0x%04x line=%d\n", entry.address_, entry.line_);
  return false;
}

/*
 * Callback for dumping locals table entry.
 */
static void dumpLocalsCb(void* /*context*/, const DexFile::LocalInfo& entry) {
  const char* signature = entry.signature_ != nullptr ? entry.signature_ : "";
  fprintf(gOutFile, "        0x%04x - 0x%04x reg=%d %s %s %s\n",
          entry.start_address_, entry.end_address_, entry.reg_,
          entry.name_, entry.descriptor_, signature);
}

/*
 * Helper for dumpInstruction(), which builds the string
 * representation for the index in the given instruction. This will
 * first try to use the given buffer, but if the result won't fit,
 * then this will allocate a new buffer to hold the result. A pointer
 * to the buffer which holds the full result is always returned, and
 * this can be compared with the one passed in, to see if the result
 * needs to be free()d.
 */
static char* indexString(const DexFile* pDexFile,
                         const Instruction* pDecInsn, char* buf, size_t bufSize) {
  // Determine index and width of the string.
  u4 index = 0;
  u4 width = 4;
  switch (Instruction::FormatOf(pDecInsn->Opcode())) {
    // SOME NOT SUPPORTED:
    // case Instruction::k20bc:
    case Instruction::k21c:
    case Instruction::k35c:
    // case Instruction::k35ms:
    case Instruction::k3rc:
    // case Instruction::k3rms:
    // case Instruction::k35mi:
    // case Instruction::k3rmi:
      index = pDecInsn->VRegB();
      width = 4;
      break;
    case Instruction::k31c:
      index = pDecInsn->VRegB();
      width = 8;
      break;
    case Instruction::k22c:
    // case Instruction::k22cs:
      index = pDecInsn->VRegC();
      width = 4;
      break;
    default:
      break;
  }  // switch

  // Determine index type.
  size_t outSize = 0;
  switch (Instruction::IndexTypeOf(pDecInsn->Opcode())) {
    case Instruction::kIndexUnknown:
      // This function should never get called for this type, but do
      // something sensible here, just to help with debugging.
      outSize = snprintf(buf, bufSize, "<unknown-index>");
      break;
    case Instruction::kIndexNone:
      // This function should never get called for this type, but do
      // something sensible here, just to help with debugging.
      outSize = snprintf(buf, bufSize, "<no-index>");
      break;
    case Instruction::kIndexTypeRef:
      if (index < pDexFile->GetHeader().type_ids_size_) {
        const char* tp = pDexFile->StringByTypeIdx(index);
        outSize = snprintf(buf, bufSize, "%s // type@%0*x", tp, width, index);
      } else {
        outSize = snprintf(buf, bufSize, "<type?> // type@%0*x", width, index);
      }
      break;
    case Instruction::kIndexStringRef:
      if (index < pDexFile->GetHeader().string_ids_size_) {
        const char* st = pDexFile->StringDataByIdx(index);
        outSize = snprintf(buf, bufSize, "\"%s\" // string@%0*x", st, width, index);
      } else {
        outSize = snprintf(buf, bufSize, "<string?> // string@%0*x", width, index);
      }
      break;
    case Instruction::kIndexMethodRef:
      if (index < pDexFile->GetHeader().method_ids_size_) {
        const DexFile::MethodId& pMethodId = pDexFile->GetMethodId(index);
        const char* name = pDexFile->StringDataByIdx(pMethodId.name_idx_);
        const Signature signature = pDexFile->GetMethodSignature(pMethodId);
        const char* backDescriptor = pDexFile->StringByTypeIdx(pMethodId.class_idx_);
        outSize = snprintf(buf, bufSize, "%s.%s:%s // method@%0*x",
                           backDescriptor, name, signature.ToString().c_str(), width, index);
      } else {
        outSize = snprintf(buf, bufSize, "<method?> // method@%0*x", width, index);
      }
      break;
    case Instruction::kIndexFieldRef:
      if (index < pDexFile->GetHeader().field_ids_size_) {
        const DexFile::FieldId& pFieldId = pDexFile->GetFieldId(index);
        const char* name = pDexFile->StringDataByIdx(pFieldId.name_idx_);
        const char* typeDescriptor = pDexFile->StringByTypeIdx(pFieldId.type_idx_);
        const char* backDescriptor = pDexFile->StringByTypeIdx(pFieldId.class_idx_);
        outSize = snprintf(buf, bufSize, "%s.%s:%s // field@%0*x",
                           backDescriptor, name, typeDescriptor, width, index);
      } else {
        outSize = snprintf(buf, bufSize, "<field?> // field@%0*x", width, index);
      }
      break;
    case Instruction::kIndexVtableOffset:
      outSize = snprintf(buf, bufSize, "[%0*x] // vtable #%0*x",
                         width, index, width, index);
      break;
    case Instruction::kIndexFieldOffset:
      outSize = snprintf(buf, bufSize, "[obj+%0*x]", width, index);
      break;
    // SOME NOT SUPPORTED:
    // case Instruction::kIndexVaries:
    // case Instruction::kIndexInlineMethod:
    default:
      outSize = snprintf(buf, bufSize, "<?>");
      break;
  }  // switch

  // Determine success of string construction.
  if (outSize >= bufSize) {
    // The buffer wasn't big enough; allocate and retry. Note:
    // snprintf() doesn't count the '\0' as part of its returned
    // size, so we add explicit space for it here.
    outSize++;
    buf = reinterpret_cast<char*>(malloc(outSize));
    if (buf == nullptr) {
      return nullptr;
    }
    return indexString(pDexFile, pDecInsn, buf, outSize);
  }
  return buf;
}

/*
 * Dumps a single instruction.
 */
static void dumpInstruction(const DexFile* pDexFile,
                            const DexFile::CodeItem* pCode,
                            u4 codeOffset, u4 insnIdx, u4 insnWidth,
                            const Instruction* pDecInsn) {
  // Address of instruction (expressed as byte offset).
  fprintf(gOutFile, "%06x:", codeOffset + 0x10 + insnIdx * 2);

  // Dump (part of) raw bytes.
  const u2* insns = pCode->insns_;
  for (u4 i = 0; i < 8; i++) {
    if (i < insnWidth) {
      if (i == 7) {
        fprintf(gOutFile, " ... ");
      } else {
        // Print 16-bit value in little-endian order.
        const u1* bytePtr = (const u1*) &insns[insnIdx + i];
        fprintf(gOutFile, " %02x%02x", bytePtr[0], bytePtr[1]);
      }
    } else {
      fputs("     ", gOutFile);
    }
  }  // for

  // Dump pseudo-instruction or opcode.
  if (pDecInsn->Opcode() == Instruction::NOP) {
    const u2 instr = get2LE((const u1*) &insns[insnIdx]);
    if (instr == Instruction::kPackedSwitchSignature) {
      fprintf(gOutFile, "|%04x: packed-switch-data (%d units)", insnIdx, insnWidth);
    } else if (instr == Instruction::kSparseSwitchSignature) {
      fprintf(gOutFile, "|%04x: sparse-switch-data (%d units)", insnIdx, insnWidth);
    } else if (instr == Instruction::kArrayDataSignature) {
      fprintf(gOutFile, "|%04x: array-data (%d units)", insnIdx, insnWidth);
    } else {
      fprintf(gOutFile, "|%04x: nop // spacer", insnIdx);
    }
  } else {
    fprintf(gOutFile, "|%04x: %s", insnIdx, pDecInsn->Name());
  }

  // Set up additional argument.
  char indexBufChars[200];
  char *indexBuf = indexBufChars;
  if (Instruction::IndexTypeOf(pDecInsn->Opcode()) != Instruction::kIndexNone) {
    indexBuf = indexString(pDexFile, pDecInsn,
                           indexBufChars, sizeof(indexBufChars));
  }

  // Dump the instruction.
  //
  // NOTE: pDecInsn->DumpString(pDexFile) differs too much from original.
  //
  switch (Instruction::FormatOf(pDecInsn->Opcode())) {
    case Instruction::k10x:        // op
      break;
    case Instruction::k12x:        // op vA, vB
      fprintf(gOutFile, " v%d, v%d", pDecInsn->VRegA(), pDecInsn->VRegB());
      break;
    case Instruction::k11n:        // op vA, #+B
      fprintf(gOutFile, " v%d, #int %d // #%x",
              pDecInsn->VRegA(), (s4) pDecInsn->VRegB(), (u1)pDecInsn->VRegB());
      break;
    case Instruction::k11x:        // op vAA
      fprintf(gOutFile, " v%d", pDecInsn->VRegA());
      break;
    case Instruction::k10t:        // op +AA
    case Instruction::k20t:        // op +AAAA
      {
        const s4 targ = (s4) pDecInsn->VRegA();
        fprintf(gOutFile, " %04x // %c%04x",
                insnIdx + targ,
                (targ < 0) ? '-' : '+',
                (targ < 0) ? -targ : targ);
      }
      break;
    case Instruction::k22x:        // op vAA, vBBBB
      fprintf(gOutFile, " v%d, v%d", pDecInsn->VRegA(), pDecInsn->VRegB());
      break;
    case Instruction::k21t:        // op vAA, +BBBB
      {
        const s4 targ = (s4) pDecInsn->VRegB();
        fprintf(gOutFile, " v%d, %04x // %c%04x", pDecInsn->VRegA(),
                insnIdx + targ,
                (targ < 0) ? '-' : '+',
                (targ < 0) ? -targ : targ);
      }
      break;
    case Instruction::k21s:        // op vAA, #+BBBB
      fprintf(gOutFile, " v%d, #int %d // #%x",
              pDecInsn->VRegA(), (s4) pDecInsn->VRegB(), (u2)pDecInsn->VRegB());
      break;
    case Instruction::k21h:        // op vAA, #+BBBB0000[00000000]
      // The printed format varies a bit based on the actual opcode.
      if (pDecInsn->Opcode() == Instruction::CONST_HIGH16) {
        const s4 value = pDecInsn->VRegB() << 16;
        fprintf(gOutFile, " v%d, #int %d // #%x",
                pDecInsn->VRegA(), value, (u2) pDecInsn->VRegB());
      } else {
        const s8 value = ((s8) pDecInsn->VRegB()) << 48;
        fprintf(gOutFile, " v%d, #long %" PRId64 " // #%x",
                pDecInsn->VRegA(), value, (u2) pDecInsn->VRegB());
      }
      break;
    case Instruction::k21c:        // op vAA, thing@BBBB
    case Instruction::k31c:        // op vAA, thing@BBBBBBBB
      fprintf(gOutFile, " v%d, %s", pDecInsn->VRegA(), indexBuf);
      break;
    case Instruction::k23x:        // op vAA, vBB, vCC
      fprintf(gOutFile, " v%d, v%d, v%d",
              pDecInsn->VRegA(), pDecInsn->VRegB(), pDecInsn->VRegC());
      break;
    case Instruction::k22b:        // op vAA, vBB, #+CC
      fprintf(gOutFile, " v%d, v%d, #int %d // #%02x",
              pDecInsn->VRegA(), pDecInsn->VRegB(),
              (s4) pDecInsn->VRegC(), (u1) pDecInsn->VRegC());
      break;
    case Instruction::k22t:        // op vA, vB, +CCCC
      {
        const s4 targ = (s4) pDecInsn->VRegC();
        fprintf(gOutFile, " v%d, v%d, %04x // %c%04x",
                pDecInsn->VRegA(), pDecInsn->VRegB(),
                insnIdx + targ,
                (targ < 0) ? '-' : '+',
                (targ < 0) ? -targ : targ);
      }
      break;
    case Instruction::k22s:        // op vA, vB, #+CCCC
      fprintf(gOutFile, " v%d, v%d, #int %d // #%04x",
              pDecInsn->VRegA(), pDecInsn->VRegB(),
              (s4) pDecInsn->VRegC(), (u2) pDecInsn->VRegC());
      break;
    case Instruction::k22c:        // op vA, vB, thing@CCCC
    // NOT SUPPORTED:
    // case Instruction::k22cs:    // [opt] op vA, vB, field offset CCCC
      fprintf(gOutFile, " v%d, v%d, %s",
              pDecInsn->VRegA(), pDecInsn->VRegB(), indexBuf);
      break;
    case Instruction::k30t:
      fprintf(gOutFile, " #%08x", pDecInsn->VRegA());
      break;
    case Instruction::k31i:        // op vAA, #+BBBBBBBB
      {
        // This is often, but not always, a float.
        union {
          float f;
          u4 i;
        } conv;
        conv.i = pDecInsn->VRegB();
        fprintf(gOutFile, " v%d, #float %f // #%08x",
                pDecInsn->VRegA(), conv.f, pDecInsn->VRegB());
      }
      break;
    case Instruction::k31t:       // op vAA, offset +BBBBBBBB
      fprintf(gOutFile, " v%d, %08x // +%08x",
              pDecInsn->VRegA(), insnIdx + pDecInsn->VRegB(), pDecInsn->VRegB());
      break;
    case Instruction::k32x:        // op vAAAA, vBBBB
      fprintf(gOutFile, " v%d, v%d", pDecInsn->VRegA(), pDecInsn->VRegB());
      break;
    case Instruction::k35c:        // op {vC, vD, vE, vF, vG}, thing@BBBB
    // NOT SUPPORTED:
    // case Instruction::k35ms:       // [opt] invoke-virtual+super
    // case Instruction::k35mi:       // [opt] inline invoke
      {
        u4 arg[Instruction::kMaxVarArgRegs];
        pDecInsn->GetVarArgs(arg);
        fputs(" {", gOutFile);
        for (int i = 0, n = pDecInsn->VRegA(); i < n; i++) {
          if (i == 0) {
            fprintf(gOutFile, "v%d", arg[i]);
          } else {
            fprintf(gOutFile, ", v%d", arg[i]);
          }
        }  // for
        fprintf(gOutFile, "}, %s", indexBuf);
      }
      break;
    case Instruction::k25x:        // op vC, {vD, vE, vF, vG} (B: count)
      {
        u4 arg[Instruction::kMaxVarArgRegs25x];
        pDecInsn->GetAllArgs25x(arg);
        fprintf(gOutFile, " v%d, {", arg[0]);
        for (int i = 0, n = pDecInsn->VRegB(); i < n; i++) {
          if (i == 0) {
            fprintf(gOutFile, "v%d", arg[Instruction::kLambdaVirtualRegisterWidth + i]);
          } else {
            fprintf(gOutFile, ", v%d", arg[Instruction::kLambdaVirtualRegisterWidth + i]);
          }
        }  // for
        fputc('}', gOutFile);
      }
      break;
    case Instruction::k3rc:        // op {vCCCC .. v(CCCC+AA-1)}, thing@BBBB
    // NOT SUPPORTED:
    // case Instruction::k3rms:       // [opt] invoke-virtual+super/range
    // case Instruction::k3rmi:       // [opt] execute-inline/range
      {
        // This doesn't match the "dx" output when some of the args are
        // 64-bit values -- dx only shows the first register.
        fputs(" {", gOutFile);
        for (int i = 0, n = pDecInsn->VRegA(); i < n; i++) {
          if (i == 0) {
            fprintf(gOutFile, "v%d", pDecInsn->VRegC() + i);
          } else {
            fprintf(gOutFile, ", v%d", pDecInsn->VRegC() + i);
          }
        }  // for
        fprintf(gOutFile, "}, %s", indexBuf);
      }
      break;
    case Instruction::k51l:        // op vAA, #+BBBBBBBBBBBBBBBB
      {
        // This is often, but not always, a double.
        union {
          double d;
          u8 j;
        } conv;
        conv.j = pDecInsn->WideVRegB();
        fprintf(gOutFile, " v%d, #double %f // #%016" PRIx64,
                pDecInsn->VRegA(), conv.d, pDecInsn->WideVRegB());
      }
      break;
    // NOT SUPPORTED:
    // case Instruction::k00x:        // unknown op or breakpoint
    //    break;
    default:
      fprintf(gOutFile, " ???");
      break;
  }  // switch

  fputc('\n', gOutFile);

  if (indexBuf != indexBufChars) {
    free(indexBuf);
  }
}

/*
 * Dumps a bytecode disassembly.
 */
static void dumpBytecodes(const DexFile* pDexFile, u4 idx,
                          const DexFile::CodeItem* pCode, u4 codeOffset) {
  const DexFile::MethodId& pMethodId = pDexFile->GetMethodId(idx);
  const char* name = pDexFile->StringDataByIdx(pMethodId.name_idx_);
  const Signature signature = pDexFile->GetMethodSignature(pMethodId);
  const char* backDescriptor = pDexFile->StringByTypeIdx(pMethodId.class_idx_);

  // Generate header.
  char* tmp = descriptorToDot(backDescriptor);
  fprintf(gOutFile, "%06x:                                        "
          "|[%06x] %s.%s:%s\n",
          codeOffset, codeOffset, tmp, name, signature.ToString().c_str());
  free(tmp);

  // Iterate over all instructions.
  const u2* insns = pCode->insns_;
  for (u4 insnIdx = 0; insnIdx < pCode->insns_size_in_code_units_;) {
    const Instruction* instruction = Instruction::At(&insns[insnIdx]);
    const u4 insnWidth = instruction->SizeInCodeUnits();
    if (insnWidth == 0) {
      fprintf(stderr, "GLITCH: zero-width instruction at idx=0x%04x\n", insnIdx);
      break;
    }
    dumpInstruction(pDexFile, pCode, codeOffset, insnIdx, insnWidth, instruction);
    insnIdx += insnWidth;
  }  // for
}

/*
 * Dumps code of a method.
 */
static void dumpCode(const DexFile* pDexFile, u4 idx, u4 flags,
                     const DexFile::CodeItem* pCode, u4 codeOffset) {
  fprintf(gOutFile, "      registers     : %d\n", pCode->registers_size_);
  fprintf(gOutFile, "      ins           : %d\n", pCode->ins_size_);
  fprintf(gOutFile, "      outs          : %d\n", pCode->outs_size_);
  fprintf(gOutFile, "      insns size    : %d 16-bit code units\n",
          pCode->insns_size_in_code_units_);

  // Bytecode disassembly, if requested.
  if (gOptions.disassemble) {
    dumpBytecodes(pDexFile, idx, pCode, codeOffset);
  }

  // Try-catch blocks.
  dumpCatches(pDexFile, pCode);

  // Positions and locals table in the debug info.
  bool is_static = (flags & kAccStatic) != 0;
  fprintf(gOutFile, "      positions     : \n");
  pDexFile->DecodeDebugPositionInfo(pCode, dumpPositionsCb, nullptr);
  fprintf(gOutFile, "      locals        : \n");
  pDexFile->DecodeDebugLocalInfo(pCode, is_static, idx, dumpLocalsCb, nullptr);
}

/*
 * Dumps a method.
 */
static void dumpMethod(const DexFile* pDexFile, u4 idx, u4 flags,
                       const DexFile::CodeItem* pCode, u4 codeOffset, int i) {
  // Bail for anything private if export only requested.
  if (gOptions.exportsOnly && (flags & (kAccPublic | kAccProtected)) == 0) {
    return;
  }

  const DexFile::MethodId& pMethodId = pDexFile->GetMethodId(idx);
  const char* name = pDexFile->StringDataByIdx(pMethodId.name_idx_);
  const Signature signature = pDexFile->GetMethodSignature(pMethodId);
  char* typeDescriptor = strdup(signature.ToString().c_str());
  const char* backDescriptor = pDexFile->StringByTypeIdx(pMethodId.class_idx_);
  char* accessStr = createAccessFlagStr(flags, kAccessForMethod);

  if (gOptions.outputFormat == OUTPUT_PLAIN) {
    fprintf(gOutFile, "    #%d              : (in %s)\n", i, backDescriptor);
    fprintf(gOutFile, "      name          : '%s'\n", name);
    fprintf(gOutFile, "      type          : '%s'\n", typeDescriptor);
    fprintf(gOutFile, "      access        : 0x%04x (%s)\n", flags, accessStr);
    if (pCode == nullptr) {
      fprintf(gOutFile, "      code          : (none)\n");
    } else {
      fprintf(gOutFile, "      code          -\n");
      dumpCode(pDexFile, idx, flags, pCode, codeOffset);
    }
    if (gOptions.disassemble) {
      fputc('\n', gOutFile);
    }
  } else if (gOptions.outputFormat == OUTPUT_XML) {
    const bool constructor = (name[0] == '<');

    // Method name and prototype.
    if (constructor) {
      char* tmp = descriptorClassToDot(backDescriptor);
      fprintf(gOutFile, "<constructor name=\"%s\"\n", tmp);
      free(tmp);
      tmp = descriptorToDot(backDescriptor);
      fprintf(gOutFile, " type=\"%s\"\n", tmp);
      free(tmp);
    } else {
      fprintf(gOutFile, "<method name=\"%s\"\n", name);
      const char* returnType = strrchr(typeDescriptor, ')');
      if (returnType == nullptr) {
        fprintf(stderr, "bad method type descriptor '%s'\n", typeDescriptor);
        goto bail;
      }
      char* tmp = descriptorToDot(returnType+1);
      fprintf(gOutFile, " return=\"%s\"\n", tmp);
      free(tmp);
      fprintf(gOutFile, " abstract=%s\n", quotedBool((flags & kAccAbstract) != 0));
      fprintf(gOutFile, " native=%s\n", quotedBool((flags & kAccNative) != 0));
      fprintf(gOutFile, " synchronized=%s\n", quotedBool(
          (flags & (kAccSynchronized | kAccDeclaredSynchronized)) != 0));
    }

    // Additional method flags.
    fprintf(gOutFile, " static=%s\n", quotedBool((flags & kAccStatic) != 0));
    fprintf(gOutFile, " final=%s\n", quotedBool((flags & kAccFinal) != 0));
    // The "deprecated=" not knowable w/o parsing annotations.
    fprintf(gOutFile, " visibility=%s\n>\n", quotedVisibility(flags));

    // Parameters.
    if (typeDescriptor[0] != '(') {
      fprintf(stderr, "ERROR: bad descriptor '%s'\n", typeDescriptor);
      goto bail;
    }
    char* tmpBuf = reinterpret_cast<char*>(malloc(strlen(typeDescriptor) + 1));
    const char* base = typeDescriptor + 1;
    int argNum = 0;
    while (*base != ')') {
      char* cp = tmpBuf;
      while (*base == '[') {
        *cp++ = *base++;
      }
      if (*base == 'L') {
        // Copy through ';'.
        do {
          *cp = *base++;
        } while (*cp++ != ';');
      } else {
        // Primitive char, copy it.
        if (strchr("ZBCSIFJD", *base) == NULL) {
          fprintf(stderr, "ERROR: bad method signature '%s'\n", base);
          goto bail;
        }
        *cp++ = *base++;
      }
      // Null terminate and display.
      *cp++ = '\0';
      char* tmp = descriptorToDot(tmpBuf);
      fprintf(gOutFile, "<parameter name=\"arg%d\" type=\"%s\">\n"
                        "</parameter>\n", argNum++, tmp);
      free(tmp);
    }  // while
    free(tmpBuf);
    if (constructor) {
      fprintf(gOutFile, "</constructor>\n");
    } else {
      fprintf(gOutFile, "</method>\n");
    }
  }

 bail:
  free(typeDescriptor);
  free(accessStr);
}

/*
 * Dumps a string value with some escape characters.
 */
static void dumpEscapedString(const char* p) {
  for (; *p; p++) {
    switch (*p) {
      case '\\':
        fputs("\\\\", gOutFile);
        break;
      case '\"':
        fputs("\\\"", gOutFile);
        break;
      case '\t':
        fputs("\\t", gOutFile);
        break;
      case '\n':
        fputs("\\n", gOutFile);
        break;
      case '\r':
        fputs("\\r", gOutFile);
        break;
      default:
        putc(*p, gOutFile);
    }
  }
}

/*
 * Dumps an XML attribute value between double-quotes.
 */
static void dumpXmlAttribute(const char* p) {
  for (; *p; p++) {
    switch (*p) {
      case '&':
        fputs("&", gOutFile);
        break;
      case '<':
        fputs("<", gOutFile);
        break;
      case '"':
        fputs(""", gOutFile);
        break;
      case '\t':
        fputs("	", gOutFile);
        break;
      case '\n':
        fputs("
", gOutFile);
        break;
      case '\r':
        fputs("
", gOutFile);
        break;
      default:
        putc(*p, gOutFile);
    }
  }
}

/*
 * Dumps a value of static (class) field.
 */
static void dumpSFieldValue(const DexFile* pDexFile,
                            EncodedStaticFieldValueIterator::ValueType valueType,
                            const jvalue* pValue) {
  switch (valueType) {
    case EncodedStaticFieldValueIterator::kByte:
      fprintf(gOutFile, "%" PRIu8, pValue->b);
      break;
    case EncodedStaticFieldValueIterator::kShort:
      fprintf(gOutFile, "%" PRId16, pValue->s);
      break;
    case EncodedStaticFieldValueIterator::kChar:
      fprintf(gOutFile, "%" PRIu16, pValue->c);
      break;
    case EncodedStaticFieldValueIterator::kInt:
      fprintf(gOutFile, "%" PRId32, pValue->i);
      break;
    case EncodedStaticFieldValueIterator::kLong:
      fprintf(gOutFile, "%" PRId64, pValue->j);
      break;
    case EncodedStaticFieldValueIterator::kFloat:
      fprintf(gOutFile, "%f", pValue->f);
      break;
    case EncodedStaticFieldValueIterator::kDouble:
      fprintf(gOutFile, "%f", pValue->d);
      break;
    case EncodedStaticFieldValueIterator::kString: {
      const char* str =
          pDexFile->GetStringData(pDexFile->GetStringId(pValue->i));
      if (gOptions.outputFormat == OUTPUT_PLAIN) {
        fputs("\"", gOutFile);
        dumpEscapedString(str);
        fputs("\"", gOutFile);
      } else {
        dumpXmlAttribute(str);
      }
      break;
    }
    case EncodedStaticFieldValueIterator::kNull:
      fputs("null", gOutFile);
      break;
    case EncodedStaticFieldValueIterator::kBoolean:
      fputs(pValue->z ? "true" : "false", gOutFile);
      break;

    case EncodedStaticFieldValueIterator::kAnnotation:
    case EncodedStaticFieldValueIterator::kArray:
    case EncodedStaticFieldValueIterator::kEnum:
    case EncodedStaticFieldValueIterator::kField:
    case EncodedStaticFieldValueIterator::kMethod:
    case EncodedStaticFieldValueIterator::kType:
    default:
      fprintf(gOutFile, "Unexpected static field type: %d", valueType);
  }
}

/*
 * Dumps a static (class) field.
 */
static void dumpSField(const DexFile* pDexFile, u4 idx, u4 flags, int i,
                       EncodedStaticFieldValueIterator::ValueType valueType,
                       const jvalue* pValue) {
  // Bail for anything private if export only requested.
  if (gOptions.exportsOnly && (flags & (kAccPublic | kAccProtected)) == 0) {
    return;
  }

  const DexFile::FieldId& pFieldId = pDexFile->GetFieldId(idx);
  const char* name = pDexFile->StringDataByIdx(pFieldId.name_idx_);
  const char* typeDescriptor = pDexFile->StringByTypeIdx(pFieldId.type_idx_);
  const char* backDescriptor = pDexFile->StringByTypeIdx(pFieldId.class_idx_);
  char* accessStr = createAccessFlagStr(flags, kAccessForField);

  if (gOptions.outputFormat == OUTPUT_PLAIN) {
    fprintf(gOutFile, "    #%d              : (in %s)\n", i, backDescriptor);
    fprintf(gOutFile, "      name          : '%s'\n", name);
    fprintf(gOutFile, "      type          : '%s'\n", typeDescriptor);
    fprintf(gOutFile, "      access        : 0x%04x (%s)\n", flags, accessStr);
    if (pValue != nullptr) {
      fputs("      value         : ", gOutFile);
      dumpSFieldValue(pDexFile, valueType, pValue);
      fputs("\n", gOutFile);
    }
  } else if (gOptions.outputFormat == OUTPUT_XML) {
    fprintf(gOutFile, "<field name=\"%s\"\n", name);
    char *tmp = descriptorToDot(typeDescriptor);
    fprintf(gOutFile, " type=\"%s\"\n", tmp);
    free(tmp);
    fprintf(gOutFile, " transient=%s\n", quotedBool((flags & kAccTransient) != 0));
    fprintf(gOutFile, " volatile=%s\n", quotedBool((flags & kAccVolatile) != 0));
    // The "value=" is not knowable w/o parsing annotations.
    fprintf(gOutFile, " static=%s\n", quotedBool((flags & kAccStatic) != 0));
    fprintf(gOutFile, " final=%s\n", quotedBool((flags & kAccFinal) != 0));
    // The "deprecated=" is not knowable w/o parsing annotations.
    fprintf(gOutFile, " visibility=%s\n", quotedVisibility(flags));
    if (pValue != nullptr) {
      fputs(" value=\"", gOutFile);
      dumpSFieldValue(pDexFile, valueType, pValue);
      fputs("\"\n", gOutFile);
    }
    fputs(">\n</field>\n", gOutFile);
  }

  free(accessStr);
}

/*
 * Dumps an instance field.
 */
static void dumpIField(const DexFile* pDexFile, u4 idx, u4 flags, int i) {
  dumpSField(pDexFile, idx, flags, i,
             EncodedStaticFieldValueIterator::kByte, nullptr);
}

/*
 * Dumping a CFG. Note that this will do duplicate work. utils.h doesn't expose the code-item
 * version, so the DumpMethodCFG code will have to iterate again to find it. But dexdump is a
 * tool, so this is not performance-critical.
 */

static void dumpCfg(const DexFile* dex_file,
                    uint32_t dex_method_idx,
                    const DexFile::CodeItem* code_item) {
  if (code_item != nullptr) {
    std::ostringstream oss;
    DumpMethodCFG(dex_file, dex_method_idx, oss);
    fprintf(gOutFile, "%s", oss.str().c_str());
  }
}

static void dumpCfg(const DexFile* dex_file, int idx) {
  const DexFile::ClassDef& class_def = dex_file->GetClassDef(idx);
  const uint8_t* class_data = dex_file->GetClassData(class_def);
  if (class_data == nullptr) {  // empty class such as a marker interface?
    return;
  }
  ClassDataItemIterator it(*dex_file, class_data);
  while (it.HasNextStaticField()) {
    it.Next();
  }
  while (it.HasNextInstanceField()) {
    it.Next();
  }
  while (it.HasNextDirectMethod()) {
    dumpCfg(dex_file,
            it.GetMemberIndex(),
            it.GetMethodCodeItem());
    it.Next();
  }
  while (it.HasNextVirtualMethod()) {
    dumpCfg(dex_file,
                it.GetMemberIndex(),
                it.GetMethodCodeItem());
    it.Next();
  }
}

/*
 * Dumps the class.
 *
 * Note "idx" is a DexClassDef index, not a DexTypeId index.
 *
 * If "*pLastPackage" is nullptr or does not match the current class' package,
 * the value will be replaced with a newly-allocated string.
 */
static void dumpClass(const DexFile* pDexFile, int idx, char** pLastPackage) {
  const DexFile::ClassDef& pClassDef = pDexFile->GetClassDef(idx);

  // Omitting non-public class.
  if (gOptions.exportsOnly && (pClassDef.access_flags_ & kAccPublic) == 0) {
    return;
  }

  if (gOptions.cfg) {
    dumpCfg(pDexFile, idx);
    return;
  }

  // For the XML output, show the package name.  Ideally we'd gather
  // up the classes, sort them, and dump them alphabetically so the
  // package name wouldn't jump around, but that's not a great plan
  // for something that needs to run on the device.
  const char* classDescriptor = pDexFile->StringByTypeIdx(pClassDef.class_idx_);
  if (!(classDescriptor[0] == 'L' &&
        classDescriptor[strlen(classDescriptor)-1] == ';')) {
    // Arrays and primitives should not be defined explicitly. Keep going?
    fprintf(stderr, "Malformed class name '%s'\n", classDescriptor);
  } else if (gOptions.outputFormat == OUTPUT_XML) {
    char* mangle = strdup(classDescriptor + 1);
    mangle[strlen(mangle)-1] = '\0';

    // Reduce to just the package name.
    char* lastSlash = strrchr(mangle, '/');
    if (lastSlash != nullptr) {
      *lastSlash = '\0';
    } else {
      *mangle = '\0';
    }

    for (char* cp = mangle; *cp != '\0'; cp++) {
      if (*cp == '/') {
        *cp = '.';
      }
    }  // for

    if (*pLastPackage == nullptr || strcmp(mangle, *pLastPackage) != 0) {
      // Start of a new package.
      if (*pLastPackage != nullptr) {
        fprintf(gOutFile, "</package>\n");
      }
      fprintf(gOutFile, "<package name=\"%s\"\n>\n", mangle);
      free(*pLastPackage);
      *pLastPackage = mangle;
    } else {
      free(mangle);
    }
  }

  // General class information.
  char* accessStr = createAccessFlagStr(pClassDef.access_flags_, kAccessForClass);
  const char* superclassDescriptor;
  if (pClassDef.superclass_idx_ == DexFile::kDexNoIndex16) {
    superclassDescriptor = nullptr;
  } else {
    superclassDescriptor = pDexFile->StringByTypeIdx(pClassDef.superclass_idx_);
  }
  if (gOptions.outputFormat == OUTPUT_PLAIN) {
    fprintf(gOutFile, "Class #%d            -\n", idx);
    fprintf(gOutFile, "  Class descriptor  : '%s'\n", classDescriptor);
    fprintf(gOutFile, "  Access flags      : 0x%04x (%s)\n", pClassDef.access_flags_, accessStr);
    if (superclassDescriptor != nullptr) {
      fprintf(gOutFile, "  Superclass        : '%s'\n", superclassDescriptor);
    }
    fprintf(gOutFile, "  Interfaces        -\n");
  } else {
    char* tmp = descriptorClassToDot(classDescriptor);
    fprintf(gOutFile, "<class name=\"%s\"\n", tmp);
    free(tmp);
    if (superclassDescriptor != nullptr) {
      tmp = descriptorToDot(superclassDescriptor);
      fprintf(gOutFile, " extends=\"%s\"\n", tmp);
      free(tmp);
    }
    fprintf(gOutFile, " interface=%s\n",
            quotedBool((pClassDef.access_flags_ & kAccInterface) != 0));
    fprintf(gOutFile, " abstract=%s\n", quotedBool((pClassDef.access_flags_ & kAccAbstract) != 0));
    fprintf(gOutFile, " static=%s\n", quotedBool((pClassDef.access_flags_ & kAccStatic) != 0));
    fprintf(gOutFile, " final=%s\n", quotedBool((pClassDef.access_flags_ & kAccFinal) != 0));
    // The "deprecated=" not knowable w/o parsing annotations.
    fprintf(gOutFile, " visibility=%s\n", quotedVisibility(pClassDef.access_flags_));
    fprintf(gOutFile, ">\n");
  }

  // Interfaces.
  const DexFile::TypeList* pInterfaces = pDexFile->GetInterfacesList(pClassDef);
  if (pInterfaces != nullptr) {
    for (u4 i = 0; i < pInterfaces->Size(); i++) {
      dumpInterface(pDexFile, pInterfaces->GetTypeItem(i), i);
    }  // for
  }

  // Fields and methods.
  const u1* pEncodedData = pDexFile->GetClassData(pClassDef);
  if (pEncodedData == nullptr) {
    if (gOptions.outputFormat == OUTPUT_PLAIN) {
      fprintf(gOutFile, "  Static fields     -\n");
      fprintf(gOutFile, "  Instance fields   -\n");
      fprintf(gOutFile, "  Direct methods    -\n");
      fprintf(gOutFile, "  Virtual methods   -\n");
    }
  } else {
    ClassDataItemIterator pClassData(*pDexFile, pEncodedData);
    if (gOptions.outputFormat == OUTPUT_PLAIN) {
      fprintf(gOutFile, "  Static fields     -\n");
    }
    EncodedStaticFieldValueIterator staticFieldValues(*pDexFile, pClassDef);
    for (int i = 0; pClassData.HasNextStaticField(); i++, pClassData.Next()) {
      EncodedStaticFieldValueIterator::ValueType valueType =
          EncodedStaticFieldValueIterator::kByte;
      const jvalue* pValue = nullptr;
      if (staticFieldValues.HasNext()) {
        valueType = staticFieldValues.GetValueType();
        pValue = &staticFieldValues.GetJavaValue();
      }
      dumpSField(pDexFile, pClassData.GetMemberIndex(),
                           pClassData.GetRawMemberAccessFlags(), i,
                 valueType, pValue);
      if (staticFieldValues.HasNext()) {
        staticFieldValues.Next();
      }
    }  // for
    DCHECK(!staticFieldValues.HasNext());
    if (gOptions.outputFormat == OUTPUT_PLAIN) {
      fprintf(gOutFile, "  Instance fields   -\n");
    }
    for (int i = 0; pClassData.HasNextInstanceField(); i++, pClassData.Next()) {
      dumpIField(pDexFile, pClassData.GetMemberIndex(),
                          pClassData.GetRawMemberAccessFlags(), i);
    }  // for
    if (gOptions.outputFormat == OUTPUT_PLAIN) {
      fprintf(gOutFile, "  Direct methods    -\n");
    }
    for (int i = 0; pClassData.HasNextDirectMethod(); i++, pClassData.Next()) {
      dumpMethod(pDexFile, pClassData.GetMemberIndex(),
                           pClassData.GetRawMemberAccessFlags(),
                           pClassData.GetMethodCodeItem(),
                           pClassData.GetMethodCodeItemOffset(), i);
    }  // for
    if (gOptions.outputFormat == OUTPUT_PLAIN) {
      fprintf(gOutFile, "  Virtual methods   -\n");
    }
    for (int i = 0; pClassData.HasNextVirtualMethod(); i++, pClassData.Next()) {
      dumpMethod(pDexFile, pClassData.GetMemberIndex(),
                           pClassData.GetRawMemberAccessFlags(),
                           pClassData.GetMethodCodeItem(),
                           pClassData.GetMethodCodeItemOffset(), i);
    }  // for
  }

  // End of class.
  if (gOptions.outputFormat == OUTPUT_PLAIN) {
    const char* fileName;
    if (pClassDef.source_file_idx_ != DexFile::kDexNoIndex) {
      fileName = pDexFile->StringDataByIdx(pClassDef.source_file_idx_);
    } else {
      fileName = "unknown";
    }
    fprintf(gOutFile, "  source_file_idx   : %d (%s)\n\n",
            pClassDef.source_file_idx_, fileName);
  } else if (gOptions.outputFormat == OUTPUT_XML) {
    fprintf(gOutFile, "</class>\n");
  }

  free(accessStr);
}

/*
 * Dumps the requested sections of the file.
 */
static void processDexFile(const char* fileName, const DexFile* pDexFile) {
  if (gOptions.verbose) {
    fprintf(gOutFile, "Opened '%s', DEX version '%.3s'\n",
            fileName, pDexFile->GetHeader().magic_ + 4);
  }

  // Headers.
  if (gOptions.showFileHeaders) {
    dumpFileHeader(pDexFile);
  }

  // Open XML context.
  if (gOptions.outputFormat == OUTPUT_XML) {
    fprintf(gOutFile, "<api>\n");
  }

  // Iterate over all classes.
  char* package = nullptr;
  const u4 classDefsSize = pDexFile->GetHeader().class_defs_size_;
  for (u4 i = 0; i < classDefsSize; i++) {
    if (gOptions.showSectionHeaders) {
      dumpClassDef(pDexFile, i);
    }
    dumpClass(pDexFile, i, &package);
  }  // for

  // Free the last package allocated.
  if (package != nullptr) {
    fprintf(gOutFile, "</package>\n");
    free(package);
  }

  // Close XML context.
  if (gOptions.outputFormat == OUTPUT_XML) {
    fprintf(gOutFile, "</api>\n");
  }
}

/*
 * Processes a single file (either direct .dex or indirect .zip/.jar/.apk).
 */
int processFile(const char* fileName) {
  if (gOptions.verbose) {
    fprintf(gOutFile, "Processing '%s'...\n", fileName);
  }

  // If the file is not a .dex file, the function tries .zip/.jar/.apk files,
  // all of which are Zip archives with "classes.dex" inside. The compressed
  // data needs to be extracted to a temp file, the location of which varies.
  //
  // TODO(ajcbik): fix following issues
  //
  // (1) gOptions.tempFileName is not accounted for
  // (2) gOptions.ignoreBadChecksum is not accounted for
  //
  std::string error_msg;
  std::vector<std::unique_ptr<const DexFile>> dex_files;
  if (!DexFile::Open(fileName, fileName, &error_msg, &dex_files)) {
    // Display returned error message to user. Note that this error behavior
    // differs from the error messages shown by the original Dalvik dexdump.
    fputs(error_msg.c_str(), stderr);
    fputc('\n', stderr);
    return -1;
  }

  // Success. Either report checksum verification or process
  // all dex files found in given file.
  if (gOptions.checksumOnly) {
    fprintf(gOutFile, "Checksum verified\n");
  } else {
    for (size_t i = 0; i < dex_files.size(); i++) {
      processDexFile(fileName, dex_files[i].get());
    }
  }
  return 0;
}

}  // namespace art


text:
package com.ccsi.web.validator;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

import com.ccsi.app.service.TenantService;
import com.ccsi.commons.dto.tenant.TenantInfo;

/**
 * @author mbmartinez
 */
@Component
public class CreateTenantValidator  implements Validator{

    private static Logger LOG = LoggerFactory.getLogger(CreateTenantValidator.class);

    @Autowired
    private LocalValidatorFactoryBean defaultValidator;

    @Autowired
    private TenantService service;

    @Override
    public boolean supports(Class<?> clazz) {
        return TenantInfo.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        LOG.debug("Performing registration form validation.");

        defaultValidator.validate(target, errors);

        TenantInfo tenant = (TenantInfo) target;
        if (tenant.getId() != null) {
            LOG.debug("Skip validating existing tenant.");
            return;
        }
        if (service.findByKeywordIgnoreCase(StringUtils.trimToEmpty(tenant.getKeyword())) != null) {
            errors.rejectValue("keyword", "keyword.unavailable", "Sadly, that keyword is already in use.");
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
//Problem 6. Strings and Objects

//Declare two string variables and assign them with Hello and World.
//Declare an object variable and assign it with the concatenation of the first two variables (mind adding an interval between).
//Declare a third string variable and initialize it with the value of the object variable (you should perform type casting).

using System;
class Hello
{
    static void Main()
    {

        string firstString = "Hello";
        string secondString = "World";
        object thirdString = firstString + ", " + secondString;
        string fourthString = (string)thirdString;
        Console.WriteLine(fourthString+".");
    }
}


text:
////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// MIT X11 license, Copyright (c) 2005-2006 by:                               //
//                                                                            //
// Authors:                                                                   //
//      Michael Dominic K. <michaldominik@gmail.com>                          //
//                                                                            //
// Permission is hereby granted, free of charge, to any person obtaining a    //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation  //
// the rights to use, copy, modify, merge, publish, distribute, sublicense,   //
// and/or sell copies of the Software, and to permit persons to whom the      //
// Software is furnished to do so, subject to the following conditions:       //
//                                                                            //
// The above copyright notice and this permission notice shall be included    //
// in all copies or substantial portions of the Software.                     //
//                                                                            //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS    //
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF                 //
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN  //
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   //
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      //
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  //
// USE OR OTHER DEALINGS IN THE SOFTWARE.                                     //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

#ifndef __DIVA_WIDGETS_TYPES_H__
#define __DIVA_WIDGETS_TYPES_H__

/* Structs */

typedef struct                  _DivaWidgetsAspectFrame DivaWidgetsAspectFrame;

typedef struct                  _DivaWidgetsThmbRenderer DivaWidgetsThmbRenderer;

typedef struct                  _DivaWidgetsTaggyRenderer DivaWidgetsTaggyRenderer;

typedef struct                  _DivaWidgetsPaintRenderer DivaWidgetsPaintRenderer;

/* Classes */

typedef struct                  _DivaWidgetsAspectFrameClass DivaWidgetsAspectFrameClass;

typedef struct                  _DivaWidgetsThmbRendererClass DivaWidgetsThmbRendererClass;

typedef struct                  _DivaWidgetsTaggyRendererClass DivaWidgetsTaggyRendererClass;

typedef struct                  _DivaWidgetsPaintRendererClass DivaWidgetsPaintRendererClass;

/* GTypes */

#define                         DIVA_WIDGETS_TYPE_ASPECT_FRAME (diva_widgets_aspect_frame_get_type ())

#define                         DIVA_WIDGETS_TYPE_THMB_RENDERER (diva_widgets_thmb_renderer_get_type ())

#define                         DIVA_WIDGETS_TYPE_TAGGY_RENDERER (diva_widgets_taggy_renderer_get_type ())

#define                         DIVA_WIDGETS_TYPE_PAINT_RENDERER (diva_widgets_paint_renderer_get_type ())

/* Is */

#define                         DIVA_WIDGETS_IS_ASPECT_FRAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
                                                                                DIVA_WIDGETS_TYPE_ASPECT_FRAME))

#define                         DIVA_WIDGETS_IS_THMB_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
                                                                                DIVA_WIDGETS_TYPE_THMB_RENDERER))

#define                         DIVA_WIDGETS_IS_TAGGY_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
                                                                                DIVA_WIDGETS_TYPE_TAGGY_RENDERER))

#define                         DIVA_WIDGETS_IS_PAINT_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
                                                                                DIVA_WIDGETS_TYPE_PAINT_RENDERER))

/* Type casts */

#define                         DIVA_WIDGETS_ASPECT_FRAME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
                                                                                DIVA_WIDGETS_TYPE_ASPECT_FRAME, \
                                                                                DivaWidgetsAspectFrame))

#define                         DIVA_WIDGETS_THMB_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
                                                                                DIVA_WIDGETS_TYPE_THMB_RENDERER, \
                                                                                DivaWidgetsThmbRenderer))

#define                         DIVA_WIDGETS_TAGGY_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
                                                                                DIVA_WIDGETS_TYPE_TAGGY_RENDERER, \
                                                                                DivaWidgetsTaggyRenderer))

#define                         DIVA_WIDGETS_PAINT_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
                                                                                GDV_TYPE_SOURCE, \
                                                                                DivaWidgetsThmbRenderer))

#endif


text:
<?php

namespace Despark\Command\Tart;

use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Formatter\OutputFormatter;
use InvalidArgumentException;

/**
 * tart:generate - Generate a new section in the admin based on a model.
 *
 * @link https://github.com/openbuildings/jam-tart
 * @link http://symfony.com/doc/current/components/console/introduction.html
 * @author Haralan Dobrev <hkdobrev@gmail.com>
 */
class GenerateCommand extends AbstractTartCommand
{
    const DEFAULT_AUTHOR = 'Ivan Kerin';

    // Templates

    const DEFAULT_TEMPLATES_DIR = 'templates';

    public $templatesDir;

    protected function configure()
    {
        $this
            ->setName('tart:generate')
            ->setDescription('Generate a new jam-tart admin module based on a model')
            ->addArgument(
                'model',
                InputArgument::REQUIRED,
                'Which model to use?'
            )
            ->addOption(
               'controller',
               'c',
               InputOption::VALUE_REQUIRED,
               'What name to use for the Controller? Defaults to pluralized model'
            )
            ->addOption(
               'author',
               'a',
               InputOption::VALUE_REQUIRED,
               'Set the @author annotations',
               $this->getDefaultAuthor()
            )
            ->addOption(
               'module',
               'm',
               InputOption::VALUE_REQUIRED,
               'In which Kohana module to place the files?',
               self::MODULE_DEFAULT
            )
            ->addOption(
               'force',
               'f',
               InputOption::VALUE_NONE,
               'Should overwrite existing files?'
            )
            ->addOption(
                'dry-run',
                'd',
                InputOption::VALUE_NONE,
                'Do not delete, only show what would be deleted'
            )
            ->addOption(
               'batch-modify',
               null,
               InputOption::VALUE_NONE,
               'Include batch modify code?'
            )
            ->addOption(
               'batch-delete',
               null,
               InputOption::VALUE_NONE,
               'Include batch delete code?'
            )
            ->addOption(
               'templates-dir',
               't',
               InputOption::VALUE_REQUIRED,
               'Which dir to use for templates?',
               __DIR__.DIRECTORY_SEPARATOR.self::DEFAULT_TEMPLATES_DIR
            );
    }

    private function getDefaultAuthor()
    {
        $gitAuthorName = trim(shell_exec('git config user.name'), "\n ");
        $gitAuthorEmail = trim(shell_exec('git config user.email'), "\n ");

        if ($gitAuthorName) {

            if ($gitAuthorEmail) {
                $gitAuthorName .= ' <'.$gitAuthorEmail.'>';
            }

            return $gitAuthorName;
        }

        if (isset($_SERVER['USER'])) {
            return $_SERVER['USER'];
        }

        return self::DEFAULT_AUTHOR;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $nameResolver = new NameResolver(
            $input->getArgument('model'),
            $input->getOption('controller')
        );

        $directoryResolver = new DirectoryResolver($input->getOption('module'));

        $data = $this->getInitialData($nameResolver, $directoryResolver);

        $batchDelete = $input->getOption('batch-delete');
        $batchModify = $input->getOption('batch-modify');
        $this->templatesDir = $input->getOption('templates-dir');

        $data = $this->preProcessData(
            $data,
            $batchDelete,
            $batchModify
        );

        $data['{{author}}'] = $input->getOption('author');

        if ($input->getOption('controller')) {
            $data['{{controllerOption}}'] = sprintf(
                "                ->controller('%s')",
                $nameResolver->getControllerName()
            );

            $data['{{extraController}}'] = sprintf(
                ", array('controller' => '%s')",
                $nameResolver->getControllerName()
            );

            $data['{{extraControllerDelete}}'] = sprintf(
                "array('controller' => '%s', 'action' => 'delete')",
                $nameResolver->getControllerName()
            );
        }

        $dryRun = $input->getOption('dry-run');

        $files = $this->getFiles(
            $nameResolver,
            $directoryResolver,
            $batchDelete,
            $batchModify
        );

        $viewsDir = $directoryResolver->getViewsDirectory()
            .$nameResolver->getControllerName();

        if ( !$dryRun and !file_exists($viewsDir)) {
            mkdir($viewsDir, 0777, true);
        }

        $output->writeln(sprintf(
            ($dryRun ? '<dry>[DRY-RUN]</dry> ' : '')
                .'<info>%d files to be created:</info>',
            count($files)
        ));

        foreach ($files as $filePath => $templateFile) {
            $humanizedFilePath = str_replace(MODPATH, 'MODPATH/', $filePath);
            $output->writeln($humanizedFilePath);
            file_put_contents($filePath, $this->parse($templateFile, $data));
        }
    }

    public function getInitialData(
        NameResolver $nameResolver,
        DirectoryResolver $directoryResolver
    ) {
        return array(
            '{{controller}}' => $nameResolver->getControllerName(),
            '{{nameKey}}' => $nameResolver->getNameKey(),
            '{{model}}' => $nameResolver->getModelName(),
            '{{moduleName}}' => $directoryResolver->getModule(),
            '{{modelTitle}}' => $nameResolver->getModelTitle(),
            '{{viewsPath}}' => $directoryResolver->getViewsPath()
                .DIRECTORY_SEPARATOR
                .$nameResolver->getControllerName(),
            '{{pluralName}}' => $nameResolver->getPluralName(),
            '{{controllerTitle}}' => $nameResolver->getControllerTitle(),
            '{{controllerClass}}' => $nameResolver->getControllerClass(),
            '{{batchIndex}}' => '',
            '{{batchDelete}}' => '',
            '{{batchModify}}' => '',
            '{{controllerOption}}' => '',
            '{{extraController}}' => '',
            '{{extraControllerDelete}}' => "'delete'",
        );
    }

    public function preProcessData(
        array $data,
        $batchModify = false,
        $batchDelete = false
    ) {
        $actions = '';

        if ($batchDelete) {
            $actions .= "\n                'delete' => 'Delete',";
            $data['{{batchDelete}}'] = $this->parse(
                static::TEMPLATE_BATCH_DELETE,
                $data
            );
        }

        if ($batchModify) {
            $actions .= "\n                'modify' => 'Modify',";

            $data['{{batchModify}}'] = $this->parse(
                static::TEMPLATE_BATCH_MODIFY,
                $data
            );
        }

        if ($batchDelete or $batchModify) {
            $data['{{batchIndex}}'] = $this->parse(
                static::TEMPLATE_BATCH_INDEX,
                $data + array('{{actions}}' => $actions)
            );
        }

        return $data;
    }

    private function parse($templateFile, $data)
    {
        $templateFilePath = $this->templatesDir
            .DIRECTORY_SEPARATOR
            .$templateFile;

        if ( !is_file($templateFilePath)) {
            throw new InvalidArgumentException(sprintf(
                'There is no template "%s"',
                $templateFile
            ));
        }

        $templateString = file_get_contents($templateFilePath);

        return strtr($templateString, $data);
    }

    public function getFiles(
        NameResolver $nameResolver,
        DirectoryResolver $directoryResolver,
        $batchDelete = false,
        $batchModify = false
    ) {
        $files = array();

        foreach (static::$viewFiles as $templateName => $viewFile) {

            if ($templateName === self::TEMPLATE_VIEW_BATCH_DELETE and !$batchDelete) {
                continue;
            }

            if ($templateName === self::TEMPLATE_VIEW_BATCH_MODIFY and !$batchModify) {
                continue;
            }

            $filePath = $directoryResolver->getViewsDirectory()
                .$nameResolver->getControllerName()
                .DIRECTORY_SEPARATOR
                .$viewFile;
            $files[$filePath] = $templateName;
        }

        $controllerFilePath = $directoryResolver->getControllersDirectory()
            .$nameResolver->getControllerPath()
            .EXT;

        $files[$controllerFilePath] = static::TEMPLATE_CONTROLLER;

        return $files;
    }
}


text:
'use strict';

const argv = require('minimist')(process.argv.slice(2));
const karmaConfig = require('../../test-configs/karma.conf');
const {
  commonIntegrationTestPaths,
  commonUnitTestPaths,
  integrationTestPaths,
  karmaHtmlFixturesPath,
  karmaJsPaths,
  unitTestCrossBrowserPaths,
  unitTestPaths,
} = require('../../test-configs/config');
const {
  createCtrlcHandler,
  exitCtrlcHandler,
} = require('../../common/ctrlcHandler');
const {app} = require('../../server/test-server');
const {createKarmaServer, getAdTypes} = require('./helpers');
const {cyan, green, red, yellow} = require('../../common/colors');
const {dotWrappingWidth} = require('../../common/logging');
const {getEsbuildBabelPlugin} = require('../../common/esbuild-babel');
const {getFilesFromArgv} = require('../../common/utils');
const {isCiBuild, isCircleciBuild} = require('../../common/ci');
const {log} = require('../../common/logging');
const {reportTestStarted} = require('../report-test-status');
const {SERVER_TRANSFORM_PATH} = require('../../server/typescript-compile');
const {startServer, stopServer} = require('../serve');
const {unitTestsToRun} = require('./helpers-unit');

/**
 * Used to print dots during esbuild + babel transforms
 */
let wrapCounter = 0;

/**
 * Used to lazy-require the HTML transformer function after the server is built.
 */
let transform;

/**
 * Consumes {@link karmaConfig} and dynamically populates fields based on test
 * type and command line arguments.
 */
class RuntimeTestConfig {
  /** @type {Array<string|Record<string, [string, *]>>} */
  plugins = [];

  /**@type {Record<string, string|string[]>} */
  preprocessors = {};

  /** @type {string[]} */
  reporters = [];

  client = {};

  /**
   * @param {string} testType
   */
  constructor(testType) {
    this.testType = testType;
    /**
     * TypeScript is used for typechecking here and is unable to infer the type
     * after using Object.assign. This results in errors relating properties of
     * which can never be `null` being treated as though they could be.
     */
    Object.assign(this, karmaConfig);
    this.updateBrowsers();
    this.updateReporters();
    this.updateFiles();
    this.updatePreprocessors();
    this.updateEsbuildConfig();
    this.updateClient();
    this.updateMiddleware();
    this.updateCoverageSettings();
  }

  /**
   * Updates the set of preprocessors to run on HTML and JS files before testing.
   * Notes:
   * - The HTML transform is lazy-required because the server is built at startup.
   * - We must use babel on windows until esbuild can natively downconvert to ES5.
   */
  updatePreprocessors() {
    const createHtmlTransformer = function () {
      return function (content, _file, done) {
        if (!transform) {
          const outputDir = `../../../${SERVER_TRANSFORM_PATH}/dist/transform`;
          transform = require(outputDir).transformSync;
        }
        done(transform(content));
      };
    };
    createHtmlTransformer.$inject = [];
    this.plugins.push({
      'preprocessor:htmlTransformer': ['factory', createHtmlTransformer],
    });
    this.preprocessors[karmaHtmlFixturesPath] = ['htmlTransformer', 'html2js'];
    for (const karmaJsPath of karmaJsPaths) {
      this.preprocessors[karmaJsPath] = ['esbuild'];
    }
  }

  /**
   * Updates the browsers based off of the test type
   * being run (unit, integration, a4a) and test settings.
   * Defaults to Chrome if no matching settings are found.
   */
  updateBrowsers() {
    if (argv.edge) {
      Object.assign(this, {
        browsers: [argv.headless ? 'EdgeHeadless' : 'Edge'],
      });
      return;
    }

    if (argv.firefox) {
      Object.assign(this, {
        browsers: ['Firefox_flags'],
        customLaunchers: {
          // eslint-disable-next-line
        Firefox_flags: {
            base: 'Firefox',
            flags: argv.headless ? ['-headless'] : [],
          },
        },
      });
      return;
    }

    if (argv.ie) {
      Object.assign(this, {
        browsers: ['IE'],
        customLaunchers: {
          IeNoAddOns: {
            base: 'IE',
            flags: ['-extoff'],
          },
        },
      });
      return;
    }

    if (argv.safari) {
      Object.assign(this, {browsers: ['SafariNative']});
      return;
    }

    if (argv.chrome_canary) {
      Object.assign(this, {browsers: ['ChromeCanary']});
      return;
    }

    if (argv.chrome_flags) {
      const chromeFlags = [];
      argv.chrome_flags.split(',').forEach((flag) => {
        chromeFlags.push('--'.concat(flag));
      });
      Object.assign(this, {
        browsers: ['Chrome_flags'],
        customLaunchers: {
          // eslint-disable-next-line
        Chrome_flags: {
            base: 'Chrome',
            flags: chromeFlags,
          },
        },
      });
      return;
    }

    if (argv.headless) {
      Object.assign(this, {browsers: ['Chrome_no_extensions_headless']});
      return;
    }

    // Default to Chrome.
    Object.assign(this, {
      browsers: [isCiBuild() ? 'Chrome_ci' : 'Chrome_no_extensions'],
    });
  }

  /**
   * Adds reporters to the default karma spec per test settings.
   * Overrides default reporters for verbose settings.
   */
  updateReporters() {
    if (
      (argv.testnames || argv.local_changes || argv.files || argv.verbose) &&
      !isCiBuild()
    ) {
      this.reporters = ['mocha'];
    }

    if (isCircleciBuild()) {
      this.reporters.push('junit');
      this.junitReporter = {
        outputFile: `result-reports/${this.testType}.xml`,
        useBrowserName: false,
      };
    }

    if (argv.coverage) {
      this.reporters.push('coverage-istanbul');
    }

    if (argv.report) {
      this.reporters.push('json-result');
      this.jsonResultReporter = {
        outputFile: `result-reports/${this.testType}.json`,
      };
    }
  }

  /**
   * Computes the set of files for Karma to load based on factors like test type,
   * target browser, and flags.
   */
  updateFiles() {
    switch (this.testType) {
      case 'unit':
        if (argv.files) {
          this.files = commonUnitTestPaths.concat(getFilesFromArgv());
          return;
        }
        if (argv.firefox || argv.safari || argv.edge) {
          this.files = commonUnitTestPaths.concat(unitTestCrossBrowserPaths);
          return;
        }
        if (argv.local_changes) {
          this.files = commonUnitTestPaths.concat(unitTestsToRun());
          return;
        }
        this.files = commonUnitTestPaths.concat(unitTestPaths);
        return;

      case 'integration':
        if (argv.files) {
          this.files = commonIntegrationTestPaths.concat(getFilesFromArgv());
          return;
        }
        this.files = commonIntegrationTestPaths.concat(integrationTestPaths);
        return;

      default:
        throw new Error(`Test type ${this.testType} was not recognized`);
    }
  }

  /**
   * Logs a message indicating the start of babel transforms.
   */
  logBabelStart() {
    wrapCounter = 0;
    log(
      green('Transforming tests with'),
      cyan('esbuild'),
      green('and'),
      cyan('babel') + green('...')
    );
  }

  /**
   * Prints a dot for every babel transform, with wrapping if needed.
   */
  printBabelDot() {
    process.stdout.write('.');
    if (++wrapCounter >= dotWrappingWidth) {
      wrapCounter = 0;
      process.stdout.write('\n');
    }
  }

  /**
   * Updates the esbuild config in the karma spec so esbuild can run with it.
   */
  updateEsbuildConfig() {
    const importPathPlugin = {
      name: 'import-path',
      setup(build) {
        build.onResolve({filter: /^[\w-]+$/}, (file) => {
          if (file.path === 'stream') {
            return {path: require.resolve('stream-browserify'), namespace: ''};
          }
        });
      },
    };
    const babelPlugin = getEsbuildBabelPlugin(
      /* callerName */ 'test',
      /* enableCache */ true,
      /* preSetup */ this.logBabelStart,
      /* postLoad */ this.printBabelDot
    );
    this.esbuild = {
      target: 'es5',
      define: {
        'process.env.NODE_DEBUG': 'false',
        'process.env.NODE_ENV': '"test"',
      },
      plugins: [importPathPlugin, babelPlugin],
      sourcemap: 'inline',
    };
  }

  /**
   * Updates the client so that tests can access karma state. This is available in
   * the browser via window.parent.karma.config.
   */
  updateClient() {
    this.singleRun = !argv.watch;
    this.client.mocha.grep = !!argv.grep;
    this.client.verboseLogging = !!argv.verbose;
    this.client.captureConsole = !!argv.verbose || !!argv.files;
    this.client.amp = {
      useCompiledJs: !!argv.compiled,
      adTypes: getAdTypes(),
      mochaTimeout: this.client.mocha.timeout,
      testServerPort: this.client.testServerPort,
      isModuleBuild: !!argv.esm, // Used by skip matchers in testing/test-config.js
    };
  }

  /**
   * Inserts the AMP dev server into the middleware used by the Karma server.
   */
  updateMiddleware() {
    const createDevServerMiddleware = function () {
      return require(require.resolve('../../server/app.js'));
    };
    this.plugins.push({
      'middleware:devServer': ['factory', createDevServerMiddleware],
    });
    this.beforeMiddleware = ['devServer'];
  }

  /**
   * Updates the Karma config to gather coverage info if coverage is enabled.
   */
  updateCoverageSettings() {
    if (argv.coverage) {
      this.plugins.push('karma-coverage-istanbul-reporter');
      this.coverageIstanbulReporter = {
        dir: 'test/coverage',
        reports: isCiBuild() ? ['lcovonly'] : ['html', 'text', 'text-summary'],
        'report-config': {lcovonly: {file: `lcov-${this.testType}.info`}},
      };
    }
  }
}

class RuntimeTestRunner {
  /**
   *
   * @param {RuntimeTestConfig} config
   */
  constructor(config) {
    this.config = config;
    this.env = null;
    this.exitCode = 0;
  }

  /**
   * @return {Promise<void>}
   */
  async maybeBuild() {
    throw new Error('maybeBuild method must be overridden');
  }

  /**
   * @return {Promise<void>}
   */
  async setup() {
    await this.maybeBuild();
    await startServer({
      name: 'AMP Test Server',
      host: 'localhost',
      port: this.config.client.testServerPort,
      middleware: () => [app],
    });
    const handlerProcess = createCtrlcHandler(`amp ${this.config.testType}`);
    this.env = new Map().set('handlerProcess', handlerProcess);
  }

  /**
   * @return {Promise<void>}
   */
  async run() {
    await reportTestStarted();
    this.exitCode = await createKarmaServer(this.config);
  }

  /**
   * @return {Promise<void>}
   */
  async teardown() {
    await stopServer();
    exitCtrlcHandler(/** @type {Map} */ (this.env).get('handlerProcess'));
    if (this.exitCode != 0) {
      const message = `Karma test failed with exit code ${this.exitCode}`;
      log(red('ERROR:'), yellow(message));
      throw new Error(message);
    }
  }
}

module.exports = {
  RuntimeTestRunner,
  RuntimeTestConfig,
};


text:
var terah = {
  name: "Terah",
  age: 32,
  height: 66,
  weight: 130,
  hairColor: "brown",
  eyeColor: "brown"
}
// __________________________________________
// Write your code below.

var adam = {
  name: "Adam"
};

terah.spouse = adam;
terah.weight = 125;
delete terah.eyeColor;
adam.spouse = terah;
terah.children = {
  carson: {name: "Carson"},
  carter: {name: "Carter"},
  colton: {name: "Colton"},
};
adam.children = terah.children

// __________________________________________
// Reflection: Use the reflection guidelines
//What tests did you have trouble passing? What did you do to make it pass? Why did that work?

//I had issues passing when it came to adding carson property to the value of the terah children property. I had issues wrapping my head around what they wanted, creating an object within an object, but after some research and looking around, it makes sense now.

// How difficult was it to add and delete properties outside of the object itself?

// It was quite easy to add and delete properties outside of the object, once learning how to do it in the first place, its quite simple.

// What did you learn about manipulating objects in this challenge?

// I learned how to add and delete properties outside of the objects, which will be quite helpful, also solidified objects inside objects.

//

// __________________________________________
// Driver Code:  Do not alter code below this line.
function assert(test, message, test_number) {
  if (!test) {
    console.log(test_number + "false");
    throw "ERROR: " + message;
  }
  console.log(test_number + "true");
  return true;
}

assert(
  (adam instanceof Object),
  "The value of adam should be an Object.",
  "1. "
)

assert(
  (adam.name === "Adam"),
  "The value of the adam name property should be 'Adam'.",
  "2. "
)

assert(
  terah.spouse === adam,
  "terah should have a spouse property with the value of the object adam.",
  "3. "
)

assert(
  terah.weight === 125,
  "The terah weight property should be 125.",
  "4. "
)

assert(
  terah.eyeColor === undefined || null,
  "The terah eyeColor property should be deleted.",
  "5. "
)

assert(
  terah.spouse.spouse === terah,
  "Terah's spouse's spouse property should refer back to the terah object.",
  "6. "
)

assert(
  (terah.children instanceof Object),
  "The value of the terah children property should be defined as an Object.",
  "7. "
)

assert(
  (terah.children.carson instanceof Object),
  "carson should be defined as an object and assigned as a child of Terah",
  "8. "
  )

assert(
  terah.children.carson.name === "Carson",
  "Terah's children should include an object called carson which has a name property equal to 'Carson'.",
  "9. "
)

assert(
  (terah.children.carter instanceof Object),
  "carter should be defined as an object and assigned as a child of Terah",
  "10. "
  )

assert(
  terah.children.carter.name === "Carter",
  "Terah's children should include an object called carter which has a name property equal to 'Carter'.",
  "11. "
)

assert(
  (terah.children.colton instanceof Object),
  "colton should be defined as an object and assigned as a child of Terah",
  "12. "
  )

assert(
  terah.children.colton.name === "Colton",
  "Terah's children should include an object called colton which has a name property equal to 'Colton'.",
  "13. "
)

assert(
  adam.children === terah.children,
  "The value of the adam children property should be equal to the value of the terah children property",
  "14. "
)

console.log("\nHere is your final terah object:")
console.log(terah)


text:
from array import array
import os

from reader.base import AbstractReader

__author__ = 'cenk'

class MNIST(AbstractReader):
    def __init__(self, *args, **kwargs):
        super(MNIST, self).__init__()

        self.train_path = os.path.join(self.base_dir, 'data/mnist/train-images.idx3-ubyte')
        self.test_path = os.path.join(self.base_dir, 'data/mnist/t10k-images.idx3-ubyte')

        self.train_label_path = os.path.join(self.base_dir, 'data/mnist/train-labels.idx1-ubyte')
        self.test_label_path = os.path.join(self.base_dir, 'data/mnist/t10k-labels.idx1-ubyte')

    @property
    def trainset_images(self):
        """
        :return: [60000, 784]
        """
        return self.read(self.train_path, **{'type': 'image'})

    @property
    def testset_images(self):
        """
        :return: [10000, 784]
        """
        return self.read(self.test_path, **{'type': 'image'})

    @property
    def trainset_labels(self):
        return self.read(self.train_label_path, **{'type': 'label'})

    @property
    def testset_labels(self):
        return self.read(self.test_label_path, **{'type': 'label'})

    def read(self, path, *args, **kwargs):

        import struct

        with open(path, 'rb') as file:
            data_type = kwargs.get('type')
            if data_type == 'image':
                magic, size, rows, cols = struct.unpack(">IIII", file.read(16))
                if magic != 2051:
                    raise ValueError('Magic number mismatch, expected 2051,'
                                     'got %d' % magic)

                image_data = array("B", file.read())
                images = []
                for i in xrange(size):
                    images.append([0] * rows * cols)

                for i in xrange(size):
                    images[i][:] = image_data[i * rows * cols: (i + 1) * rows * cols]
                return images

            elif data_type == 'label':
                magic, size = struct.unpack(">II", file.read(8))
                if magic != 2049:
                    raise ValueError('Magic number mismatch, expected 2049,'
                                     'got %d' % magic)

                labels = array("B", file.read())
                return labels


text:
#include "mega/waiter.h"

namespace mega {
void Waiter::init(dstime ds)
{
    maxds = ds;
}

// add events to wakeup criteria
void Waiter::wakeupby(EventTrigger* et, int flags)
{
    et->addevents(this, flags);
}
} // namespace


text:
"""
Local Shared Object implementation.

Local Shared Object (LSO), sometimes known as Adobe Flash cookies, is a
cookie-like data entity used by the Adobe Flash Player and Gnash. The players
allow web content to read and write LSO data to the computer's local drive on
a per-domain basis.

:see: `Local Shared Object on WikiPedia (external) <http://en.wikipedia.org/wiki/Local_Shared_Object>`_
:see: `Local Shared Object envelope (external) <http://osflash.org/documentation/amf/envelopes/sharedobject>`_

:since: 0.1.0
"""

import pyamf
from pyamf import util

#: Magic Number - 2 bytes
HEADER_VERSION = '\x00\xbf'
#: Marker - 10 bytes
HEADER_SIGNATURE = 'TCSO\x00\x04\x00\x00\x00\x00'
#: Padding - 4 bytes
PADDING_BYTE = '\x00'

def decode(stream, strict=True):
    """
    Decodes a SOL stream. `strict` mode ensures that the sol stream is as spec
    compatible as possible.

    :param strict: Ensure that the SOL stream is as spec compatible as possible.
    :type strict: `bool`
    :return: A `tuple` containing the `root_name` and a `dict` of name,
        value pairs.
    :rtype: `tuple`

    :raise DecodeError: Unknown SOL version in header.
    :raise DecodeError: Inconsistent stream header length.
    :raise DecodeError: Invalid signature.
    :raise DecodeError: Invalid padding read.
    :raise DecodeError: Missing padding byte.
    """
    if not isinstance(stream, util.BufferedByteStream):
        stream = util.BufferedByteStream(stream)

    # read the version
    version = stream.read(2)

    if version != HEADER_VERSION:
        raise pyamf.DecodeError('Unknown SOL version in header')

    # read the length
    length = stream.read_ulong()

    if strict and stream.remaining() != length:
        raise pyamf.DecodeError('Inconsistent stream header length')

    # read the signature
    signature = stream.read(10)

    if signature != HEADER_SIGNATURE:
        raise pyamf.DecodeError('Invalid signature')

    length = stream.read_ushort()
    root_name = stream.read_utf8_string(length)

    # read padding
    if stream.read(3) != PADDING_BYTE * 3:
        raise pyamf.DecodeError('Invalid padding read')

    decoder = pyamf.get_decoder(stream.read_uchar())
    decoder.stream = stream

    values = {}

    while 1:
        if stream.at_eof():
            break

        name = decoder.readString()
        value = decoder.readElement()

        # read the padding
        if stream.read(1) != PADDING_BYTE:
            raise pyamf.DecodeError('Missing padding byte')

        values[name] = value

    return (root_name, values)

def encode(name, values, strict=True, encoding=pyamf.AMF0):
    """
    Produces a SharedObject encoded stream based on the name and values.

    :param name: The root name of the SharedObject.
    :type name: `basestring`
    :param values: A `dict` of name value pairs to be encoded in the stream.
    :type values: `dict`
    :param strict: Ensure that the SOL stream is as spec compatible as possible.
    :type strict: `bool`
    :return: A SharedObject encoded stream.
    :rtype: :class:`BufferedByteStream<pyamf.util.BufferedByteStream>`
    """
    encoder = pyamf.get_encoder(encoding)
    encoder.stream = stream = util.BufferedByteStream()

    # write the header
    stream.write(HEADER_VERSION)

    if strict is True:
        length_pos = stream.tell()

    stream.write_ulong(0)

    # write the signature
    stream.write(HEADER_SIGNATURE)

    # write the root name
    if not isinstance(name, unicode):
        name = unicode(name)

    stream.write_ushort(len(name))
    stream.write_utf8_string(name)

    # write the padding
    stream.write(PADDING_BYTE * 3)
    stream.write_uchar(encoding)

    for n, v in values.iteritems():
        encoder.writeString(n, writeType=False)
        encoder.writeElement(v)

        # write the padding
        stream.write(PADDING_BYTE)

    if strict:
        stream.seek(length_pos)
        stream.write_ulong(stream.remaining() - 4)

    stream.seek(0)

    return stream

def load(name_or_file):
    """
    Loads a sol file and returns a :class:`SOL` object.

    :param name_or_file: Name of file, or file-object.
    :type name_or_file: `str` or `StringIO`

    :raise ValueError: Readable stream expected.
    """
    f = name_or_file
    opened = False

    if isinstance(name_or_file, basestring):
        f = open(name_or_file, 'rb')
        opened = True
    elif not hasattr(f, 'read'):
        raise ValueError('Readable stream expected')

    name, values = decode(f.read())
    s = SOL(name)

    for n, v in values.iteritems():
        s[n] = v

    if opened is True:
        f.close()

    return s

def save(sol, name_or_file, encoding=pyamf.AMF0):
    """
    Writes a :class:`SOL` object to `name_or_file`.

    :param sol:
    :type sol:
    :param name_or_file: Name of file, or file-object.
    :type name_or_file: `str` or `StringIO`
    :param encoding: AMF encoding type.
    :type encoding: `int`

    :raise ValueError: Writable stream expected.
    """
    f = name_or_file
    opened = False

    if isinstance(name_or_file, basestring):
        f = open(name_or_file, 'wb+')
        opened = True
    elif not hasattr(f, 'write'):
        raise ValueError('Writable stream expected')

    f.write(encode(sol.name, sol, encoding=encoding).getvalue())

    if opened:
        f.close()

class SOL(dict):
    """
    Local Shared Object class, allows easy manipulation of the internals of a
    `sol` file.
    """
    def __init__(self, name):
        self.name = name

    def save(self, name_or_file, encoding=pyamf.AMF0):
        save(self, name_or_file, encoding)

    def __repr__(self):
        return '<%s %s %s at 0x%x>' % (self.__class__.__name__,
            self.name, dict.__repr__(self), id(self))

LSO = SOL


text:
package com.siyeh.ig.style;

import com.siyeh.ig.IGInspectionTestCase;

public class UnnecessaryThisInspectionTest extends IGInspectionTestCase {

  public void test() throws Exception {
    doTest("com/siyeh/igtest/style/unnecessary_this",
           new UnnecessaryThisInspection());
  }
}


text:
/*
  FARM like experiment for RDMA read throughput
  Had to adjust size of completion queues and queue pairs to allow for large number of pending requests since we post all the reads without waiting for their completion
*/

#include <chrono>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <map>
#include <pthread.h>
#include <string.h>
#include <thread>
#include <time.h>
#include <vector>

#include "sst/tcp.h"
#include "sst/verbs.h"

using std::cin;
using std::cout;
using std::endl;
using std::map;
using std::string;
using std::vector;

using namespace sst;
using namespace sst::tcp;

// number of threads to spawn for posting reads
int num_threads = 16;
// threads set this to indicate main that they are ready to post reads
vector<bool> done_initializing;
// main sets this to set off the threads
bool send = false;

// number of nodes
int num_nodes;
// rank of the current node
int node_rank;

// size of data transfer
long long int read_size = 16;
// size of the entire buffer. Its size shouldn't matter for performance. CHECK THIS!)
long long int buf_size = 1024 * 1024;
// number of reads per thread
int num_reads = 10000;

// resources for the nodes
vector<resources *> res_vec;

void *post_reads(void *tid) {
    int thread_id = (long)tid;

    // we want to separate calls to random number generator from read requests
    int node[num_reads];
    long long int offset[num_reads];
    for(int i = 0; i < num_reads; ++i) {
        // pick a random node
        node[i] = rand() % (num_nodes - 1);
        // but not the local node!
        if(node[i] >= node_rank) {
            node[i] += 1;
        }
        // pick a random offset to read
        offset[i] = read_size * (rand() % (buf_size / read_size));
    }
    cout << "Done with initializing : thread " << thread_id << endl;
    // indicate to main thread, readiness to post reads
    done_initializing[thread_id] = true;

    // wait for the signal to start reading
    while(send == false) {
    }
    // read randomly many times
    for(int i = 0; i < num_reads; ++i) {
        // post the read
        res_vec[node[i]]->post_remote_read(offset[i], read_size);
    }

    pthread_exit(NULL);
}

void *poll_reads(void *tid) {
    for(int i = 0; i < num_reads; ++i) {
        verbs_poll_completion();
    }

    struct timespec end_time;
    clock_gettime(CLOCK_REALTIME, &end_time);
    cout << end_time.tv_sec * 1000000000 + end_time.tv_nsec << endl;

    return NULL;
}

void initialize(int node_rank, const map<uint32_t, string> &ip_addrs) {
    // initialize tcp connections
    tcp_initialize(node_rank, ip_addrs);
    // initialize the rdma resources
    verbs_initialize();
}

int main() {
    srand(time(NULL));

    pthread_t threads[num_threads], poll_threads[num_threads];
    pthread_attr_t attr;
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    cin >> num_nodes;
    cin >> node_rank;
    // input the ip addresses
    map<uint32_t, string> ip_addrs;
    for(int i = 0; i < num_nodes; ++i) {
        cin >> ip_addrs[i];
    }

    // create all tcp connections and initialize global rdma resources
    initialize(node_rank, ip_addrs);

    // create memory for RDMA operations (with all nodes, we share the same buffer, which should not cause contention. CHECK THIS!)
    char *write_buf, *read_buf;
    write_buf = (char *)malloc(buf_size);
    read_buf = (char *)malloc(read_size);
    // create the resources
    res_vec.resize(num_nodes);
    for(int i = 0; i < num_nodes; ++i) {
        res_vec[i] = new resources(num_nodes - node_rank - 1, write_buf, read_buf, buf_size, read_size);
    }

    done_initializing.resize(num_threads, false);
    // create the threads
    for(long i = 0; i < num_threads; ++i) {
        pthread_create(&threads[i], NULL, post_reads, (void *)i);
    }
    // check to see that all threads have finished random number calls
    bool ready = false;
    while(ready == false) {
        ready = true;
        for(int i = 0; i < num_threads; ++i) {
            if(done_initializing[i] == false) {
                ready = false;
            }
        }
    }

    // // create the polling threads
    // for (long i = 0; i < num_threads; ++i) {
    //   pthread_create(&poll_threads[i], NULL, poll_reads, (void *) i);
    // }

    cout << "Starting experiments" << endl;

    // create structures for storing time
    struct timespec start_time;
    struct timespec end_time;
    long long int nanoseconds_elapsed;

    // note the current time
    clock_gettime(CLOCK_REALTIME, &start_time);
    // set the threads off
    send = true;

    // cout << start_time.tv_sec*1000000000 + start_time.tv_nsec <<endl;

    // main thread polls for completion. I think creating multiple threads to poll should not improve performance by much. CHECK THIS!
    for(long long int i = 0; i < num_threads * num_reads; ++i) {
        verbs_poll_completion();
    }

    // note the number of years elapsed
    clock_gettime(CLOCK_REALTIME, &end_time);
    nanoseconds_elapsed = (end_time.tv_sec - start_time.tv_sec) * 1000000000 + (end_time.tv_nsec - start_time.tv_nsec);

    cout << "Number of operations : " << num_threads * num_reads << endl;
    cout << "Time taken (in ns) : " << nanoseconds_elapsed << endl;

    // wait for threads to exit
    void *status;
    // pthread_attr_destroy (&attr);
    for(int i = 0; i < num_threads; ++i) {
        int rc = pthread_join(threads[i], &status);
        if(rc) {
            cout << "Error in thread join " << endl;
        }
    }
    // for (int i = 0; i < num_threads; ++i) {
    //   int rc = pthread_join(poll_threads[i], &status);
    //   if (rc) {
    //     cout << "Error in thread join " << endl;
    //   }
    // }
    cout << "All threads terminated. Exiting!!" << endl;

    // sync with every other node for grace exit
    for(int i = 0; i < num_nodes; ++i) {
        if(i == node_rank) {
            continue;
        }
        sync(i);
    }

    // free malloc()ed area
    free(write_buf);
    free(read_buf);
    // destroy the resources
    for(int i = 0; i < num_nodes; ++i) {
        delete(res_vec[i]);
    }
    verbs_destroy();

    return 0;
}